
CAN总线本身已经在很多地方使用了,尽管对此区域没有限制,但我对它在汽车中的使用很感兴趣。 特别是几年前,这个机会出现了。 我查看了一般规格-似乎没有什么特别复杂的。 我查看了Internet上的程序-我不喜欢任何程序,每个程序都缺少当时对我来说必要的东西。 我会重新发明我的自行车。 我把我的CAN嗅探器进一步削减了。
CAN总线
详细描述CAN总线的技术细节是一份文档。 在本文中,知道它就足够了:
- 具有两线物理连接
- 有各种数据速率
- 现成的芯片,甚至是带有焊接零件的现成板都已经可以连接
浏览了一家来自中东王国的著名在线商店的页面后,我订购了几种不同的屏蔽罩选项,然后研究了汽车中电信号的功能。 试验车是带有第127发动机的LADA Kalina Cross和一个ITELMA M74.5 CAN电子控制单元。
我连接到OBD诊断连接器(引脚6和14),并查看那里的示波器。 转动点火钥匙后,振幅最高为2.5 V的小包开始运行,我停在示波器上,看着小包。
起始和停止位很明显,数据包中有一些数据。 那时我已经知道,数据传输速率有望达到500 kbit / s,这是马达CAN总线最频繁的传输速率。 数据包持续时间约为230μs,在数据包发送之前,数据传输会出现较大的暂停。 我按比例缩放时间,看到三个数据包在它们之间暂停。
如果我们加上数据传输的持续时间和数据包之间的暂停,事实证明,一件数据的传输大约需要1毫秒。
我为什么要推断所有这些? 问题是完全实际的:是否有足够的串行端口速度来传输所有数据? 根据我们所看到的,我们可以得出结论,数据包内部的速度达到了500 kbit / s,大约需要传输时间的四分之一。 因此,平均传输速率将降低四倍。 那时,我还没有进行Arduino串行接口速度测试,因此展望未来,我可以说,即使使用最普通的Serial to USB CH340转换器,2 Mbps的速度也能稳定地工作。
Arduino上的CAN扫描仪
经典Arduino UNO的第一个到货盾牌。 是的,它的成本比较小的同类产品高得多,但它拥有您所需的一切,甚至有两个按钮。
我是和他一起开始所有实验的。 用该屏蔽罩和液晶两线屏组装一个简单的电路。 目的是在屏幕上显示至少一些数据。 我对用于在Arduino上使用CAN总线的各种库进行了排序(我马上会说Seeed Studio使用mcp_can.h标头文件将正确且有效的库称为CAN-BUS Shield,并更改了16 MHz屏蔽(最初是8 MHz)上的石英谐振器-没有数据。
屏蔽板上安装了两个微电路:CAN总线控制器MCP2515和CAN总线驱动器TJA1050。 在阅读了文档和各种论坛之后,我决定将TJA1050更改为更具规范的驱动程序MCP2551,然后出现数据。 也许TJA1050最初是有故障的,因为很难用两根线连接它,另外,我使用OBD和DB9连接器进行连接。
在几个小时内,编写了一个简单的CAN扫描仪,该扫描仪在LCD上显示了所捕获数据包的编号,其ID以及该数据包的最多8个字节的数据。
这是在盾牌上的按钮派上用场的地方,我用它在显示的包裹数量之间切换。
关于按钮通常,这些按钮在很多事情上派上用场。 正是与他们一起,我开始测试汽车某些设备的控制。
奠定了开始,我们必须继续进行更有趣的实现。
Arduino上的CAN嗅探器
任务很简单:
- 接受来自CAN总线的数据包
- 我们将接收到的数据放入我们的结构中
- 通过串口发送结构
我发现前两个任务没有任何问题。 该库在接收下一个数据包时提供了一个中断,并提供了方便的数据接收功能。 但是我决定通过CyberLib库将数据发送到计算机,这消除了整个Arduino平台的一些开销,因此您可以稍微减轻处理器的负担来处理数据。 后来,该图书馆不得不被废弃。
为了在计算机端正确处理要发送的数据,在每个下一个数据之前在流中插入四个字节的前缀0xAA55AA55(出于某种原因,这些字节被记住是DOS引导扇区的最后两个字节,只是它们的顺序不同)。 逻辑是这样的:
- 计算机从串行端口读取整个流,并在其中找到所需的前缀序列0xAA55AA55
- 前缀之后立即有4个字节的数据包标识符
- 此数据包的数据长度进一步控制了整个数据包的长度
- 最多8个字节的数据
至此,当时Arduino中的软件部分完成了。 后来进行了重做,但总体概念没有改变。
我还编写了一个简单的数据包生成器用于调试,以便在家进行调试-它只是将带有随机数据的数据包发送到串行端口,从而使您可以在舒适的条件下调试计算机上的应用程序。
大约在同一时间,Arduino Nano和Mini CAN防护罩的较小组件问世。
我设计了一个小箱子,将其打印出来,并将所有组件放入其中。
在外面,一侧有OBD连接器,另一侧有Mini USB。 内部有一个用于终端电阻的开关。
使用wxWidgets在PC上的CAN嗅探器
我用C#绘制了一个程序的简单草稿,该草稿在Grid中显示了收到的数据。 然后他去检车。 我只是不带我的笔记本电脑,因为他的电池命令我住了很长时间并且被用作固定计算机,但是我拿着一台上网本,但处理器很弱。 我所看到的...我什么都没看到。 两个内核均100%加载,应用程序接口不响应。 但是在我的计算机上,它仍然比上网本快得多,并且使用随机数据包生成器,该应用程序可以正常工作并显示数据。 由此得出的结论是,弱计算机上的.NET平台对我不起作用,因为当时我只能使用该上网本在现场进行调试。
之前,我在几个项目中使用了wxWidgets库,对此我只有一种愉快的体验。 它是轻量级的,不需要随身携带各种库,甚至不需要跨平台,这带来了希望代码的接口部分可以转移而无需对其他平台进行重大改动的希望。 如果不想烦恼所有这些,在文章末尾将有一个指向已编译程序的链接。
如何为Visual Studio安装和编译wxWidgets安装与编译1.下载Windows Installer
wxWidgets并将其安装在例如文件夹C:\ wxWidgets中
2.创建一个环境变量:
WXWIN = C:\ wxWidgets
3.运行Visual Studio命令提示符,然后转到目录:
%WXWIN%\ build \ msw
4.键入两个命令进行编译:
nmake / f makefile.vc BUILD =调试RUNTIME_LIBS =静态
nmake / f makefile.vc BUILD =释放RUNTIME_LIBS =静态
在Visual Studio中设置项目1.在Visual Studio中,使用参数Empty project创建一个Win32 Project。
2.在“所有配置”的项目属性中,在“ VC ++目录”部分中指定路径:
包括目录:
$(WXWIN)\包括
$(WXWIN)\包含\ msvc
图书馆目录:
$(WXWIN)\ lib \ vc_lib
3.在“ C / C ++-代码生成”部分中,更改:
用于调试的运行时库:/ MTd配置
用于配置发布版本的运行库:/ MT
4.在“常规”部分中,更改:
字符集:使用Unicode字符集
5.要将图标添加到exe文件,您需要添加具有以下内容的资源文件:
#include“ wx \ msw \ wx.rc”
wxicon图标app_icon.ico
6.另外,如果需要使用UAC,请在“链接器-清单文件”部分中:
UAC执行级别:requireAdministrator
第一个在C ++和wxWidgets中实现的原型表明,即使是上网本也可以在表中显示数据,并且我开始开发自己计划的内容。
从结构上讲,该程序由两个流组成:接口和带有串行端口的工作流。 没有应用非常有趣的算法。 该代码有很多注释,应该非常简单。 到源的链接将在文章的结尾。
首先要做的就是根据获取此数据的限制在表中对数据单元进行着色。 我已经在第一个原型中查看了连续变化值的17行数据,我意识到有必要以某种方式区分新鲜数据和不变或很少更改的数据。 他分两个阶段进行着色:
- 首次数据以绿色单元格背景突出显示
- 重复到达并进一步到达的数据以红色背景突出显示,如果此数据不再更改,则逐渐变为白色
立刻清楚地发现,根本没有使用哪些单元,哪些单元包含了反信号。 寻找感兴趣的变量值大大简化了。 在下文中,将所有图像动画化。 如果该动画在文章中不起作用(在某些移动浏览器上),请单击图像以打开完整版本的动画。
然后,我仍然想检查串行端口是否可以处理数据流。 为此,在Arduino端,我添加了接收数据包数量的计数器和数据包中的字节计数器。 这些计数器以标识符为0x000的数据包发送到计算机。 收到此数据后,程序不会在表中显示它们,而是在顶部的单独信息字段中显示它。 结果甚至是令人愉快的。 平均而言,以高达9.5 kB / s的速度接收高达750包/秒的数据,这是该区域中高达80 kbit / s的速度的地方,这对于串行端口而言是完全可能的。 但同样,默认情况下,数据交换配置为500 kbps,这是更好的选择。
我将ELM327诊断适配器与OBD接口并行连接并将其连接到电话,然后尝试读取各种数据后,出现了向日志添加数据的功能。 数据运行得如此之快,以至于看不到它。 将所有这些记录在日志中之后,您就可以从容地坐下来查看传输的数据了。 为此,甚至可以将ASCII文本数据写入日志。 如果所有数据都是冗余的,您还可以选择文件类型,定界符并通过单击表中指定的数据包标识符并单击“添加要过滤的ID”按钮(默认情况下,写入所有数据)来配置数据包过滤器。
那时,人们意识到,通过ELM327捆绑包执行各种“诊断”的所有电话应用程序都无法直接与车辆的CAN总线通信。 他们只是通过访问CAN ID 0x7E0来通过CAN总线使用OBD诊断功能。 通常,这是电动机控制器(ECU)的地址,其答案来自标识符为0x7E8的数据包。 但是所有其他数据包都是所谓的“特定于供应商的数据包”,没有任何制造商会如此轻松地打开它们(尽管有一个例子:
福特为其汽车发布了一个SDK )。
继续研究这些包中传输的内容时,我想到了另一个想法:当单击表中的一个单元格时,在右侧的程序窗口中,显示该字节的二进制和十进制值,并取下一个字节并添加到单词中。 接下来,将该单词乘以某个系数,得到十进制结果。 听起来还不太清楚,但与完成操作有关:引擎速度以CAN ID 0x180数据包的形式出现在前两个字节中。 这两个字节给出与转弯成比例的特定字。 如果该词的含义除以8,则可获得当前动量。 因此,将系数的0.125表示为8的倒数。接下来,该单词在幅度动态调整的图形中可视化。 原则上,可以按相反的顺序搜索乘数:我发现与时间表非常相似的单元格与引擎速度或其他内容非常相似,之后调整乘数以获得实数值。
好吧,二进制表示形式使您可以搜索各种位指示符。 例如,搜索方向指示器指示器的过程被简化为打开它们并观察哪个单元格开始变化,在下面的示例中为CAN ID 0x481字节2。此后,单击一个单元格将在相应的字段中显示其二进制值,其中已经可以看到下面两个开关的切换。位(向左,向右,以及一起响起-警报)。
最后,我需要将一些控制数据发送到CAN总线,并查看对这些命令的反应。 将代码添加到Arduino程序,该程序从计算机接收数据并传输到CAN总线。 正是在这个阶段,CyberLib被放弃了,因为它不支持中断串行端口缓冲区中的数据接收。 在计算机上的程序中,我添加了几个文本字段,可以在其中输入各种参数,并添加了一个表格以查看执行器的响应。 下例显示了控制命令启用/禁用冷却风扇的第一速度(0x0A)和启用/禁用空调的离合器(0x0B)。

总结
几乎没有地方可以找到制造商数据的完整解密,尤其是官方数据。 最好的情况是,将在其他人的研究框架内执行某些附加功能。 CAN嗅探器可以帮助您找到此数据。 我能够找到大约40种不同的汽车参数,并且为了进行实验,根据接收到的数据,我对冷却风扇进行了自己的控制。
我希望所有这些不仅对我有用。