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指令必须以回车符(\r)结尾。部分模块也支持回车换行(\r\n),但最保险的做法是只发\r。我在项目中统一用\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 - 查询模块型号

这个更细,能查到具体型号,比如BC95BC26。不同型号的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=? - 测试运营商查询

这个指令会列出当前可用的运营商网络。返回格式比较复杂,但测试指令能帮你确认模块是否支持网络扫描。

小技巧:测试指令是调试时的好帮手。如果某个AT指令不按预期工作,先用测试指令看看它支持什么参数。我曾经花了两小时查一个配置问题,最后发现是参数范围搞错了。

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秒。为什么?因为网络操作本来就慢,你催它也没用。

核心要点:AT指令的解析,核心就是三件事:发指令、等响应、判结果。响应可能是OK、ERROR、+CME ERROR,或者带数据的正常响应。写代码时,一定要用状态机来处理,别用阻塞延时。否则,一个指令卡住,整个系统就瘫痪了。

4.5 实战中的小建议

最后,分享几个我踩过的坑:

  • 回车换行别搞错:MCU串口发送时,确认发的是\r,不是\n。很多新手在这里翻车。
  • 响应要读完:模块返回的数据可能分多包到达。别收到一个OK就以为完事了,后面可能还有数据。我习惯用超时+缓冲区的方式,收完一整条响应再解析。
  • 错误码要记录:产品出问题时,错误日志是救命稻草。我在每个AT指令的响应里,都会把错误码和原始数据存下来,方便远程分析。
  • 别信默认值:模块出厂设置不一定适合你的场景。我每次初始化,都会把关键参数重新设置一遍,比如波特率、回显、网络注册模式。这样即使模块被复位过,也能保证配置正确。

嗯,AT指令这块,说难不难,说简单也不简单。关键是把细节抠到位。下一讲,咱们会深入NB-IoT特有的AT指令,比如网络注册、信号查询、数据发送。到时候,这些基础就派上大用场了。