NB-IoT模组AT指令调试与嵌入式接入实战
在窄带物联网(NB-IoT)终端开发中,模组(如移远BC26/BC95、中移M5311、华为Boudica)通过AT指令与MCU交互。相比WiFi/BLE,NB-IoT的入网附着、数据发送流程更长,且需处理PSM(省电模式)与eDRX。本文基于STM32 + BC26,走完从串口调试到数据上云的完整接入流程。
一、硬件连接与串口初始化
• MCU:STM32F103(UART1接模组,UART2接调试串口)
• BC26:VCC=3.3V(注意峰值电流可达300mA),SIM卡座(1.8V/3V自适应),天线(50Ω阻抗)
• 电平匹配:BC26为1.8V逻辑,STM32需加电平转换(如TXS0108或分压)
1.1 串口初始化(HAL库)
UART_HandleTypeDef huart1; // NB-IoT模组
#define NB_UART &huart1
void MX_USART1_UART_Init(void)
{
huart1.Instance = USART1;
huart1.Init.BaudRate = 9600; // BC26默认9600
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
HAL_UART_Init(&huart1);
}
二、AT指令交互基础函数
2.1 发送AT指令并等待响应
#include <string.h>
#include <stdio.h>
uint8_t nb_tx_buf[128];
uint8_t nb_rx_buf[256];
uint16_t rx_len = 0;
void NB_SendCmd(const char *cmd)
{
sprintf((char*)nb_tx_buf, "%s\r\n", cmd);
HAL_UART_Transmit(NB_UART, nb_tx_buf, strlen((char*)nb_tx_buf), 1000);
}
uint8_t NB_WaitResp(const char *expect, uint32_t timeout_ms)
{
uint32_t tick = HAL_GetTick();
rx_len = 0;
memset(nb_rx_buf, 0, sizeof(nb_rx_buf));
while (HAL_GetTick() - tick < timeout_ms) {
uint8_t ch;
if (HAL_UART_Receive(NB_UART, &ch, 1, 10) == HAL_OK) {
nb_rx_buf[rx_len++] = ch;
if (strstr((char*)nb_rx_buf, expect) != NULL)
return 1; // 成功
if (strstr((char*)nb_rx_buf, "ERROR") != NULL)
return 2; // 失败
}
}
return 0; // 超时
}
三、入网附着流程(关键步骤)
NB-IoT终端需依次完成搜网→附着→PDP激活,方可发送数据。
3.1 完整入网序列
void NB_Network_Attach(void)
{
// 1. 确认模组响应
NB_SendCmd("AT");
NB_WaitResp("OK", 2000);
// 2. 查询IMEI(可选)
NB_SendCmd("AT+CGSN=1");
NB_WaitResp("OK", 2000);
// 3. 设置APN(运营商提供)
NB_SendCmd("AT+CGDCONT=1,\"IP\",\"cmnbiot\""); // 中国移动
NB_WaitResp("OK", 3000);
// 4. 自动搜网附着(核心!)
NB_SendCmd("AT+CFUN=1"); // 全功能模式
NB_WaitResp("OK", 5000);
NB_SendCmd("AT+CGATT=1"); // 附着网络
NB_WaitResp("OK", 15000); // 首次附着需10~15秒
// 5. 检查附着状态
NB_SendCmd("AT+CGATT?");
NB_WaitResp("+CGATT:1", 5000); // 返回1表示附着成功
// 6. 激活PDP上下文
NB_SendCmd("AT+CEREG?"); // 注册状态
NB_WaitResp("+CEREG:0,1", 5000);
}
⚠️ 注意:NB-IoT入网速度慢,CGATT超时应设15~30秒,切勿用普通WiFi的3秒超时。
四、数据发送与接收(UDP示例)
NB-IoT通常使用UDP(非TCP)以减少连接开销,数据经运营商核心网转发到客户服务器。
4.1 建立UDP socket并发送
void NB_Send_UDP(const char *server_ip, uint16_t port,
const uint8_t *data, uint16_t len)
{
char cmd[128];
// 1. 创建socket
sprintf(cmd, "AT+NSOCR=\"DGRAM\",17,%d,1", port);
NB_SendCmd(cmd);
NB_WaitResp("OK", 5000);
// 2. 发送数据(hex格式)
sprintf(cmd, "AT+NSOST=0,\"%s\",%d,%d,\"", server_ip, port, len);
NB_SendCmd(cmd);
// 追加十六进制数据
for (int i = 0; i < len; i++) {
char hex[4];
sprintf(hex, "%02X", data[i]);
NB_SendCmd(hex);
}
NB_SendCmd("\"");
NB_WaitResp("OK", 10000);
}
4.2 接收数据(轮询)
void NB_Poll_Receive(void)
{
NB_SendCmd("AT+NSORF=0,512"); // 读最多512字节
if (NB_WaitResp("+NSONMI:", 5000)) {
// 解析收到的UDP数据
char *p = strstr((char*)nb_rx_buf, "+NSONMI:");
if (p) sscanf(p, "+NSONMI:%d,%d", &socket, &len);
}
}
五、低功耗配置(PSM/eDRX)
NB-IoT终端的核心优势是超低功耗。在非数据传输时段,模组进入PSM(省电模式),电流降至3~5μA。
void NB_Enable_PSM(void)
{
// 请求PSM:T3324(活动定时器)和T3412(周期性TAU)
NB_SendCmd("AT+CPSMS=1,,,\"01000111\",\"01000111\"");
// 参数解释:活动时间=10秒,TAU周期=约2小时
NB_WaitResp("OK", 5000);
}
实测功耗:
• 空闲(PSM):3.5 μA
• 数据发送(峰值):250 mA(约1~2秒)
• 平均(每小时上报一次):< 30 μA
六、常见故障排查
现象 原因 对策
AT无响应 波特率不匹配或模组未启动 检查VCC;发AT前先发+++退出数据模式
CGATT一直为0 SIM卡未插好/欠费/信号差 检查SIM卡座;用AT+CSQ查信号强度(>10可用)
UDP发送超时 服务器IP/端口不可达或防火墙 先用PC+NB-IoT模组直连验证服务器可达
入网后很快掉线 运营商APN配置错 联系运营商确认APN(cmnbiot/ctnb/unicom)
PSM不生效 核心网不支持或T3412过短 设T3412为01000111(约2小时)重试
七、结语
NB-IoT嵌入式接入的核心流程可概括为:AT握手 → 设APN → CGATT附着(耐心等15秒)→ UDP Socket发数 → 进PSM休眠。通过串口日志监控每一步响应,结合AT+CSQ与AT+CEREG?排查信号与注册状态,即可在STM32等MCU上稳定实现NB-IoT数据上云。





