CAN——Controller Area Network
应用背景:CAN 总线协议已经成为汽车计算机控制系统和嵌入式工业控制局域网的标准总线,并且拥有以 CAN 为底层协议专为大型货车和重工机械车辆设计的 J1939协议。近年来,它具有的高可靠性和良好的错误检测能力受到重视,被广泛应用于汽车计算机控制系统和环境温度恶劣、电磁辐射强及振动大的工业环境。
物理层
CAN通讯是异步通讯,只具有 CAN_High 和 CAN_Low 两条信号线,共同构成一组差分信号线,以差分信号的形式进行通讯。
开环总线网络(低速、远距离)
闭环总线网络(高速、短距离)
收发器涉及 逻辑电平信号与差分信号的相互转换
利用CAN_High和CAN_Low的电位差代表逻辑1/0
优点:抑制噪声、抑制电磁干扰、时序定位精确
(USB 协议、485 协议、以太网协议及 CAN 协议的物理层中,都使用了差分信号传输)
隐性电平(逻辑 1)或显性电平(逻辑 0) 显性电平优先
CAN 通讯是半双工的,收发数据需要分时进行。
CAN通讯因为共用总线,在整个网络中同一时刻只能有一个通讯节点发送信号,其余的节点在该时刻都只能接收。
协议层
1.位时序分解
为了实现位同步,CAN 协议把每一个数据位的时序分解成SS 段、PTS 段、PBS1 段、PBS2 段,这四段的长度加起来即为一个 CAN 数据位的长度。分解后最小的时间单位是 Tq,而一个完整的位由 8~25 个 Tq 组成。
SS段固定为1Tq,PTS 段的大小可以为 1~8Tq,PBS1段的初始大小可以为 1~8Tq,PBS2 段的初始大小可以为 2~8Tq。
2.同步的判断:
若通讯节点检测到总线上信号的跳变沿被包含在 SS 段的范围之内,则表示节点与总线的时序是同步的。
3.通讯的波特率:
总线上的各个通讯节点只要约定好 1 个 Tq 的时间长度以及每一个数据位占据多少个Tq,就可以确定 CAN 通讯的波特率。
每秒可传输的数据位的个数即为通讯中的波特率
4.同步过程:
若某个 CAN 节点通过总线发送数据时,它会发送一个表示通讯起始的信号(帧起始信号),该信号是一个由高变低的下降沿。而挂载到 CAN 总线上的通讯节点在不发送数据时,会时刻检测总线上的信号。
硬同步:把自己的位时序中的 SS段平移至总线出现下降沿的部分,但只是当存在帧起始信号时才起作用。
重新同步:相位超前:下一个位时序中的 PBS1 段增加时间长度
相位滞后:上一个位时序中的 PBS2 段减少时间长度
5.SPI 通讯中,片选、时钟信号、数据输入及数据输出这 4 个信号都有单独的信号线,
I2C 协议包含有时钟信号及数据信号 2 条信号线,异步串口包含接收与发送 2 条信号线,
而 CAN 使用的是两条差分信号线,只能表达一个信号,如何用一个信号通道实现同样、甚至更强大的功能呢?
CAN协议给出的解决方案是对数据、操作命令(如读/写)以及同步信号进行打包,打包后的这些内容称为报文。
着重了解数据帧的结构:
显性位(逻辑 0)开始、仲裁段、控制段、数据段、CRC段、ACK段、7 个连续的隐性位(逻辑 1)结束
(1)仲裁段的内容主要为本数据帧的 ID 信息(标识符),①I**D决定着数据帧发送的优先级(即当同时有两个报文被发送时,总线会根据仲裁段的内容决定哪个数据包能被传输) ② ID也决定着其它节点是否会接收这个数据帧。
CAN 协议不对挂载在它之上的节点分配优先级和地址,对总线的占有权是由信息的重要性决定的,即对于重要的信息,我们会给它打包上一个优先级高的 ID,使它能够及时地发送出去。也正因为它这样的优先级分配
原则,使得 CAN 的扩展性大大加强,在总线上增加或减少节点并不影响其它设备。**
仲裁过程:若两个节点同时竞争 CAN 总线的占有权,当它们发送报文时,若首先出现隐性电平,则会失去对总线的占有权,进入接收状态。(总线的“线与”特性)
因为在 CAN 总线上数据是以广播的形式发送的,所有连接在 CAN 总线的节点都会收到所有其它节点发出的有效数据,因而我们的 CAN 控制器大多具有根据 ID 过滤报文的功能,它可以控制自己只接收某些 ID的报文。
仲裁段还包括:
RTR位(Remote Transmission Request Bit),译作远程传输请求位,它是用于区分数据帧和遥控帧的,当它为显性电平时表示数据帧,隐性电平时表示遥控帧。
IDE 位(Identifier Extension Bit),译作标识符扩展位,它是用于区分标准格式与扩展格式,当它为显性电平时表示标准格式,隐性电平时表示扩展格式。
(2)控制段
在控制段中的 r1 和 r0 为保留位,默认设置为显性位。它最主要的是 DLC 段(DataLength Code),译为数据长度码,它由 4个数据位组成,用于表示本报文中的数据段含有多少个字节,DLC段表示的数字为 0~8。
(3)数据段为数据帧的核心内容,它是节点要发送的原始信息。
(4)CRC段
CAN 的报文包含了一段 15 位的 CRC 校验码,一旦接收节点算出的 CRC 码跟接收到的 CRC 码不同,则它会向发送节点反馈出错信息,利用错误帧请求它重新发送。CRC 部分的计算一般由 CAN 控制器硬件完成,出错时的处理则由软件控制最大重发数。
STM32的CAN控制器
主控制寄存器 CAN_MCR 负责管理 CAN 的工作模式
位时序寄存器 CAN_BTR 用于配置测试模式、波特率以及各种位内的段参数。
STM32 的 CAN 提供了测试模式,使用它是不需要修改硬件接线的。
但实际应用时,需要输出数据到总线或从总线接收数据,才会经过 CAN_Tx/Rx 引脚和收发器。
STM32 的 CAN 外设位时序和标准CAN位时序有一些不同,STM32中只包含 3段,分别是同步段 SYNC_SEG、位段 BS1及位段 BS2,而采样点位于 BS1 及 BS2 段的交界处。其中 SYNC_SEG 段固定长度为 1Tq,而BS1 及 BS2 段可以在位时序寄存器 CAN_BTR 设置它们的时间长度,它们可以在重新同步期间增长或缩短,该长度 SJW也可在位时序寄存器中配置。
理解: BS1 段是由前面介绍的标准协议中 PTS段 与 PBS1段 合在一起的,而 BS2段 就相当于 PBS2段。
CAN 通讯的波特率:BaudRate = 1/N Tq
发送邮箱:
当我们要使用 CAN 外设发送报文时,把报文的各个段分解,按位置写入到这些寄存器中,并对标识符寄存器 CAN_TIxR 中的发送请求寄存器位 TMIDxR_TXRQ 置 1,即可把数据发送出去。
我们可设置FIFO锁定模式,锁定模式下 FIFO 溢出时会丢弃新报文,非锁定模式下 FIFO 溢出时新报文会覆盖旧报文。
验收筛选器:
STM32 的 CAN 外设接收报文前会先使用验收筛选器检查,只接收需要的报文到 FIFO 中。
根据过滤的方法分为以下两种模式:
(1) 标识符列表模式,它把要接收报文的 ID 列成一个表,要求报文 ID 与列表中的某一个标识符完全相同才可以接收,可以理解为白名单管理。
(2) 掩码模式,它把可接收报文 ID 的某几位作为列表,这几位被称为掩码,可以把它理解成关键字搜索,只要掩码(关键字)相同,就符合要求,报文就会被保存到接收 FIFO。
注意:在 32 位的 ID 中,第 0 位是保留位,第 1 位是 RTR 标志,第 2 位是IDE 标志,从第 3位起才是报文的 ID(扩展 ID)。
CAN_FilterMaskIdHigh
CAN_FilterMaskIdHigh 存储的内容分两种情况,当筛选器工作在标识符列表模式时,它的功能与 CAN_FilterIdHigh 相同,都是存储要筛选的 ID;而当筛选器工作在掩码模式时,它存储的是 CAN_FilterIdHigh 成员对应的掩码,与 CAN_FilterIdLow 组成一组筛选器。
CanRxMsg RxMessage;
CanTxMsg TxMessage; //接收/发送结构体定义
当需要使用 CAN 发送报文时,先定义一个上面发送类型的结构体,然后把报文的内容按成员赋值到该结构体中,最后调用库函数 CAN_Transmit 把这些内容写入到发送邮箱即可把报文发送出去。
接收报文时,通过检测标志位获知接收 FIFO 的状态,若收到报文,可调用库函数CAN_Receive 把接收 FIFO 中的内容读取到预先定义的接收类型结构体中,然后再访问该结构体即可利用报文了。
发送:
CAN_SetMsg(&TxMessage);//初始化发送数据的结构体 具体需要配置ID、IDE位、RTR位和要发的数据
CAN_Transmit(CAN1,&TxMessage);//发送数据
接收(有中断):
#define CAN_RX_IRQHandler USB_LP_CAN1_RX0_IRQHandler
void CAN_RX_IRQHandler(void)
{
CAN_Receive(CANx, CAN_FIFO0, &RxMessage);
//可以进行比较来判断收到的数据是否正确
if ((RxMessage.ExtId==0x1314) && (RxMessage.IDE==CAN_ID_EXT) && (RxMessage.DLC==8) )
……
}