can327: 用于 Linux SocketCAN 的 ELM327 驱动程序

作者

Max Staudt <max@enpas.org>

动机

此驱动程序旨在降低对 CAN 总线感兴趣的黑客的初始成本。

CAN 适配器价格昂贵,数量稀少。ELM327 接口价格便宜且数量充足。让我们使用 ELM327 作为 CAN 适配器。

简介

此驱动程序致力于将大量的基于 ELM327 的 OBD 接口转换为功能齐全(尽可能)的 CAN 接口。

由于 ELM327 从来就不是一个独立的 CAN 控制器,因此驱动程序必须尽可能快地在其模式之间切换,以模拟全双工操作。

因此,can327 是一个尽力而为的驱动程序。但是,这足以实现简单的请求-响应协议(例如 OBD II),并监控总线上的广播消息(例如在车辆中)。

大多数 ELM327 以不引人注目的串行设备的形式出现,通过 USB 或蓝牙连接。驱动程序本身无法识别它们,因此用户需要以 TTY 行规(类似于 PPP、SLIP、slcan 等)的形式附加它。

此驱动程序适用于 ELM327 1.4b 及更高版本,有关旧控制器和克隆版本的已知限制,请参见下文。

数据表

官方数据表可在 ELM electronics 的主页上找到

如何附加行规

每个 ELM327 芯片都出厂设置为以 38400 波特/秒、8 个数据位、无奇偶校验、1 个停止位的串行设置运行。

如果您保留了此默认配置,则可以在命令提示符下附加行规,如下所示

sudo ldattach \
       --debug \
       --speed 38400 \
       --eightbits \
       --noparity \
       --onestopbit \
       --iflag -ICRNL,INLCR,-IXOFF \
       30 \
       /dev/ttyUSB0

要更改 ELM327 的串行设置,请参考其数据表。这需要在附加行规之前完成。

一旦附加了 ldisc,CAN 接口将开始未配置。在启动它之前设置速度

# The interface needs to be down to change parameters
sudo ip link set can0 down
sudo ip link set can0 type can bitrate 500000
sudo ip link set can0 up

500000 位/秒是 OBD-II 诊断的常用速率。如果您直接连接到汽车的 OBD 端口,这是大多数汽车(但不是全部!)期望的速度。

在此之后,您可以像往常一样使用 candump、cansniffer 等。

如何检查控制器版本

使用终端程序连接到控制器。

发出 “AT WS” 命令后,控制器将响应其版本

>AT WS


ELM327 v1.4b

>

请注意,克隆版本可能会声称是它们喜欢的任何版本。这并不表示它们的实际功能集。

通信示例

这是关于如何与 ELM327 通信的简短而不完整的介绍。它在这里是为了指导理解控制器和驱动程序的限制(如下所列)以及手动测试。

ELM327 有两种模式

  • 命令模式

  • 接收模式

在命令模式下,它期望每行一个命令,以 CR 结尾。默认情况下,提示符为 “>”,之后可以输入命令

>ATE1
OK
>

驱动程序中的 init 脚本会关闭一些仅在芯片最初的 OBD 场景中有意义的配置选项,这些选项实际上阻碍了 can327 的使用。

当命令未被识别时,例如被旧版本的 ELM327 识别时,会打印问号作为响应,而不是 OK

>ATUNKNOWN
?
>

目前,can327 不会评估此响应。有关详细信息,请参阅下面关于已知限制的部分。

当要发送 CAN 帧时,将配置目标地址,然后将帧作为包含数据十六进制转储的命令发送

>ATSH123
OK
>DEADBEEF12345678
OK
>

上述交互发送具有(11 位)CAN ID 0x123 的 SFF 帧 “DE AD BE EF 12 34 56 78”。为此,必须将控制器配置为 SFF 发送模式(使用 “AT PB”,请参阅代码或数据表)。

一旦发送了帧并且等待回复模式开启(ATR1,在 listen-only=off 上配置),或者当回复超时到期并且驱动程序将控制器设置为监控模式(ATMA)时,ELM327 将为每个接收到的 CAN 帧发送一行,包括 CAN ID、DLC 和数据

123 8 DEADBEEF12345678

对于 EFF(29 位)CAN 帧,地址格式略有不同,can327 使用它来区分两者

12 34 56 78 8 DEADBEEF12345678

ELM327 将接收 SFF 和 EFF 帧 - 当前 CAN 配置(ATPB)无关紧要。

如果 ELM327 的内部 UART 发送缓冲区已满,它将中止监控模式,打印 “BUFFER FULL” 并返回到命令模式。请注意,在这种情况下,与其他的错误消息不同,错误消息可能与最后(通常不完整的)数据帧出现在同一行中

12 34 56 78 8 DEADBEEF123 BUFFER FULL

控制器的已知限制

  • 克隆设备(“v1.5” 及其他)

    不支持发送 RTR 帧,并且会被静默丢弃。

    接收带有 DLC 8 的 RTR 将显示为具有最后接收到的帧的 DLC 和有效负载的常规帧。

    不支持 “AT CSM”(CAN 静默监控,即不发送 CAN ACK),并且硬编码为 ON。因此,在侦听时不会确认帧:“AT MA”(监控全部)将始终是 “静默的”。但是,在发送帧后立即,ELM327 将处于“接收回复”模式,在这种模式下,它确认任何接收到的帧。一旦总线静默,或者发生错误(例如 BUFFER FULL),或者接收回复超时结束,ELM327 将自行结束回复接收模式,can327 将返回到 “AT MA”,以便继续监控总线。

    其他限制可能适用,具体取决于克隆版本及其固件的质量。

  • 所有版本

    不支持全双工操作。驱动程序将尽可能快地在输入/输出模式之间切换。

    无法设置传出 RTR 帧的长度。实际上,某些克隆版本(经过测试,识别为 “v1.5”)根本无法发送 RTR 帧。

    我们无法获得有关 CAN 错误的实时通知。虽然有一个命令(AT CS)来检索一些基本统计信息,但我们不会轮询它,因为它会迫使我们中断接收模式。

  • 1.4b 之前的版本

    这些版本在监控模式(AT MA)下不会发送 CAN ACK。但是,它们会在发送帧后立即等待回复时发送 ACK。驱动程序会最大化此时间,以使控制器尽可能有用。

    从 1.4b 版本开始,ELM327 支持 “AT CSM” 命令,“仅侦听” CAN 选项将生效。

  • 1.4 之前的版本

    这些芯片不支持 “AT PB” 命令,因此无法即时更改比特率或 SFF/EFF 模式。这必须由用户在附加行规之前进行编程。有关详细信息,请参阅数据表。

  • 1.3 之前的版本

    这些芯片完全不能与 can327 一起使用。它们不支持 “AT D1” 命令,该命令对于避免传入数据上的解析冲突以及区分 RTR 帧长度是必要的。

    具体来说,这允许轻松区分 SFF 和 EFF 帧,并检查帧是否完整。虽然可以从 ELM327 发送给我们的行的长度推断类型和长度,但是当 ELM327 的 UART 输出缓冲区溢出时,此方法会失败。它可能会在行中间中止发送,然后会被误认为是其他内容。

驱动程序的已知限制

  • 无 8/7 定时。

    ELM327 只能设置 500000/n 形式的 CAN 比特率,其中 n 是整数除数。但是,有一个例外:使用单独的标志,它可以将速度设置为除数指示的速度的 8/7。目前尚未实现此模式。

  • 不评估命令响应。

    当命令被理解时,ELM327 会回复 OK,当命令不被理解时,会回复 ?。驱动程序目前不会检查这个,而是简单地假设芯片理解每个命令。驱动程序的构建方式是即使出现问题,功能也能优雅地降级。请参阅关于控制器已知限制的部分。

  • 未使用硬件 CAN ID 过滤

    在 CAN 总线负载较重的情况下,ELM327 的 UART 发送缓冲区很容易溢出,导致出现 “BUFFER FULL” 消息。使用通过 “AT CF xxx” 和 “AT CM xxx” 提供的硬件过滤器会有所帮助,但是 SocketCAN 目前不提供使用此类硬件功能的机制。

选择此配置的原因

AT E1

打开回显

我们需要这个来可靠地获取提示符。

AT S1

打开空格

我们需要这个来区分接收到的 11 位/29 位 CAN 地址。

注意:我们通常可以使用行长度(奇数/偶数)来做到这一点,但是如果行没有完全传输到主机(BUFFER FULL),则会失败。

AT D1

打开 DLC

我们需要这个来告知 RTR 帧的“长度”。

关于 CAN 总线终端的说明

你的适配器可能焊接有用于终止总线的电阻。当它插入 OBD-II 插座时,这是正确的,但在尝试接入现有 CAN 总线的中间时,则没有帮助。

如果连接适配器后通信不起作用,请检查其 PCB 上的终端电阻,并尝试将其移除。