4、ELM327 AT指令集:AT指令格式、常用AT指令、初始化流程、响应解析

好,咱们进入正题。ELM327 这颗芯片,说白了就是 OBD 协议翻译官。你发一句「AT 咒语」给它,它帮你跟车上的 ECU 沟通。这一章,我就带你把这套咒语彻底搞明白。

4.1 AT指令格式:别小看这串字符

AT 指令的格式其实很简单:AT<命令><参数>,后面跟一个回车符(\r)。注意,是回车,不是换行。我见过不少新手用 \n 结尾,结果 ELM327 根本不搭理你。

标准格式:

AT<命令>[参数]\r

比如:ATZ\r 就是复位,ATE0\r 就是关闭回显。

这里有个坑:所有 AT 指令都是大写。虽然有些 ELM327 固件兼容小写,但我建议你统一用大写。我在项目里吃过亏——某批国产模块只认大写,小写直接返回 ?

4.2 常用AT指令:我的工具箱

ELM327 的 AT 指令有几十条,但日常用的就那七八条。我按使用频率给你排个序:

指令 含义 我的备注
ATZ 复位模块 初始化第一步,必用
ATE0 关闭回显 不关的话响应里会混着你的指令
ATL0 关闭换行符 方便程序解析,我习惯关掉
ATS0 关闭空格 响应更紧凑,解析省事
ATH1 开启响应头 能看到 ECU 的 ID,调试时有用
ATSP0 自动选择协议 省心,但速度慢,我一般手动指定

我的习惯:初始化时固定用 ATE0 + ATL0 + ATS0 三连。这样返回的数据干净得像白纸,解析起来特别爽。

4.3 初始化流程:从冷启动到就绪

每次上电,ELM327 都要走一套固定的初始化流程。我把它总结成 5 步:

  1. 发送 ATZ\r —— 复位模块,等待 ELM327 v1.5 之类的版本信息返回。
  2. 发送 ATE0\r —— 关闭回显。不关的话,后面每条指令的响应前面都会多出你刚发的指令。
  3. 发送 ATL0\r —— 关闭换行符。这样响应就是连续的一串,方便用 split() 处理。
  4. 发送 ATS0\r —— 关闭空格。比如 41 0C 1A 会变成 410C1A,解析效率高不少。
  5. 发送 ATSP0\r —— 自动协议检测。这一步最耗时,可能要等 2-3 秒。

注意:ATSP0 之后,ELM327 会尝试所有协议。如果车比较老,可能会卡在某个协议上。我建议你根据车型手动指定协议,比如 ATSP6 是 CAN 总线,大部分现代车都支持。

嗯,这里要特别说一下:每次发送指令后,一定要等模块返回 > 提示符。这个提示符表示模块空闲了,可以发下一条指令。我曾经写过一个脚本,没等提示符就连发三条指令,结果模块直接死机了。

4.4 响应解析:从原始数据到可用信息

ELM327 的响应格式其实很固定。咱们拿一个实际例子来说:

发送:010C\r
响应:41 0C 1A 0A>

这串东西怎么拆?我教你一个口诀:「去头、去尾、取中间」

  • 去头:去掉模式字节 41(表示响应的是模式 01 的请求)。
  • 去尾:去掉最后的 > 提示符。
  • 取中间:剩下的 0C 1A 0A 就是有效数据。

其中 0C 是 PID 号(发动机转速),1A 0A 是转速值。计算公式是:(0x1A * 256 + 0x0A) / 4,算出来就是 1670 RPM。

解析代码片段(Python):

def parse_rpm(raw_response):
    # 去掉提示符和空格
    clean = raw_response.replace('>', '').replace(' ', '')
    # 取后4个字符(转速占2字节)
    hex_str = clean[-4:]
    # 转成整数再除以4
    rpm = int(hex_str, 16) / 4
    return rpm

你想想看,如果没关空格和换行,这解析代码得多写好几行。所以我一直强调:初始化时把格式调干净,后面解析就省心

4.5 避坑指南:我踩过的雷

做 OBD 开发这些年,我在 AT 指令上栽过不少跟头。挑几个典型的说说:

  • 波特率不匹配:ELM327 默认 38400,但有些模块被改过。我建议初始化前先发几个 ATZ 试探一下,不行就换波特率。
  • 指令间不加延时:ELM327 处理指令需要时间,尤其是协议检测时。我一般每条指令后等 100ms 以上。
  • 忽略 NO DATA 响应:有些 PID 车不支持,会返回 NO DATA。别傻等,直接跳过。

我的调试技巧:用串口助手手动发指令,先确认每条指令的响应格式。等摸透了,再写代码自动化。这样能省一半的调试时间。

好了,AT 指令这块就这些。说白了就是「发什么、怎么发、怎么收」三个问题。你把这套流程跑通了,后面读取车速、水温、故障码什么的,都是换汤不换药。