4、AT指令集详解:基础AT指令、3GPP标准指令、TCP/IP协议栈指令、MQTT/HTTP扩展指令、自定义指令开发
AT指令,说白了就是咱们工程师和模组对话的「通用语言」。不管你用哪个厂家的模组,只要它支持AT,你就能用一串简单的字符串让它干活——连网、发数据、读状态。
我刚开始做蜂窝项目时,总觉得AT指令太简单,不就是发个字符串嘛。直到有一次,一个设备在产线上死活连不上服务器,查了三天才发现是AT指令的换行符没对齐。嗯,从那以后我再也不敢小看这些「小字符」了。
核心认知:AT指令集是模组与主控MCU之间的「通信协议」。你发一条指令,模组回一条响应。就这么简单,但细节决定成败。
4.1 基础AT指令——模组的「开机自检」
基础AT指令是所有模组都支持的「最小指令集」。说白了,就是用来确认模组活着没、SIM卡插了没、信号好不好。
我个人习惯,拿到一个新模组,第一件事就是发一条 AT。如果它回 OK,说明串口通了,模组在跑。如果没反应——先检查波特率,再检查电平匹配。我曾经被一个3.3V和1.8V的电平不匹配坑过,串口线焊对了,但电平不对,模组就是不搭理你。
| 指令 | 功能 | 典型响应 | 说明 |
|---|---|---|---|
AT |
测试连接 | OK |
模组活着,串口正常 |
AT+CPIN? |
查询SIM卡状态 | +CPIN: READY |
SIM卡已就绪 |
AT+CSQ |
查询信号强度 | +CSQ: 20,99 |
20对应约-75dBm,还行 |
AT+CGMI |
查询模组厂商 | Quectel |
确认模组型号 |
AT+CGMR |
查询固件版本 | Revision: BG96MAR02A08M2G |
用于版本管理 |
我的小技巧:在产线测试时,我会写一个「三连测」脚本:先发 AT 确认模组活着,再发 AT+CPIN? 确认SIM卡,最后发 AT+CSQ 看信号。三个都过,基本可以放行。这个流程我用了好几年,省了不少返工。
4.2 3GPP标准指令——和基站「握手」
3GPP标准指令是蜂窝通信的「国际通用语」。不管你是用2G、4G还是NB-IoT,这些指令的格式和含义都是统一的。你想想看,如果每个厂家的模组都用不同的指令去注册网络,那工程师不得疯掉?
我遇到过最典型的问题:设备在实验室跑得好好的,一到现场就连不上网。查了半天,发现是 AT+CREG? 返回的是 0,2——模组正在搜索网络,但一直搜不到。后来发现是天线没拧紧。嗯,这种低级错误,谁还没犯过呢?
| 指令 | 功能 | 典型响应 | 避坑点 |
|---|---|---|---|
AT+CREG? |
查询网络注册状态 | +CREG: 0,1 |
1表示已注册,2表示搜索中 |
AT+CGATT? |
查询GPRS附着状态 | +CGATT: 1 |
1表示已附着,0表示未附着 |
AT+CGPADDR |
查询IP地址 | +CGPADDR:1,10.168.1.100 |
拿到IP才能走TCP/IP |
AT+COPS? |
查询当前运营商 | +COPS: 0,0,"CHINA MOBILE" |
确认是否连对了运营商 |
⚠️ 重要提醒:很多新手会忽略 AT+CGATT? 的返回值。模组注册了网络(CREG=1),不代表它已经附着到GPRS(CGATT=1)。这两个状态必须都OK,才能进行数据传输。我曾经见过一个项目,CREG一直为1,但CGATT始终为0,结果设备「在线但发不了数据」——这种问题最难排查。
4.3 TCP/IP协议栈指令——让数据「跑起来」
基础指令和3GPP指令搞定了,模组已经连上网络了。但怎么把数据发出去?这就需要TCP/IP协议栈指令了。说白了,就是让模组帮你完成Socket连接、数据收发这些脏活累活。
我个人习惯用移远模组的 AT+QIOPEN 系列指令。不同厂家的指令格式略有差异,但逻辑是一样的:先建连接,再发数据,最后关连接。
// TCP客户端连接示例(移远模组)
AT+QIOPEN="TCP","192.168.1.100",8080
// 响应:CONNECT OK
// 发送数据
AT+QISEND=0
> Hello, this is my IoT device!
// 响应:SEND OK
// 接收数据(URC上报)
+QIURC: "recv",0,5
// 表示从连接0收到5字节数据
// 关闭连接
AT+QICLOSE=0
// 响应:CLOSE OK
避坑指南:我曾经在发送数据时,忘了在数据末尾加换行符。模组一直等,超时后才返回 SEND FAIL。后来我养成了习惯:发完数据后,一定用 0x1A(Ctrl+Z)结束。嗯,这个坑踩过一次就够了。
4.4 MQTT/HTTP扩展指令——上云「快车道」
TCP/IP是底层,MQTT和HTTP是上层协议。现在做物联网,大部分场景都是直接上MQTT或HTTP。模组厂商也聪明,直接把协议栈集成到固件里,你发几条AT指令就能完成连接、订阅、发布。
我最近做的一个智慧农业项目,就是用MQTT AT指令直接连阿里云。整个过程不到20行AT指令,比用MCU自己跑MQTT库省了至少一半的代码量。
// MQTT连接示例(移远模组)
AT+QMTCFG="aliauth",0,"productKey","deviceName","deviceSecret"
// 配置阿里云三元组
AT+QMTOPEN=0,"iot-as-mqtt.cn-shanghai.aliyuncs.com",1883
// 打开MQTT连接
// 响应:+QMTOPEN: 0,0
AT+QMTCONN=0,"clientId"
// 建立MQTT连接
// 响应:+QMTCONN: 0,0,0
AT+QMTSUB=0,1,"/topic/test",0
// 订阅主题
// 响应:+QMTSUB: 0,1,0,0
AT+QMTPUB=0,0,0,0,"/topic/test","Hello MQTT"
// 发布消息
// 响应:+QMTPUB: 0,0,0
| 协议 | 典型指令前缀 | 适用场景 | 注意事项 |
|---|---|---|---|
| MQTT | AT+QMTOPEN / AT+QMTCONN |
实时数据上报、远程控制 | 注意QoS等级,QoS1会重发 |
| HTTP | AT+QHTTPURL / AT+QHTTPGET |
非实时数据、OTA升级 | 注意URL长度限制 |
| CoAP | AT+QCOAPOPEN |
NB-IoT低功耗场景 | UDP协议,不保证可靠 |
⚠️ 注意:MQTT的保活心跳(Keep Alive)是个容易忽略的点。如果心跳间隔太长,服务器会断开连接;太短又浪费功耗。我一般设60秒,配合模组的PSM省电模式,效果不错。另外,记得在断线后自动重连——我见过太多设备因为网络抖动掉线后「失联」的案例。
4.5 自定义指令开发——让模组「听懂你的话」
标准AT指令能覆盖大部分场景,但总有一些特殊需求——比如读取某个私有传感器的数据、执行特定的加密算法、或者对接某个非标协议。这时候,就需要自定义指令了。
我做过一个项目,客户要求模组直接读取一个I2C温湿度传感器。标准AT指令肯定不支持。怎么办?让模组厂商帮忙开发自定义指令。说白了,就是让模组的固件里多一段代码,注册一个新的AT指令处理函数。
// 伪代码:自定义AT指令处理流程
// 1. 注册指令
AT_REGISTER("AT+TEMP", temp_handler);
// 2. 实现处理函数
int temp_handler(char *params, char *response) {
int temp = read_i2c_temperature(); // 读取I2C传感器
sprintf(response, "+TEMP: %d", temp);
return AT_OK;
}
// 3. 使用效果
// 发:AT+TEMP
// 收:+TEMP: 25
我的经验:自定义指令开发,一般有两种方式:一是找模组厂商定制固件(适合大批量),二是在MCU端做指令转发(适合小批量)。我个人更推荐第二种——把自定义指令的逻辑放在MCU上,模组只做透传。这样模组固件不用动,升级也方便。我曾经用这种方式,在MCU上实现了 AT+GPS 指令,模组收到后通过串口转发给GPS模块,再把结果返回。灵活得很。
4.6 指令调试与排错——实战中的「救命稻草」
指令写好了,但设备就是不按预期工作。怎么办?别慌,我总结了一套「AT指令排错三板斧」:
- 看响应码:模组返回
ERROR时,后面通常跟着+CME ERROR:或+CMS ERROR:错误码。查一下模组手册,基本能定位问题。 - 开回显:发
ATE1打开回显,看看你发的指令模组到底收到了什么。我曾经发现MCU发的指令多了个空格,模组直接不认。 - 抓日志:用串口工具把模组的所有输出都抓下来。很多时候,问题就藏在那些你忽略的URC上报里。
最后说一句:AT指令不难,难的是细心。每个换行符、每个逗号、每个引号,都可能成为你调试一整天的问题根源。但只要你掌握了这五类指令——基础、3GPP、TCP/IP、MQTT/HTTP、自定义——你就能驾驭市面上90%的蜂窝模组。