目录
CAN协议介绍
物理层
闭环总线网络
开环总线网络
?通讯节点
差分信号
协议层简介
CAN的波特率
位时序
帧类型、作用及格式
数据帧
STM32CAN外设
?CAN 发送邮箱
?CAN 接收 FIFO
?有效消息
?接收处理
上溢
?标识符筛选
CAN1与CAN2整体逻辑
HAL库函数
CAN协议介绍
物理层
CAN 通讯并不是以时钟信号来进行同步的,它是一种异步通讯,只具有 CAN_High 和 CAN_Low 两条信号线,共同构成一组差分信号线,以差分信号的形式进行通讯。
CAN的物理层有两种拓扑结构,闭环总线网络和开环总线网络,我们将依次介绍他们。
闭环总线网络
闭环网络的特点是:高速、近距离。
它的总线最大长度为 40m,通信速度最高为1Mbps,总线的两端各要求有一个“120 欧”的电阻。
开环总线网络
闭环网络的特点是:低速、远距离。
它的最大传输距离为1km,最高通讯速率为 125kbps,两根总线是独立的、不形成闭环,要求每根总线上各串联有一个“2.2 千欧”的电阻。
?通讯节点
CAN 总线上可以挂载多个通讯节点,节点之间的信号 经过总线传输,实现节点间通讯。
由于 CAN 通讯协议不对节点进行地址编码,而是对数据内容进行编码的,所以网络中的节点个数理论上不受限制,只要总线的负载足够即可,可以通过中继器增强负载。
CAN 通讯节点由一个 CAN 控制器及 CAN 收发器组成,控制器与收发器之间通过 CAN_Tx 及 CAN_Rx 信号线相连,收发器与 CAN 总线之间使用 CAN_High 及 CAN_Low 信号线相连。而 CAN_High 及 CAN_Low 是一对差分信号线,使用差分信号。
差分信号
与传统使用单根信号线电压表示逻辑的方式有区别,使用差分信号传输时,需要两根信号线,这两个信号线的振幅相等,相位相反,通过两根信号线 的电压差值来表示逻辑 0 和逻辑 1。
?差分信号传输具有如下优点:
- 抗干扰能力强,当外界存在噪声干扰时,几乎会同时耦合到两条信号线上。所以外界的共模噪声可以被完全抵消。
- 能有效抑制它对外部的电磁干扰,同样的道理,由于两根信号的极性相反,他们对外辐射的电磁场可以相互抵消,耦合的越紧密,泄放到外界的电磁能量越少。
- 时序定位精确,由于差分信号的开关变化是位于两个信号的交点,而不像普通单端信号依靠高低两个阈值电压判断,因而受工艺,温度的影响小,能降低时序上的误差,同时也更适合于低幅度信号的电路。
CAN信号 | 高速CAN | 低速CAN |
---|
电平 | 显性 | 隐性 | 显性 | 隐性 |
---|
CAN_H | 3.50 | 2.50 | 4.00 | 1.75 |
---|
CAN_L | 1.50 | 2.50 | 1.00 | 3.25 |
---|
电位差 | 2.00 | 0 | 3.00 | -1.50 |
---|
?由于CAN总线的仲裁机制采取“线与”的方式对总线上的信号进行仲裁。因此,假如有两个 CAN 通讯节点,在同一时间,一个输出隐性电平,另一个输出显性电平,“线与”的总线仲裁机制将使它处于显性电平状态。因此低电平“0”被成为显性电平。
协议层简介
CAN的波特率
由于 CAN 属于异步通讯,没有时钟信号线,连接在同一个总线网络中的各个节点会像串口异步通讯那样,节点间使用约定好的波特率进行通讯
总线上的各个通讯节点只要约定好 1 个 Tq 的时间长度以及每一个数据位占据多少个Tq,就可以确定 CAN 通讯的波特率。
位时序
为了实现位同步,在STM32数据手册中通过将标称位时间划分为以下三段
- 同步段 (SYNC_SEG):位变化应该在此时间段内发生。它只有一个时间片的固定长度 (1 x tCAN)
- 位段 1 (BS1):定义采样点的位置。它包括 CAN 标准的 PROP_SEG 和 PHASE_SEG1。 其持续长度可以在 1 到 16 个时间片之间调整,但也可以自动加长,以补偿不同网络节 点的频率差异所导致的正相位漂移。
- 位段 2 (BS2):定义发送点的位置。它代表 CAN 标准的 PHASE_SEG2。其持续长度可 以在 1 到 8 个时间片之间调整,但也可以自动缩短,以补偿负相位漂移。
?关于同步,还有硬件同步、再同步等操作。更多关于位时序的内容可以参看 ISO 11898 标准。
帧类型、作用及格式
为了更有效地控制通讯,CAN 一共规定了 5 种类型的帧:
我们在这里主要介绍一下数据帧
数据帧
数据帧由 7 个段构成:
- 帧起始:表示数据帧开始的段.
- 仲裁段:表示该帧优先级的段。
- 控制段:表示数据的字节数及保留位的段。
- 数据段:数据的内容,可发送 0~8 个字节的数据。
- CRC段:检查帧的传输错误的段。
- ACK段:表示确认正常接收的段。
- 帧结束:表示数据帧结束的段。
帧起始
表示帧开始的段。1 个位的显性位。
仲裁段
表示数据的优先级的段。
标准格式和扩展格式在此的构成有所不同。
控制段
控制段由 6 个位构成,表示数据段的字节数。标准格式和扩展格式的构成有所不同。
数据段
数据段可包含 0~8 个字节的数据。从 MSB(最高位)开始输出。
CRC段
CRC 段是检查帧传输错误的帧。由 15 个位的 CRC 顺序和 1 个位的 CRC 界定符(用于分隔的位)构成。
ACK段?
?ACK 段用来确认是否正常接收。由 ACK 槽(ACK Slot)和 ACK 界定符 2 个位构成。
帧结束?
?帧结束是表示该该帧的结束的段。由 7 个位的隐性位构成。
STM32CAN外设
?从图上我们可以看到,CAN 1与CAN 2为主从关系,CAN 1为Master ( 主 ) ,CAN 2为Slave ( 从 ) 。CAN 1和CAN 2有各自的3个发送邮箱,2个FIFO Buffer缓冲,6个接收邮箱。但是,28个Filter 过滤器却是共用的,我们可以规定,哪些Filter给那个CAN用,甚至可以在程序运行的时候调控。
● CAN1:主 bxCAN,用于管理 bxCAN 与 512 字节 SRAM 存储器之间的通信。
● CAN2:从 bxCAN,无法直接访问 SRAM 存储器。
● 两个 bxCAN 单元共享 512 字节 SRAM 存储器
?CAN 发送邮箱
CAN 1和CAN 2有各自的3个发送邮箱,最多可以缓存 3 个待发送的报文。
为了发送消息,程序必须在请求发送之前选择一个空的发送邮箱,使邮箱退出空的状态,进入挂起状态。此时,对于挂起的邮箱,软件无法再对其访问。进入挂起状态后,优先级高的邮箱将优先发送。发送后的邮箱将恢复到空的状态。
?CAN 接收 FIFO
?为了接收 CAN 消息,提供了构成 FIFO 的三个邮箱。为了节约 CPU 负载,FIFO 完全由硬件进行管理。应用程序通过 FIFO 输出邮箱访问 FIFO 中所存储的消息。
?有效消息
当消息依据 CAN 协议正确接收并且成功通过标识符筛选后,该消息将视为有效。
?接收处理
当接收到报文时,FIFO 的报文计数器会自增,而 STM32 内部读取 FIFO 数据之后,报文计数器会自减,我们通过状态寄存器可获知报文计数器的值
上溢
?标识符筛选
?在 CAN 协议中,消息的标识符与节点地址无关,但与消息内容有关。因此,发送器将消息广播给所有接收器。在接收到消息时,接收器节点会根据标识符的值来确定软件是否需要该消息。STM32 的 CAN 外设接收报文前会先使用验收筛选器检查,只接收需要的报文到 FIFO 中。
CAN1与CAN2整体逻辑
CAN2 外设的结构与 CAN1 外设是一样的,他们共用筛选器且由于存储访问控制器由 CAN1 控制,所以要使用 CAN2 的时候必须要使能 CAN1 的时钟。
HAL库函数
HAL_StatusTypeDef HAL_CAN_ActivateNotification(CAN_HandleTypeDef *hcan, uint32_t ActiveITs);
- 参数
hcan :指向CAN配置结构体ActiveITs :表明哪个中断会被启动,开启改中断的消息提示
- 返回值
HAL_StatusTypeDef :如果开启成功,返回HAL_OK ;如果失败,返回HAL_ERROR
HAL_StatusTypeDef HAL_CAN_Start(CAN_HandleTypeDef *hcan);
- 参数
- 返回值
HAL_StatusTypeDef :如果开启成功,返回HAL_OK ;如果失败,返回HAL_ERROR
HAL_StatusTypeDef HAL_CAN_ConfigFilter(CAN_HandleTypeDef *hcan, CAN_FilterTypeDef *sFilterConfig);
- 参数
hcan :指向CAN配置结构体sFilterConfig :指向Filter过滤器配置结构体
- 返回值
HAL_StatusTypeDef :如果开启成功,返回HAL_OK ;如果失败,返回HAL_ERROR
HAL_StatusTypeDef HAL_CAN_AddTxMessage(CAN_HandleTypeDef *hcan, CAN_TxHeaderTypeDef *pHeader, uint8_t aData[], uint32_t *pTxMailbox);
- 参数
hcan :指向CAN配置结构体pHeader :指向发送数据的配置结构体aData[] :指向需要发送的数据pTxMailbox :该函数会返回用于储存发送数据的发送邮箱编号到该变量
- 返回值
HAL_StatusTypeDef :如果添加成功,返回HAL_OK ;如果失败,返回HAL_ERROR
uint32_t HAL_CAN_IsTxMessagePending(CAN_HandleTypeDef *hcan, uint32_t TxMailboxes);
- 参数
hcan :指向CAN配置结构体TxMailboxes :指向发送数据的发送邮箱
- 返回值
uint32_t :如果有发送数据正在等待发送,返回1 ;如果没有,返回0
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan);
- 在写代码的时候,在
main.c 中创建HAL_CAN_RxFifo0MsgPendingCallback 函数 - 在该函数中填写在FIFO 0中已经没有正在等待接收的数据的时候开启中断,需要执行的代码
HAL_StatusTypeDef HAL_CAN_GetRxMessage(CAN_HandleTypeDef *hcan, uint32_t RxFifo, CAN_RxHeaderTypeDef *pHeader, uint8_t aData[]);
- 参数
hcan :指向CAN配置结构体RxFifo :指向负责接收的FIFOpHeader :指向接收数据的配置结构体aData[] :指向需要接收的数据
- 返回值
HAL_StatusTypeDef :如果接收成功,返回HAL_OK ;如果失败,返回HAL_ERROR
|