解读乐鑫 AT 指令解析器,解锁你不知道的用法(全网唯一)

欢迎关注、星标 🌟 物联网学前班 公众号,畅享精彩内容

由于近期正好在做这个事情,所以今天就以乐鑫的 AT 指令为例,讲讲 AT 解析器设计有哪些事情,也算是个自己近期的学习总结了。

往期文章回顾

少有人关注的 AT 解析器

互联网上很多 xxx AT 指令使用教程,为何少有人关注 AT 解析器呢?

情况是这样的,绝大部分开发者是拿 AT 固件来开发产品的,只有很少一部分人是开发 AT 固件的。AT 固件通常是由芯片原厂、模组厂商来提供的,并且大多模组厂商也仅基于芯片原厂提供的 AT 解析器自定义 AT 指令。所以设计 AT 解析器的人就更少了,由于芯片原厂通常又不会提供 SDK 源码到互联网上,因此也基本上看不到 AT 解析器分析的文章。所以,互联网上关于 AT 的文章大都是某某模块都 AT 指令如何使用、怎么使用 MCU 控制 AT 指令模块。

总结:用 AT 固件都多,开发 AT 固件的少,设计 AT 解析器的人更少。

玩得好规则,才做得好产品

想要写一个好的 AT 解析器,或者你想解析 AT 指令的响应,你首先得知道 AT 指令的规则,清楚不同指令共性的地方和差异的地方。

关于 AT 指令语法格式可以参考我的这篇文章 AT 指令介绍

标准晦涩难懂,寻个实际产品

以乐鑫的 AT 解析器 esp-at 为例,说说 AT 解析器涉及的内容。

乐鑫的 AT 指令语法也是遵循 3GPP TS 27.007 语法规范。

AT 指令共性的内容

  1. 遵循 AT 规范,AT 开头,CRLF 结尾(考虑到有些平台只用 LF 的情况,CRLF 结尾还需要容错);
  2. 有五类 AT 指令(TEST, GET, SET, EXEC),这里不带加号算作是 basic 指令;
  3. 字符串类型使用双引号(”string”)括起来;
  4. 整数类型不实使用双引号;
  5. 特殊字符需要转译;
  6. 等号后面必须有一个参数(当然你的解析器也可以容忍等号后面无参数,作为默认参数填充,这样的话跟执行命令又有什么不同呢);
  7. 支持省略参数。

以上这些都是需要基于 AT 解析器实现。

AT 指令差异的内容

  1. 参数数量不定

  2. 参数类型不定

  3. 是否有 省略参数

  4. 参数内容不同

    • 是否使用来非 ascii 文本
    • 是否使用来特殊符号
    • 各种可能性的 AT 指令格式错误(人为原因)
    • 是否有需要 转译 的字符,转译规则是怎么样的

由于这些都是跟用户输入紧密相关的,解析器事先并不知道,要想解析这些情况下的文本,我们需要先定好规则,告诉解析器支持什么、不支持什么、特殊特性如何支持等,然后用户按照既定的规则输入正确的指令,同时解析器也应该能检测到错误格式的指令并报告错误。

以上 4 条里,最麻烦的就是第四条——用户可能使用任何可打印文本,另外最复杂的还是处理 待转译的字符

转译字符语法

乐鑫给出里下面几个需要转译的字符:

  • 反斜杠本身 \,转译用法 \\
  • 逗号 ,,转译用法 \,
  • 双引号 ",转译用法 \"
  • \<any>,意思是使用 \ 后面的所有字符 <any> 替代这里的 \

AT+CWSAP=<ssid>,<pwd>,<channel>,<ecn> 指令举例,改指令用于启动一个 AP 热点,举例如下:

AT+CWJAP="ssid_\\\"\,\"\<any>\<\"\,\\\123中文>", "12345678",6,0

上面这条指令会启动一个 AP 热点,ssid 名称将是 ssid_\","<any><",\123中文>,密码是 12345678,信道是 6,加密方式是 open。有硬件条件的用户可以验证下。

转译字符测试

关于中文等非 ascii 字符的支持

中文及其他非 ascii 字符的其他国家字符所使用的编码格式通常都是兼容 ascii 的,换句话说 ascii 的编码范围 0x0-0x7f 在 GBK、GB232、UTF-8 等编码里依旧是这个范围,不会有其他字符占用这个范围里的编号。因此,只要支持 ascii 字符的解析器,理论上是可以直接支持其他编码格式的文本的。

虽然解析器可以解析,但是你输入的 ssid 和 pwd 不一定被路由器正确识别!!!

为什么会这样?原因如下:

  1. 用户不知道 路由器 的 ssid 是什么编码格式,通常是 utf-8 编码

  2. 用户输入的 ssid 编码格式在不同的终端上也不一样,用户自己也不知道

  3. 如果用户输入的 ssid 编码和 路由器保存的 ssid 编码不一样,那么就连不上了嘛!

    如果你能连上,说明 Wi-Fi 模块帮你做连转码!

Wi-Fi 模块又是怎么匹配用户输入的 ssid 和 路由器保存的 ssid 编码呢?

这就要靠 Wi-Fi scan 了,Wi-Fi 扫描的时候会拿到 Wi-Fi 的 ssid 和加密类型等信息,模块就可以通过拿到的 ssid 探测到路由器 ssid 使用的编码格式,然后将用户输入的编码格式转成路由器格式,这样双方的编码格式就匹配了。

编码格式转化演示图

另外一个难点——指令和数据混合传输

除了对特殊格式的 AT 指令解析外,还有一个难点,就是使用 AT 串口进行数据传输(后面简称数传)。AT 指令模块串口的另外一端通常连接着一个 MCU,MCU 通过 AT 串口发送数据给 Wi-Fi 模块,Wi-Fi 模块再发送到网络上;Wi-Fi 模块收到数据后,也是通过 AT 串口发送数据到 MCU。通常,还不仅仅存在一路数据传输,还会有多路数据传输(比如两路 TCP),这个时候怎么管控他们使用 AT 串口呢,以及什么时候发送数据,又什么时候发送 AT 指令呢?

在 MCU 通过 AT 串口给 Wi-Fi 模块发送数据的时候,乐鑫有两种数传模式:normal 模式 和 passthrough 透传模式。透传模式只支持单个连接。

  • 在 normal 模式下,MCU 需要先告诉对端 Wi-Fi 模块我要发多少数据,然后再发送数据;

    在 normal 模式下 MCU 使用 AT+CIPSEND=<len> 指令,告诉 Wi-Fi 模块我要发 len 字节数据,请进入 数据传输模式,我这个指令后就发数据了。

  • 在 透传 模式下,每 20ms 或者每 2048 字节发送一次,哪个方式先到用哪个方式。

    在透传模式下 MCU 使用 AT+CIPSEND 执行指令,告诉 Wi-Fi 模块我要发数据了,请进入 数据透传模式,我这个指令后就发数据了。

    AT 标准规定从数据透传模式切换到 AT 指令模式需要单独发送一包 +++ 的数据,并在紧接着的 1s 内不发送任何内容,这样 AT 解析器就会从数据透传模式切换到 AT 指令模式

在多连接的时候,Wi-Fi 模块还要管理多路连接,乐鑫 提供以下指令来处理:

  1. 使用 CIPMUX 设置是否支持多路连接
  2. 使用 CIPSTART 创建 socket 连接
  3. 使用 CIPSEND 发送 socket 数据(也就是我说的数传)
  4. 支持主动下发数据到对端,也支持被动读取,主动下发使用 +IPD;被动读取使用 CIPRECVLEN 和 CIPRECVDATA。
  5. 使用 CIPCLOSE 关闭连接
  6. 使用 CIPMODE 配置数传模式是 normal 还是 passthrough(透传)模式

在有多路 socket 链接的时候,数传变得会相对麻烦些,因为多路 socket 可能都在接收数据,每一个 sock 都需要将收到的数据通过 AT 串口传送到对端,串口端还要保证两路数据的独立完整,不能混到一起。这个时候,应该每一路连接都会有一个 receive buff 用来缓存收到的数据(乐鑫默认的 buff 大小是 5744 字节)。所有的 socket 连接可以共用一个 send buff,因为同一时刻只有一个连接使用 AT 串口。

其他

简单分析了下乐鑫的 AT 指令解析器所做的事情,最近也尝试写了个 AT 指令解析器,感触是非常麻烦,关键是要做很多测试,来检查是否有逻辑问题,各种转译情况的支持问题。

我看到圈里很多朋友尝试自己写了 console 命令行工具,有朋友感兴趣的话,不妨尝试实现一个 AT 解析器。


如有错误,欢迎指正!


物联网      AT 指令 乐鑫 AT 解析器

本博客所有文章除特别声明外,均采用 CC BY-SA 3.0协议 。转载请注明出处!

 目录

微信公众号:物联网学前班