4. AT指令基础:AT指令格式、基本AT指令、常用测试指令、错误码解读
好,咱们进入第四讲。AT指令,说白了就是咱们MCU和NB-IoT模块之间的“通用语言”。你想想看,模块厂商那么多,华为的、移远的、中移的,每家底层实现都不一样。但为什么咱们换模块时,上层代码改动不大?
嗯,就是因为AT指令这个标准。我最早做2G模块时,就被AT指令“教育”过。当时以为发个AT就完事了,结果模块半天没反应,查了半天才发现是回车换行没加对。这种坑,我帮你们先踩了。
4.1 AT指令的基本格式
AT指令的格式其实很简单。但简单归简单,细节上容易翻车。咱们先看标准格式:
AT<command><CR>
这里<CR>是回车符,也就是\r,ASCII码是0x0D。注意,不是换行符\n!
我见过不少新手,在串口调试助手里直接敲AT然后点发送,结果模块没反应。为什么?因为很多调试工具默认只发\n,而模块只认\r。
AT指令的响应格式也很有规律。模块收到指令后,会返回:
<CR><LF><响应内容><CR><LF>
OK
<CR><LF>
或者出错时:
<CR><LF>
ERROR
<CR><LF>
你看,开头和结尾都有<CR><LF>。所以咱们在MCU端解析时,要按行读取,以\r\n作为行分隔符。这个细节,决定了你的驱动稳不稳定。
4.2 基本AT指令
基本指令是每个模块都支持的。咱们挑几个最常用的讲讲。
4.2.1 AT - 测试连接
最简单的指令,就是发一个AT\r。模块如果活着,会回复OK。
我个人习惯,在系统初始化时,先发3次AT指令做握手。如果3次都没回应,就判定模块异常,直接报错。这比傻等要高效得多。
发送: AT\r
接收: \r\nOK\r\n
4.2.2 ATE - 回显控制
ATE0关闭回显,ATE1开启回显。默认是ATE1,也就是你发什么,模块就原样返回什么。
调试阶段,开着回显方便看。但正式产品里,我建议关掉。为什么?因为回显会增加数据量,MCU解析起来也麻烦。我在一个低功耗项目里,就因为没关回显,多耗了不少电。
发送: ATE0\r
接收: \r\nOK\r\n
// 之后发指令,模块不再回显指令内容
4.2.3 AT+CGMI - 查询制造商
这个指令用来查模块是谁家生产的。比如移远的模块会返回Quectel。
我建议在产品初始化时,用这个指令做一次模块识别。万一产线装错了模块型号,你能第一时间发现。
发送: AT+CGMI\r
接收: \r\nQuectel\r\n\r\nOK\r\n
4.2.4 AT+CGMM - 查询模块型号
这个更细,能查到具体型号,比如BC95或BC26。不同型号的AT指令集可能有细微差别,查一下心里有底。
4.2.5 AT+CGMR - 查询固件版本
固件版本很重要。同一个模块,不同固件版本的行为可能不一样。我遇到过某个版本有bug,升级后才解决。所以,出货前一定要确认固件版本。
4.3 常用测试指令
测试指令,说白了就是“问模块你支持什么”。格式是AT+<cmd>=?。
4.3.1 AT+CGMI=? - 测试制造商查询指令
这个指令会返回模块支持的参数范围。不过对于CGMI这种只读指令,测试结果通常是OK。
4.3.2 AT+CSQ=? - 测试信号质量指令
这个很实用。它会告诉你信号强度值的范围,通常是0-31,加上99表示不可检测。
发送: AT+CSQ=?\r
接收: \r\n+CSQ: (0-31,99)\r\n\r\nOK\r\n
你看,返回值告诉你,第一个参数范围是0到31,或者99。这样你写代码时就知道,返回值在0-31之间是有效信号,99就是没信号。
4.3.3 AT+COPS=? - 测试运营商查询
这个指令会列出当前可用的运营商网络。返回格式比较复杂,但测试指令能帮你确认模块是否支持网络扫描。
4.4 错误码解读
模块不是每次都会乖乖回复OK的。出错时,它会返回ERROR,或者更详细的+CME ERROR: <err>。
4.4.1 通用错误
| 错误码 | 含义 | 常见原因 |
|---|---|---|
| 0 | 操作成功 | 无 |
| 1 | 未知错误 | 模块内部异常 |
| 3 | 操作不允许 | 当前状态不支持该操作 |
| 4 | 操作不支持 | 模块固件不支持该指令 |
| 13 | SIM卡故障 | SIM卡未插好或损坏 |
| 14 | SIM卡PIN码需要输入 | SIM卡开启了PIN码验证 |
| 16 | 位置更新失败 | 网络注册失败 |
| 22 | 未注册到网络 | 模块没找到网络 |
这些错误码,不同厂商可能略有差异。但前几个是通用的。我建议你在驱动里做一个错误码映射表,把数字转成可读的字符串,方便调试。
4.4.2 CME ERROR 的解析
当模块返回+CME ERROR: 13时,你就知道是SIM卡问题。我曾经在一个项目里,产品发到现场后频繁掉线。远程一看日志,全是+CME ERROR: 13。后来发现是SIM卡座接触不良,震动后就会断开。
所以,我写驱动时,会把+CME ERROR单独拎出来处理。一旦检测到,就记录错误码,并尝试恢复操作,比如重新插拔SIM卡(通过模块的复位引脚)。
4.4.3 超时错误
还有一种错误不是模块返回的,而是咱们MCU端检测到的——超时。模块没在规定时间内回复,就算超时。
我一般给AT指令设3秒超时。网络相关的指令,比如搜网、附着,可以放宽到10秒。为什么?因为网络操作本来就慢,你催它也没用。
4.5 实战中的小建议
最后,分享几个我踩过的坑:
- 回车换行别搞错:MCU串口发送时,确认发的是
\r,不是\n。很多新手在这里翻车。 - 响应要读完:模块返回的数据可能分多包到达。别收到一个
OK就以为完事了,后面可能还有数据。我习惯用超时+缓冲区的方式,收完一整条响应再解析。 - 错误码要记录:产品出问题时,错误日志是救命稻草。我在每个AT指令的响应里,都会把错误码和原始数据存下来,方便远程分析。
- 别信默认值:模块出厂设置不一定适合你的场景。我每次初始化,都会把关键参数重新设置一遍,比如波特率、回显、网络注册模式。这样即使模块被复位过,也能保证配置正确。
嗯,AT指令这块,说难不难,说简单也不简单。关键是把细节抠到位。下一讲,咱们会深入NB-IoT特有的AT指令,比如网络注册、信号查询、数据发送。到时候,这些基础就派上大用场了。