文章目录
-
- 什么是CAN总线?
- 物理层
-
- 差分信号
- 连接方式
- CAN节点
- CAN协议
- 如何寻址?
- 帧类型
-
- 数据帧
- 远程帧
- 错误帧
- 过载帧
- 新闻时间和同步
-
- 位时序
- 波特率
- 消息过滤器
- 如何配置?
- 总结
- 参考
什么是CAN总线?
,简称或者) 是最早的串行总线标准,功能丰富CAN控制芯片应用于梅赛德斯-奔驰并大规模生产。由于支持多主机和多从机的优点,所有控制器、传感器和电子设备的直接通信只需要两条线路,大大优化了整车的布线。
[^wiki can bus]:
随着技术的不断发展,CAN国际标准组织公布了相应的标准和标准CAN不同标准;
标准 | 涵盖内容 | |
---|---|---|
ISO 11898-1 | 数据链路层 | |
ISO 11898-2 | 高速CAN的物理层 | |
ISO 11898-3 | 低速容错CAN的物理层 |
ISO 11898-1
,ISO 11898-2
是相应的设计标准,去搜索就能知道这个技术点是怎么设计的。
物理层
差分信号
这里我们来介绍一下物理层,什么是物理层?CAN传输电信号的过程。CAN是串行异步通信,只有CAN_HIGH
和CAN_LOW
通过差分信号通信两条差分信号线,其优点是可以增加信号的抗干扰能力,抑制共模信号的干扰;
如下图所示;
因此,在将信号转换为一个字节和一个字节的数字信号之前,按照这种差异形式的模拟信号传输信号。
当CAN_HIGH减去CAN_LOW当大于一个阈值时,它可以被视为高逻辑,相反,当小于一个阈值时,它变得低逻辑。
让我们再来看看CAN如何连接总线设备?
连接方式
CAN总线支持在总线上挂载多个节点,类似I2C
总线,可以在SCL
和SDA
多个从机挂载在上面,如下图所示;
不过CAN其实总线没有主从的概念,每个设备都是节点(Node
),与节点相比,节点可以直接相互通信I2C
总线,CAN总线设置终端电阻,常见的闭环连接模式,相对于开环连接模式。
在不同的连接模式下,它们的通信速即高速CAN和低速CAN的区别。
两条线形成一条双绞线,连接120Ω特性阻抗。,又称高速CAN。它在总线两端均接120Ω电阻。
使用了120Ω
终端电阻(这是CAN的ISO该模型的最高通信速率在标准中规定),以下是传输距离与传输速度的关系;
高速CAN拓扑结构如下所示;
还有一种是低速CAN,或者也叫容错CAN,低速容错 CAN 通信的最大带宽从总线 1 Mbps
降低到 125 Kbps
,不再在总线,而是将电阻。如下图所示;
由于高速CAN和低速CAN拓扑结构不同,终端电阻分布不同,因此CAN_HIGH
和CAN_LOW
这里有隐性电平和显性电平。
硬件上的连接基本上已经弄清楚了。以下是如何实现CAN节点。让我们简单介绍一下。
CAN节点
CAN节点通常分为三部分;
- ;
- ,
- ;
通常,一些单片机集成在相应的内部CAN控制器外设,比如我们常用的单片机——STM32
,所以我们常见的结构通常是这样的。
因此,整个过程如下:
- CAN差分通过总线;
- CAN收发器将,或者将TTL将电平信号转换为差分信号;
- CAN控制器将TTL接收电平信号并传输给MCU;
那么,对于单片机开发者而言,需要关注的就是最终CAN传输给控制器MCU如何配置数据CAN以及使用控制器CAN控制数据的读取和发送。
在这种情况下,我们必须了解它CAN总线的通信原理,如何寻址,上层协议如何规定。
CAN协议
CAN协议类似于网络协议,分层设计理念;
按照我的理解;
- 物理层是上述硬件拓扑结构,包括高速CAN和低速CAN,而CAN收发器属于物理层;
- 传输层则是CAN控制器需要做的事情,包括CAN时序,同步,消息仲裁,确认,错误检验等,这个比较复杂,如果只是应用开发,我认为,简单了解一下即可;这一层需要做的工作包括:
- 故障约束;
- 错误监测;
- 消息验证;
- 信息确认;
- 仲裁;
- 信息帧;
- 传输速率和时间;
- 路由信息;
- 对象层,MCU我们需要属于这一层CAN信息过滤设置,CAN新闻处理等;
- 应用层就是基于对象层的进一步封装,不同的CAN工业自动化等标准
CANopen
,汽车诊断ISO 14229 定义的UDS等等;
如何寻址?
CAN总线上的每个节点都不需要设置节点地址,而是通过新闻标识符(Identifier)区分信息CAN总线的消息是广播的(也就是大家都能收到消息),比如总线有节点A,节点B,节点C,那么节点A发消息,节点B和节点C都会收到消息;
节点B 和 节点C 根据消息,以及B和C比较新闻过滤规则,如果不符合规则,则不接受信息。
这里需要注意的是:
- 发消息时,总线必须空闲;
- 标识符越小,消息获取总线的优先级越高;
在这里我们已经了解如何寻址,下面就看一下消息帧了。
帧类型
CAN有4种帧类型:
- 数据帧:包含用于传输的节点数据的帧
- 远程帧:请求传输特定标识符的帧
- 错误帧:由任何检测到错误的节点发送的帧
- 过载帧:在数据帧或远程帧之间插入延迟的帧
这里我们有必要重点了解一下,下面继续介绍各种帧之间的区别。
数据帧
数据帧分为标准帧和扩展帧两种格式;
- 基本帧格式:有11个标识符位
- 扩展帧格式:有29个标识符位
数据帧的结构具体如下所示;
简单介绍一下数据帧的细节;
-
sof
:start of frame
,表示数据帧开始;(1 bit) -
Identifier
:标准格式11 bit,扩展格式29 bit包括Base Identifier(11 bit)和Extended Identifier(18 bit),该区段标识数据帧的优先级,数值越小,优先级越高; -
RTR
:远程传输请求位,0时表示为数据帧,1表示为远程帧,也就是说RTR=1时,消息帧的Data Field为空;(1 bit) -
IDE
:标识符扩展位,0时表示为标准格式,1表示为扩展格式;(1 bit) -
DLC
:数据长度代码,08表示数据长度为08 Byte;(4 bit) -
Data Field
:数据域;(0~8 Byte) -
CRC Sequence
:校验域,校验算法, G ( x ) = x 15 + x 14 + x 10 + x 8 + x 7 + x 4 + x 3 + 1 G(x) = x15 + x14 + x10 + x8 + x7 + x4 + x3 + 1 G(x)=x15+x14+x10+x8+x7+x4+x3+1 -
DEL
:校验域和应答域的隐性界定符;(1 bit) -
ACK
:应答,确认数据是否正常接收,所谓正常接收是指不含填充错误、格式错误、 CRC 错误。发送节点将此位为1,接收节点正常接收数据后将此位置为0;(1 bit) -
SRR
:替代远程请求位,在扩展格式中占位用,必须为1;(1 bit) -
EOF
:连续7个隐性位(1)表示帧结束;(7 bit) -
ITM
:帧间空间,Intermission (ITM)
,又称Interframe Space
(),连续3个隐性位,但它不属于数据帧。帧间空间是用于将数据帧和远程帧与前面的帧分离开来的帧。数据帧和远程帧可通过插入帧间空间将本帧与前面的任何帧(数据帧、遥控帧、错误帧、过载帧)分开。过载帧和错误帧前不能插入帧间空间。
远程帧
一般地,数据是由发送单元主动向总线上发送的,但也存在接收单元主动向发送单元请求数据的情况。远程帧的作用就在于此,它是接收单元向发送单元请求发送数据的帧。远程帧与数据帧的帧结构类似,如上图X所示。远程帧与数据帧的帧结构区别有两点:
- 数据帧的 值为“”,远程帧的 值为“”
远程帧的 块表示请求发送单元发送的数据长度(Byte)。当总线上具有相同标识符的数据帧和远程帧同时发送时,由于数据帧的 位是显性的,将在仲裁中赢得总线控制权。
错误帧
用于在接收和发送消息时检测出错误时,通知错误的帧。错误帧由错误标志和错误界定符构成。错误帧的帧结构如图11示。
-
错误标志:
个显性/隐性重叠位
- 主动错误标志(6个显性位): 处于主动错误状态的单元检测出错误时输出的错误标志
- 被动错误标志(6个隐性位): 处于被动错误状态的单元检测出错误时输出的错误标志
-
错误界定符: 个隐性位
过载帧
过载帧是用于接收单元通知发送单元它尚未完成接收准备的帧。在两种情况下,节点会发送过载帧:
- 接收单元条件的制约,要求发送节点延缓下一个数据帧或远程帧的传输;
- 帧间空间(Intermission)的 内检测到显性位
每个节点最多连续发送两条过载帧。过载帧由过载标志和过载界定符( 个隐性位)构成。数据帧的帧结构如图12所示。
这里基本把帧介绍完了,但是每个节点之间的通讯,我们如何知道这一帧开始接收了,这一帧已经接收结束了呢?下面就需要了解一下消息的时序和消息同步的方法。
消息时序以及同步
位时序
在讲CAN消息时序和同步之前,我们可以对照一下UART串口的传输协议,他有起始位和停止位,然后大家都规定使用相同的通讯速率(波特率);
其实CAN通讯也是类似的方式,它属于异步通讯,没有时钟信号线,所以所有节点之间要约定好使用相同的波特率来传输数据。
在总线空闲一段时间后,在(起始位) 进行硬同步,同步方式是将每一位划分成多个称为(time quanta),并分配一定数量的量子到位中的四个阶段完成的。
这四个阶段分别为:
SYNC_SEG
:同步段,1 个时间量子长度。它用于同步各种总线节点;PROP_SEG
:传播段,1~8 时间量子长度。它用于补偿网络上的信号延迟。PHASE_SEG_1
:相位缓冲段1,1~8 时间量子长度。它用于补偿边缘相位误差,在重新同步期间可能会延长。PHASE_SEG_2
:相位缓冲段2,2~8 时间量子长度。它用于补偿边缘相位误差
具体如下图所示;
波特率
如何计算波特率,需要知道每个量子时间的长度(time quanta),以及每一位需要多少个量子时间,
假设这里time quanta = 1us
,并且1 bit = 8 tq
,那么上图中的波特率就应该是: 1 ∗ 1 0 6 1 + 1 + 4 + 2 = 125 K b p s \cfrac{1*10^6}{1+1+4+2} =125K bps 1+1+4+21∗106=125Kbps
消息过滤器
前面有提到消息在CAN总线上是的,但并不是所有节点都会对总线上所有消息感兴趣。节点通过控制器中过滤码( )和掩码(),再检验总线上消息的标识符,来判断是否接收该消息()。
对于掩码,“”表示该位与本节点,“”表示该位与本节点。举例如下:
**例1:**仅接收消息标识符为00001567
(十六进制)的帧
- 设置过滤码为
00001567
- 设置掩码为
1FFFFFFF
节点检测消息的标识符的所有位(29位),如果标识符为00001567
接收,否则舍弃。
**例2:**接收消息标识符为00001567
到0000156F
的帧
- 设置过滤码为
00001560
- 设置掩码为
1FFFFFF0
节点检测消息的标识符的高25位,最低的4位则不care。如果标识符最高25位相同则接收,否则舍弃。
**例3:**接收消息标识符为00001560
到 00001567
的帧
- 设置过滤码为
00001560
- 设置掩码为
1FFFFFF8
节点检测消息的标识符的高26位,最低的3位则不care。如果标识符最高26位相同则接收,否则舍弃。
**例4:**接收所有消息帧帧
- 设置过滤码为
0
- 设置掩码为
0
节点接收总线上所有消息。
如何配置?
上面介绍了帧类型,那么如何基于MCU
进行配置呢?这里以STM32F407
为硬件平台,使用HAL库进行初始化,看一下都对哪些地方进行了配置。一般来说,我们需要配置CAN的波特率,消息过滤器等等,下面是简单的配置的代码;
CAN_HandleTypeDef hCAN; void MX_CAN_Init(void) { CAN_FilterTypeDef sFilterConfig; /*CAN单元初始化*/ hCAN.Instance = CAN1; /* CAN外设 */ /* BTR-BRP 波特率分频器 定义了时间单元的时间长度42/(1+6+7)/6=500Kbps */ hCAN.Init.Prescaler = 6; hCAN.Init.Mode = CAN_MODE_NORMAL; /* 正常工作模式 */ hCAN.Init.SyncJumpWidth = CAN_SJW_1TQ; /* BTR-SJW 重新同步跳跃宽度 1个时间单元 */ hCAN.Init.TimeSeg1 = CAN_BS1_6TQ; /* BTR-TS1 时间段1 占用了6个时间单元 */ hCAN.Init.TimeSeg2 = CAN_BS2_7TQ; /* BTR-TS1 时间段2 占用了7个时间单元 */ hCAN.Init.TimeTriggeredMode = DISABLE; /* MCR-TTCM 关闭时间触发通信模式使能 */ hCAN.Init.AutoBusOff = ENABLE; /* MCR-ABOM 自动离线管理 */ hCAN.Init.AutoWakeUp = ENABLE; /* MCR-AWUM 使用自动唤醒模式 */ hCAN.Init.AutoRetransmission = DISABLE; /* MCR-NART 禁止报文自动重传 DISABLE-自动重传 */ /* MCR-RFLM 接收FIFO
锁定模式 DISABLE-溢出时新报文会覆盖原有报文 */ hCAN.Init.ReceiveFifoLocked = DISABLE; /* MCR-TXFP 发送FIFO优先级 DISABLE-优先级取决于报文标示符 */ hCAN.Init.TransmitFifoPriority = DISABLE; if (HAL_CAN_Init(&hCAN) != HAL_OK) { //Error_Handler(); } // 初始化发送器 hCAN1_TxMessage.IDE = CAN_ID_STD; hCAN1_TxMessage.RTR = CAN_RTR_DATA; hCAN1_TxMessage.TransmitGlobalTime = ENABLE; // 初始化滤波器 设置为0 则不对消息进行过滤 hCAN1_Filter.FilterIdHigh = 0; /* 要过滤的ID高位 */ hCAN1_Filter.FilterIdLow = 0; /* 要过滤的ID低位 */ hCAN1_Filter.FilterMaskIdHigh = 0; /* 过滤器高16位每位必须匹配 */ hCAN1_Filter.FilterMaskIdLow = 0; /* 过滤器低16位每位必须匹配 */ hCAN1_Filter.FilterFIFOAssignment = CAN_FILTER_FIFO0;/* 过滤器被关联到FIFO 0 */ hCAN1_Filter.FilterBank = 0; hCAN1_Filter.FilterMode = CAN_FILTERMODE_IDMASK; /* 工作在标识符屏蔽位模式 */ hCAN1_Filter.FilterScale = CAN_FILTERSCALE_32BIT; /* 过滤器位宽为单个32位。*/ hCAN1_Filter.FilterActivation = ENABLE; hCAN1_Filter.SlaveStartFilterBank = 0; HAL_CAN_ConfigFilter(&hCAN, &hCAN1_Filter); while(HAL_CAN_Start(&hCAN) != HAL_OK ) { printf("\nCAN_Start Failed!!"); HAL_Delay(100); } HAL_CAN_ActivateNotification(&hCAN, CAN_IT_RX_FIFO0_MSG_PENDING); }
下面是CAN发送的函数,我们需要自己构建相应的消息帧格式,通常需要设置消息帧的ID格式,消息长度,具体如下;
void CAN_TxMessage(CAN_HandleTypeDef *hcan,uint16_t ID ,uint8_t aData[], uint8_t DLC)
{
uint32_t Tx_MailBox;
/*-1- 配置数据段长度 ----------------------------------------*/
hCAN1_TxMessage.IDE = CAN_ID_STD;
hCAN1_TxMessage.RTR = CAN_RTR_DATA;
hCAN1_TxMessage.StdId = ID;
hCAN1_TxMessage.DLC = DLC;
hCAN1_TxMessage.TransmitGlobalTime = ENABLE;
/*-2- 发送aData ---------------------------------------------*/
while(HAL_CAN_AddTxMessage(hcan, &hCAN1_TxMessage, aData, &Tx_MailBox) != HAL_OK)
{
HAL_Delay(5);
}
}
上述代码设置发送消息:
CAN_ID_STD
设置为标准ID;CAN_RTR_DATA
设置消息为数据帧;StdId
为当前消息的ID;DLC
为当前消息的长度;
整体可以参考前面介绍的消息帧格式,篇幅有限,这里就先简单的介绍一下。
总结
本文对CAN总结进行了简单的介绍,CAN通讯的特点可以总结如下;
- 符合OSI开放式通信系统参考模型;
- 两线式总线结构,电气信号为差分式;
- 多主控制。在总线空闲时,所有的单元都可开始发送消息,最先访问总线的单元可获得发送权;多个单元同时开始发送时,发送高优先级 ID 消息的单元可获得发送权;
- 消息报文不包含源地址或者目标地址,仅通过标识符表明消息功能和优先级;
- 基于固定消息格式的广播式总线系统,短帧结构;
- 事件触发型。只有当有消息要发送时,节点才向总线上广播消息;
- 可以通过发送远程帧请求其它节点发送数据;
- 消息数据长度 0~8 Byte;
- 错误检测功能。所有节点均可检测错误,检测处错误的单元会立即通知其它所有单元;
- 发送消息出错后,节点会自动重发;
- 故障限制。节点控制器可以判断错误是暂时的数据错误还是持续性错误,当总线上发生持续数据错误时,控制器可将节点从总线上隔离;
- 通信介质可采用双绞线、同轴电缆和光导纤维,一般使用最便宜的双绞线;
- 理论上,CAN总线用单根信号线就可以通信,但还是配备了第二根导线,第二根导线与第一根导线信号为差分关系,可以有效抑制电磁干扰;
- 在40米线缆条件下,最高数据传输速率 1Mbps;
- 总线上可同时连接多个节点,可连接节点总数理论上是没有限制的,但实际可连接节点数受总线上时间延迟及电气负载的限制;
参考
- Learning Module CAN -Vector
- CAN Bus -Wikipedia
- Can Bus Id Filter And Mask - De Montfort University
- Introduction to the Controller Area Network - TI
- https://www.nxp.com/docs/en/application-note/AN1798.pdf - NXP
本着对自己和对他人负责的原则,由于我接触CAN的时间也不是很久,本文很多是基于个人在项目中学习和总结的经验,所以文中难免存在错误和不足,请各位不吝赐教,及时指出,如果文章帮到了你,