3、AT指令集核心:常用AT指令详解与超时处理
AT指令,说白了就是咱们工程师跟模组对话的“黑话”。模组能不能上网、信号好不好、有没有注册上网络,全得靠这几条指令来问。我刚开始做蜂窝项目那会儿,总觉得AT指令就是发几条字符串,没啥技术含量。直到有一次产品在客户现场死活连不上网,我拿着串口工具一条一条地试,才发现自己对这几个指令的理解太浅了。
今天咱们就把最常用的四条指令掰开揉碎讲清楚。你想想看,这四条指令搞明白了,模组80%的网络状态问题你都能自己搞定。
3.1 AT+CSQ:信号质量的“体温计”
这条指令,我习惯叫它“信号体温计”。你发一条AT+CSQ,模组就会告诉你当前的信号强度。
AT+CSQ
+CSQ: 19,99
OK
返回的格式是+CSQ: <rssi>, <ber>。第一个值是接收信号强度指示(RSSI),范围0-31,数值越大信号越强。第二个值是误码率(BER),99表示不报告。
RSSI值对照表(我常用的判断标准)
| RSSI值 | 信号强度 | 实际体验 |
|---|---|---|
| 0-9 | 极差 | 基本没法用,掉线频繁 |
| 10-14 | 弱 | 能连上,但速率不稳定 |
| 15-19 | 中等 | 日常可用,大部分场景够用 |
| 20-25 | 良好 | 速率稳定,体验不错 |
| 26-31 | 极好 | 信号满格,接近理论速率 |
| 99 | 无效 | 模组没检测到信号,检查天线 |
我的经验:RSSI值低于10的时候,别急着怀疑模组坏了。先看看天线有没有拧紧,或者换个位置试试。我在一个工厂项目里遇到过,RSSI一直是0,折腾了半天发现是天线座虚焊了。
3.2 AT+CREG:网络注册的“身份证”
信号好不代表能上网。你得确认模组有没有注册到运营商的网络。这时候就用AT+CREG。
AT+CREG?
+CREG: 0,1
OK
返回格式+CREG: <n>, <stat>。n是设置,一般用0或1。stat才是关键:
| stat值 | 含义 | 说明 |
|---|---|---|
| 0 | 未注册 | 模组正在找网,或者根本找不到 |
| 1 | 已注册,本地网 | 正常状态,可以上网 |
| 2 | 未注册,正在搜索 | 模组在努力找网,等一会儿再查 |
| 3 | 注册被拒绝 | 运营商不让你入网,检查SIM卡和资费 |
| 4 | 未知 | 一般不会出现,出现了就重启模组 |
| 5 | 已注册,漫游 | 在外地或者用了别家运营商的信号 |
注意:stat=3(注册被拒绝)是个大坑。我曾经有个客户,SIM卡插上去一直返回3,换了三张卡都不行。最后发现是SIM卡的APN没开通物联网业务。所以遇到stat=3,先找运营商确认卡的状态。
3.3 AT+CGATT:PS域的“开关”
注册上网络了,但你还得确认PS域(分组交换域)是不是附着上了。说白了,就是模组有没有准备好走数据流量。
AT+CGATT?
+CGATT: 1
OK
返回1表示已附着,0表示未附着。如果返回0,就算信号再好、注册状态再正常,你也发不了数据。
为什么会这样?我遇到过一种情况:模组刚上电,CSQ显示20,CREG也返回1,但CGATT就是0。等了大概10秒钟再查,变成1了。嗯,这里要注意——模组启动有个过程,别一上电就急着发数据。
建议:在代码里加一个循环,每隔2秒查一次CGATT,直到返回1或者超时。超时时间我一般设30秒,够用了。
3.4 AT+CGDCONT:PDP上下文的“配置单”
最后一步,配置PDP上下文。你可以把它理解成模组上网的“配置单”——用什么协议、连哪个APN、需不需要用户名密码。
AT+CGDCONT=1,"IP","CMNET"
OK
参数说明:
- cid(1):上下文ID,一般用1就行
- PDP类型("IP"):IPv4就用IP,IPv4/v6双栈用IPV4V6
- APN("CMNET"):接入点名称,移动是CMNET,联通是3GNET,电信是CTNET
查一下当前配置:
AT+CGDCONT?
+CGDCONT: 1,"IP","CMNET","0.0.0.0",0,0,0,0
OK
关键点:APN必须跟SIM卡匹配。我见过有人用移动的卡配了联通的APN,结果CGATT死活上不去。APN错了,模组就不知道从哪个门出去上网。
3.5 指令超时处理:别让模组“卡死”你
AT指令不是发出去就一定有回应的。模组有时候忙不过来,或者信号不好,指令就卡住了。如果不做超时处理,你的程序可能永远等在那条指令上。
我个人的做法是这样的:
- 每条指令都设超时:普通指令设3秒,网络相关指令(如AT+CGATT)设10-15秒
- 超时后先发“中断”:发一个0x1B(ESC字符),让模组退出当前状态
- 再发AT测试:发一条
AT,看模组还活着没 - 连续超时则重启:如果3次AT都没回应,直接硬件复位
// 伪代码示例
bool sendATCommand(const char* cmd, int timeout_ms) {
// 清空接收缓冲区
// 发送指令
// 等待响应,同时计时
while (time_elapsed < timeout_ms) {
if (收到 "OK" 或 "ERROR") {
return true;
}
delay(100);
}
// 超时处理
sendByte(0x1B); // 发送ESC中断
delay(500);
// 发AT测试模组状态
if (!sendATCommand("AT", 2000)) {
// 模组可能挂了,执行硬件复位
hardwareReset();
}
return false;
}
血的教训:有一次我在做远程升级功能,模组正在下载固件,这时候我发了一条AT+CSQ。结果模组没理我,程序就卡在等待响应的循环里了。下载任务也断了,升级失败。从那以后,所有AT指令我都加了超时保护。
3.6 知识体系总览
下面这张图,把四条指令的关系和排查流程串起来了。你照着这个顺序查,90%的网络问题都能定位到。
这张图从左到右、从上到下,就是标准的排查流程。先看信号,再看注册,然后确认PS域附着,最后配好APN。每一步都卡住了,就回到上一步找原因。
最后说一句:AT指令看着简单,但实际项目里坑不少。我建议你在开发阶段就把这些指令的返回值和超时处理都做成日志,出了问题翻日志比现场抓串口快得多。