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。因此,帧在监听时不会被 ACK:“AT MA”(监视所有)将始终是“静默”的。但是,在发送帧后立即,ELM327 将处于“接收回复”模式,在这种模式下,它 ACK 任何接收到的帧。一旦总线静默,或者发生错误(例如 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 上的终端电阻,然后尝试将其移除。