最近在技术群中看到网友们就「CAN和UART的难易程度」展开讨论,有人说CAN很简单,也有人说CAN很难。
实际上,难不难主要取决于个人的角度。对于那些基础较好且学习过CAN的人来说,可能会觉得CAN很简单。但对于基础较差的初学者来说,相对于UART来说,CAN确实要难得多。
在这里,我将针对初学者分享一些关于CAN总线的基础知识。相对于UART而言,CAN的内容要多得多。至于CAN相对于UART来说难不难,你可以看完之后自己得出答案。
CAN总线波特率
CAN总线是一种异步通信方式,因此它具有通信的波特率,而这个波特率的发生器位于CAN控制器内部。我们不需要深入了解它是如何产生的,但我们需要了解它的含义。在这一章节中,我将向初学者介绍以下两个内容。
1、异步通信
在串行通信中,主要分异步通信和同步通信。
同步通信:通信设备之间通过同步信号(CLK时钟)来实现数据传输的通信叫同步通信。如I2C、SPI这类通信中都具有一个时钟信号,其实在STM32中USART也具有同步功能,只是我们大多数人都只用了它的异步功能。
异步通信:简单来说,就是通信设备之间通过约定一样的时间来收发数据。而这个时间就会决定本节说的波特率。
2、波特率
很多工程师一直都没彻底搞明白什么是波特率,我这里还是结合UART波特率来简述一下其含义。
在电子通信领域,波特(Baud)即调制速率,指的是有效数据信号调制载波的速率,即单位时间内载波调制状态变化的次数。它是对符号传输速率的一种度量,1波特即指每秒传输1个符号。
UART每秒钟传送240个字符,而每个字符格式包含10位(1个起始位,1个停止位,8个数据位),这时的波特率为240Bd,比特率为10位*240个/秒=2400bps。
从上面的描述可以总结:
比特率:即单位时间内传送的二进制位数;
波特率:即单位时间内传输的符号个数;
只有在每个符号只代表一个比特信息的情况下,波特率与比特率才在数值上相等,但是它们的意义并不相同。
位时序
上面讲述了波特率,而决定波特率大小的就是本节说的位时序。在CAN标准中一个位可分为4段:
-
同步段(SS) -
传播时间段(PTS) -
相位缓冲段1(PBS1) -
相位缓冲段2(PBS2)
这些段又由可称为 Time Quantum(简称Tq)的最小时间单位构成。
1位分为4个段,每个段又由若干个Tq构成,这称为位时序。
而在STM32参考手册中,将位时序分为三段,但它将它传播段和位段1合并在一起了,如下图:
![image-20231029215859311](https://pic.imgdb.cn/item/653e657ac458853aef9e9193.png)
1位由多少个Tq构成、每个段又由多少个Tq构成等,可任意设定位时序。通过设定位时序,决定传输的波特率:
![image-20231029215903166](https://pic.imgdb.cn/item/653e6579c458853aef9e89c4.png)
这几个参数会在以后编程中进行配置,从而决定通信的波特率。
关于同步,还有硬件同步、再同步等操作。但初学者可以不必过多理解,掌握上面基础内容就行了。更多关于位时序的内容可以参看 ISO 11898 标准。
帧类型及格式说明
CAN总线是通过以下5种类型的帧进行通信:
数据帧:用于发送单元向接收单元传送数据的帧。
遥控帧:用于接收单元向具有相同 ID 的发送单元请求数据的帧。
错误帧:用于当检测出错误时向其它单元通知错误的帧。
过载帧:用于接收单元通知其尚未做好接收准备的帧。
帧间隔:用于将数据帧及遥控帧与前面的帧分离开来的帧。
数据帧和遥控帧有标准格式和扩展格式两种格式。标准格式有11个位的标识符ID,扩展格式有29个位的ID。
1、 数据帧
![image-20231029215908113](https://pic.imgdb.cn/item/653e6579c458853aef9e8517.png)
如上图,数据帧由7个段构成:
(1) 帧起始
表示数据帧开始的段。
(2) 仲裁段
表示该帧优先级的段。
(3) 控制段
表示数据的字节数及保留位的段。
(4) 数据段
数据的内容,可发送 0~8 个字节的数据。
(5) CRC 段
检查帧的传输错误的段。
(6) ACK 段
表示确认正常接收的段。
(7) 帧结束
表示数据帧结束的段。
理解数据帧的含义,请从认真理解它的定义:用于发送单元向接收单元传送数据的帧。
一般的CAN总线通信,总线上通信绝大部分时候都是数据帧。像在CANOpen协议中,用的最多的PDO过程数据对象就是通过数据帧进行的通信。
初学者可以先理解数据帧,然后其他就容易理解了。下面再来讲述一下数据帧7段的详情。
帧起始
标准和扩展格式相同。表示帧开始的段,1个位的显性位(如下图):
![image-20231029215912399](https://pic.imgdb.cn/item/653e6577c458853aef9e7b94.png)
关于显性和隐性电平,请参看我上一篇文章差分信号章节。
总线上的电平有显性电平和隐性电平两种。
总线上执行逻辑上的线“与”时,显性电平的逻辑值为“0”,隐性电平为“1”。
“显性”具有“优先”的意味,只要有一个单元输出显性电平,总线上即为显性电平。并且,“隐性”具有“包容”的意味,只有所有的单元都输出隐性电平,总线上才为隐性电平。(显性电平比隐性电平更强)
仲裁段
标准格式和扩展格式在此的构成有所不同。仲裁段表示该帧优先级的段,扩展格式多了18位ID(如下图):
![image-20231029215917312](https://pic.imgdb.cn/item/653e6579c458853aef9e89b4.png)
RTR = 0代表数据帧,RTR = 1代表远程帧。
为什么叫仲裁段,就是通过ID来判断总线上哪一个节点具有优先发送的权利。ID越小(0代表显性),优先级越高。
控制段
标准和扩展格式的构成有所不同。控制段由 6 个位构成(如下图):
![image-20231029215920793](https://pic.imgdb.cn/item/653e657ac458853aef9e917b.png)
它们除了都有4位表示数据段长度代码(DLC)外,标准帧有IDE(数值为0)位和r0保留位,扩展帧有r0和r1保留位。
保留位必须全部以显性电平发送。但接收方可以接收显性、隐性及其任意组合的电平。
数据段
标准和扩展格式相同。数据段表示传输数据的内容,从 MSB(最高位)开始输出,可发送 0~8 个字节的数据,长度由前面控制段决定。
CRC段
标准和扩展格式相同。CRC段是检查帧传输错误的帧,由 15 个位的 CRC 顺序和 1 个位的 CRC 界定符(用于分隔的位)构成。
![image-20231029215923972](https://pic.imgdb.cn/item/653e6577c458853aef9e7bce.png)
相比485这类通信,CAN控制器就已经把CRC校验做了,不需要你的程序再次去计算,从而节约了处理器资源。
ACK段
标准和扩展格式相同。ACK段用来确认是否正常接收。由 ACK 槽(ACK Slot)和 ACK 界定符 2 个位构成。
![image-20231029215926915](https://pic.imgdb.cn/item/653e6579c458853aef9e89c9.png)
**A.**发送单元在 ACK 段发送 2 个位的隐性位。
**B.**接收到正确消息的单元在 ACK 槽(ACK Slot)发送显性位, 通知发送单元正常接收结束。这称作“发送 ACK”或者“返回 ACK”。
帧结束
标准和扩展格式相同。帧结束是表示该该帧的结束的段。由 7 个位的隐性位构成。
![image-20231029215929729](https://pic.imgdb.cn/item/653e6577c458853aef9e7bb2.png)
2、遥控帧
![image-20231029215933337](https://pic.imgdb.cn/item/653e657ac458853aef9e9164.png)
和数据帧相比,遥控帧是接收单元向发送单元请求发送数据所用的帧。所以,遥控帧没有数据段。因此,遥控帧由如下 6 个段组成:
(1) 帧起始(SOF)
表示帧开始的段。
(2) 仲裁段
表示该帧优先级的段。可请求具有相同 ID 的数据帧。
(3) 控制段
表示数据的字节数及保留位的段。
(4) CRC 段
检查帧的传输错误的段。
(5) ACK 段
表示确认正常接收的段。
(6) 帧结束
表示遥控帧结束的段。
这6个段和上面数据帧的内容基本一样,这里就不一一讲述了。讲一下遥控帧和数据帧的区别:
-
遥控帧的 RTR 位为隐性位,没有数据段。 -
没有数据段的数据帧和遥控帧可通过 RTR 位区别开来。
问题一:遥控帧没有数据段,数据长度码该如何表示?
遥控帧的数据长度码以所请求数据帧的数据长度码表示。
问题二:没有数据段的数据帧有何用途?
例如,可用于各单元的定期连接确认/应答、或仲裁段本身带有实质性信息的情况下。
3、错误帧
![image-20231029215940285](https://pic.imgdb.cn/item/653e6577c458853aef9e7be8.png)
用于在接收和发送消息时检测出错误通知错误的帧。错误帧由错误标志和错误界定符构成。
(1) 错误标志
错误标志包括主动错误标志和被动错误标志两种。
-
主动错误标志:6 个位的显性位。 -
被动错误标志:6 个位的隐性位。
(2) 错误界定符
错误界定符由 8 个位的隐性位构成。
4、过载帧
![image-20231029215945634](https://pic.imgdb.cn/item/653e657ac458853aef9e9169.png)
过载帧是用于接收单元通知其尚未完成接收准备的帧。过载帧由过载标志和过载界定符构成。
(1) 过载标志
6 个位的显性位。
过载标志的构成与主动错误标志的构成相同。
(2) 过载界定符
8 个位的隐性位。
过载界定符的构成与错误界定符的构成相同。
5、帧间隔
![image-20231029215948940](https://pic.imgdb.cn/item/653e657ac458853aef9e919a.png)
帧间隔是用于分隔数据帧和遥控帧的帧。数据帧和遥控帧可通过插入帧间隔将本帧与前面的任何帧(数据帧、遥控帧、错误帧、过载帧)分开。
过载帧和错误帧前不能插入帧间隔。
(1) 间隔
3 个位的隐性位。
(2) 总线空闲
隐性电平,无长度限制(0 亦可)。
本状态下,可视为总线空闲,要发送的单元可开始访问总线。
(3) 延迟传送(发送暂时停止)
8 个位的隐性位。
只在处于被动错误状态的单元刚发送一个消息后的帧间隔中包含的段。
以上就是良许教程网为各位朋友分享的Linu系统相关内容。想要了解更多Linux相关知识记得关注公众号“良许Linux”,或扫描下方二维码进行关注,更多干货等着你 !
![137e00002230ad9f26e78-265x300](https://pic.imgdb.cn/item/653e657ac458853aef9e91ae.png)