在软件中实现 CAN 协议层

电器工程 沟通 能够
2022-01-09 00:59:13

背景

我正在开发一个需要适度微控制器规格的项目:

  • 8 个 12 位、10kHz ADC
  • 1kB 内存
  • 48-QFN 或更小的占位面积
  • 20kbps 菊花链式抗噪和纠错通信协议

信号处理要求相当低,大部分可以输出到系统中的主处理器。前三个规格很容易满足,并且可以以不到 2 美元的数量完成。然而,通信将发生在一个非常电噪声的环境中,因此像 LIN 和 I2C 这样的易受噪声影响的网络已经不存在了。反对 LIN 的另一个论点是,我希望在 5V 或 3.3V 下运行整个设备,而 LIN 收发器需要 12V,因此每个传感器板都需要额外的稳压器或电线。我最初选择 CAN 来完成这项任务。然而,CAN 控制器增加了相当大的成本,我很好奇这是否可以在软件中完成。

CAN物理层

CAN 规范定义了 OSI 网络参考模型的数据链路和物理层。许多廉价的 8 引脚 IC,例如NXP TJA1040/50Maxim MAX3058/59Microchip MCP2551TI SN65HVD1050用于实现物理层。使用 D/A 转换器或运算放大器实现物理层即使不是不可能,也很困难,因此这些 IC 非常值得 1 美元左右的成本。

CAN 数据链路/协议层

对于数据链路层,一些微控制器将 CAN 协议模块添加到基本的 UART、I2C 和 SPI 通信层。然而,这些芯片比基本芯片贵得多。

CAN协议模块成本调查

为了证实这一说法,这里有一些流行的 CAN 和非 CAN 版本的 micros,来自:

  • ATmega16 - ATMEGA16M1(带 CAN):3.87 美元,ATMEGA168A(无 CAN):3.23 美元
  • dsPIC - DSPIC33FJ64MC802(带 CAN):6.14 美元,DSPIC33FJ64GP202(无 CAN):5.48 美元
  • PIC18 - PIC18F2480(带 CAN):6.80 美元,PIC18F24J10(无 CAN):2.10 美元
  • Cortex-M3 - STM32F103C4T6A(带 CAN):6.50 美元,STM32F100C4T6B(无 CAN):2.73 美元

公平地说,我只比较了具有相同内存大小的微控制器,但是,许多非 CAN 版本都可以以更少的内存大小获得。外部 CAN 控制器,如Microchip MCP2515,几乎是 2 美元,因此如果您有选择,将 CAN 集成到微控制器中显然更具成本效益。

有趣的是,ATmega 部件是迄今为止 Digikey 库存中最便宜的配备 CAN 的部件。

CAN协议层功能

dsPIC 单片机中的 CAN 模块执行以下操作:

CAN 总线模块由协议引擎和消息缓冲/控制组成。CAN 协议引擎处理在 CAN 总线上接收和传输消息的所有功能。通过首先加载适当的数据寄存器来传输消息。可以通过读取相应的寄存器来检查状态和错误。在 CAN 总线上检测到的任何消息都会检查是否有错误,然后与过滤器进行匹配,以查看是否应该接收它并将其存储在接收寄存器之一中。

这在软件中似乎相当可行。

问题

是否可以使用软件协议层仅通过配备廉价 UART 的微控制器和 CAN 收发器来实现 CAN 规范?如果是这样,是否存在任何开源实现?

或者,CAN 收发器可以与 UART 一起使用来实现自定义协议吗?我可以使用单主拓扑;我知道在自定义协议中很难进行仲裁。

4个回答

我认为仅在固件中实现 CAN 协议会很困难,并且需要一段时间才能正确完成。这不是一个好主意。

但是,你的价格很高。我刚查了一下,一个 QFN 封装的 dsPIC 33FJ64GP802 在 microchipdirect 上的售价为 3.68 美元,1000 片。实际产量的价格会更低。

硬件 CAN 外围设备为您做了一些实际的事情,而且它的价格涨幅远不及您所声称的。

添加:

由于您似乎决心尝试固件路线,因此这里有一些显而易见的问题。很可能还有其他我还没有遇到过的问题。

你想以 20 kbit/s 的速度进行 CAN。对于 CAN 来说,这是一个非常慢的速率,它在至少 10 秒的时间内达到 1Mbit/s。为了给您一个数据点,NMEA 2000 船载信号标准以 200 kbits/s 的速度在 CAN 上分层,这意味着从一艘大船的一端到另一端。

您可能认为您所需要的只是每个位一个中断,并且您可以在该中断中完成您需要的一切。那是行不通的,因为在每个 CAN 位时间中都会发生几件事。有两件事特别需要在子位级别完成。第一个是检测碰撞,第二个是动态调整比特率。

CAN 总线上有两种信号状态,隐性和显性。隐性是当没有东西驱动公共汽车时发生的事情。两条线通过总共 60 Ω 拉在一起。由 MCP2551 等普通芯片实现的普通 CAN 总线的两端应有 120 Ω 的端接器,因此总共有 60 Ω 的电阻将两条差分线被动地拉到一起。显性状态是当两条线被主动拉开时,如果我没记错的话,距离隐性状态大约 900mV。基本上,这就像一个集电极开路总线,只是它是用差分对实现的。如果 CANH-CANL < 900mV,则总线处于隐性状态,而当 CANH-CANL > 900mV 时,总线处于显性状态。显性状态信号 0,隐性状态信号 1。

每当一个节点向总线“写”一个 1(放开它),它就会检查是否有其他节点正在写一个 0。当你发现总线处于显性状态 (0) 时,当你认为你正在发送并且您发送的当前位为 1,则表示其他人也在发送。冲突只有在两个发送者不同意时才有意义,规则是发送隐性状态的那个会后退并中止其消息。发送主导状态的节点甚至不知道这发生了。这就是仲裁在 CAN 总线上的工作方式。

CAN 总线仲裁规则意味着您必须在发送 1 的每个位中途观察总线,以确保其他人没有发送 0。此检查通常在位的 2/3 处完成, 是 CAN 总线长度的基本限制。比特率越慢,从总线一端到另一端的最坏情况传播的时间就越长,因此总线可以越长。必须在您认为自己拥有总线并发送 1 位的每一位进行此检查。

另一个问题是比特率调整。总线上的所有节点必须就比特率达成一致,比 RS-232 更接近。为了防止小的时钟差异累积成重大错误,每个节点必须能够做一个比其标称长一点或短一点的位。在硬件中,这是通过运行比比特率快 9 到 20 倍的时钟来实现的。这个快速时钟的周期称为时间量子。有一些方法可以检测到新位的开始是否在您认为它们应该在的位置上徘徊。然后,硬件实现会稍微添加或跳过一个时间量以重新同步。只要您可以调整预期位时间和实际测量位时间之间的小相位差,还有其他方法可以实现这一点。

无论哪种方式,这些机制都需要在一段时间内的不同时间完成各种事情。这种时序在固件中会变得非常棘手,或者需要总线运行得很慢。假设您在固件中以 20 kbits/s 的速度实现了时间量子系统。每个位至少有 9 个时间量子,这将需要 180 kHz 中断。使用 dsPIC 33F 之类的东西当然可以做到这一点,但会占用处理器的很大一部分。在 40 MHz 的最大指令速率下,每个中断可以获得 222 个指令周期。完成所有检查不应该花那么长时间,但可能需要 50-100 个周期,这意味着 25-50% 的处理器将用于 CAN,并且它需要抢占其他所有正在运行的东西。这会阻止这些处理器经常运行的许多应用程序,就像开关电源或电机驱动器的逐脉冲控制一样。对于我用这样的芯片所做的许多事情,每隔一个中断的 50-100 个周期延迟将是一个完整的展示停止器。

所以你会花钱以某种方式做CAN。如果不在用于该目的的专用硬件外围设备中,那么在获得更大的处理器来处理重要的固件开销,然后处理其他所有事情的不可预测和可能的大中断延迟。

然后是前期工程。CAN 外围设备正常工作。从您的评论来看,这个外围设备的增量成本似乎是 0.56 美元。这对我来说似乎很划算。除非您拥有非常大批量的产品,否则您将无法收回仅在固件中实施 CAN 所需的大量时间和费用。如果您的销量那么高,那么我们一直提到的价格无论如何都是不现实的,添加 CAN 硬件的差价会更低。

我真的不认为这是有道理的。

我们使用PIC18F25K80虽然它没有 DSP,但数量约为 2 美元。它几乎可以直接替代您提到的 PIC18F2480。我们使用CCS编译器及其用于 CAN 的软件堆栈,这可能是从 Microchip 移植的。它适用于我需要和尝试的一切。

如果我没看错,听起来你想只使用 UART 和一些聪明的固件来对 CAN 功能进行 bit-bash。相信我,这永远不会奏效——我建议阅读一篇关于 CAN 或 CANopen 错综复杂的好文章。沿着这条路线走,您将消除您正在寻找的任何成本节约。

我要么使用带有 CAN 模块的微控制器,然后多花 2 美元,要么您是否考虑过与 UART 兼容的不同协议,例如RS-485上的Modbus

我也在考虑在 PIC µC 上使用位碰撞 CAN 协议,所以请 EricM,如果你真的这样做了,请回复并至少告诉你,你得到的 PIC18F 或 DSPic 核心频率的比特率是多少。谢谢!

一般来说:RS 485 将是主要问题的解决方案,但也可以使用具有非全双工 UART 通信(点 2 点)的 CAN(甚至 FlexRay)收发器作为所有协议使用 NRZ 编码。

但是在 UART/V24/RS232 中,全双工主要是使用而不考虑细节,所以也许你需要在你的应用程序的超级循环或状态机上投入一些头脑......

但回到 CAN-bitbanging:我使用 CAN 多年,从未见过 bitbanging 实现,但据我所知,这应该适用于现代 µC(如 DSPic 或 ARM 等)的 tp 100kBit 的位时序。 (拥有 80MHz 或以上的核心......)

至少如果只考虑回读......发送将意味着在准备位结构时需要一些开销,因此无法达到 100% 的总线负载,但在 CAN 中,超过 65% 的情况很少见......