1、协议简介
CAN协议是半双工的。
CAN是控制器局域网络( Controller Area Network )的简称,他是由研发和生产汽车电子产品著称的德国BOSCH(博世)公司开发,最终成为国际标准(ISO11519)。
CAN总线协议成为汽车计算机控制系统和嵌入式工业控制局域网的总线标准,并且拥有以CAN为底层协议专为大型货车和重工机械车辆设计的J1939协议。
2、CAN物理层
和IIC、SPI通讯方式不同,CAN通讯不以时钟信号来同步,是一种异步的通讯方式,是由CAN_High和CAN_Low两条信号线,这两条线共同构成一组差分信号线,以差分信号的形式通讯
CAN的物理层特性主要分为闭环总线和开环总线网络两种,前者适用高速通讯,后者适用远距离传输
1、闭环总线网络
CAN闭环总线网络是一种遵循ISO11898标准的高速、短距离网络,他的总线最大长度为40米,通讯速度最高位1Mbps,总线的两端各要求有一个120Ω的电阻
2、差分信号
CAN_High和CAN_Low组成一组差分信号。
差分信号又称差模信号,与传统使用单根信号线的电压表示逻辑有所不同,使用差分信号传输时,需要两根信号线,这两根线振幅相等、相位相反 ,通过两根线的电压差值来表示 0 和 1
1、差分信号的优点
- 和单根线传输相比,,抗干扰能力强,当外界突然有强电场的时候,会同时影响两根线的电压值,而不会对差分信号造成影响。例如共模噪声可以被完全抵消。
- 有效抑制外部的电磁干扰,同样的道理,由于两根信号的极性相反,他们对外辐射的电磁场可以抵消,耦合的越紧密泄放到外界的电磁能量越少
- 时序定位精确,由于差分信号的开关变化是位于两个信号的交点,而不像普通的单端信号依靠高低电压的两个阀值,因而受工艺、温度的影响小,能降低时序上的误差,同时也更适合低幅度信号的电路
- 由于差分信号具有这些优点,所以在USB协议、485协议、以太网、以及CAN协议的物理层,都使用了差分信号传输。
2、CAN协议中的差分信号
在CAN总线中,必须使它处于隐性电平(逻辑1)或者显性电平(逻辑0)中的一个状态,假如有两个通讯结点,在同一时间,一个输出显性电平,另一个输出隐性电平,这是总线将处于显性电平状态。线与或者高阻态的意思,只要有0,总线就会被拉低。这是显性、隐性名字的由来。(显性优先)
有点像反逻辑,当差值在 [ -0.5, 0.05 ] 之间,表示隐性的逻辑1,差值在 [ 1.5, 3.0 ]之间为显性的逻辑0。
3、CAN协议层
CAN的协议层规定了通讯逻辑
1、CAN的波特率及同步位
由于CAN协议属于异步通讯,不用时钟线,连接在同一个总线网络的各个节点,会像串口的异步通讯那样,节点之间使用约定好的波特率进行通讯,特别的CAN还会使用位同步的方式来抗干扰,吸收误差,实现对总线电平的正确采样,确保通讯无误。
为了实现 位同步 CAN协议把每个数据位的时序分解成 SS段、PTS段、PBS1段、PBS2段,这四段长度加起来就是一个CAN的数据位长度。把每个数据位的时序分成若干个时间单位,单位是Tq。每一个完整的位由 8~25 个Tq组成。
图中的CAN通讯信号每一个数据位的长度是19Tq,是由SS段、PTS段、PBS1段、PBS2段组成。信号的采样点位于PBS1段和PBS2段之间。
-
SS段:同步段,若通讯结点检测到总线上信号的跳变被包含在SS段的范围之内,则表示结点与总线的时序是同步的。当结点与总线同步时,采样点采集到的总线电平(PBS1段和PBS2段之间)就是该位的电平,SS段大小固定位1Tq。如下图所示,如果没有延时,两个板子晶振一模一样,没有误差,那么电平跳变应该出现在SS段,而图中这个电平变化信号靠后了两个Tq,所以采样点也应该延后两个Tq,在PBS1后延长一个SJW的时间长度进行调整。
-
PTS段:传播时间段,这个时间段用于补偿网络的物理延时时间,一般大小为 1~8Tq。在stm32里这一段与PBS1合并了,不是很重要,了解即可。
-
PBS1段:相位缓冲段,主要用来补偿边沿阶段的误差,它的时间长度在重新同步时可以加长。PBS1段初始大小 1~8Tq。
-
PBS2段:另一个相位缓冲段,也是用来补偿边沿误差的,它的时间长度在重新同步时可以缩短。PBS2段初始大小 2~8Tq。
-
PBS1和PBS2作用是一样的,就是检测总线上电平的跳变是出现在SS段之前还是之后,如果出现在SS段之后,那就加长PBS1段时间,如果出现在SS段之前,那就减小PBS2段的时间。理想状态是不加不减,正好在PBS1和PBS2之间采样。
CAN总线上的各个节点设备,只要约定好1Tq的时间长度,以及一个数据为占多少个Tq,就可以确定CAN的波特率。
-
波特率就是每秒能传输数据位的个数。
比如上图所示,1Tq = 1微秒,每个数据位由19个Tq组成,传输一个数据位需要的时间是19微秒。取到数,换算成秒即为波特率。
2、CAN的报文种类及结构
使用CAN协议进行通讯时,需要的数据,操作命令(读写等)、以及同步信号进行打包,打包后的这些内容称为报文。
报文的种类:
帧 |
帧用途 |
数据帧 |
结点向外传送数据 |
遥控帧 |
向远端结点请求数据 |
错误帧 |
向远端结点通知校验错误,请求重新发送上一个数据 |
过载帧 |
通知远端结点,本节点尚未做好接受准备 |
间隔帧 |
将数据帧及遥控帧与前面的帧分离开来 |
结构:
- 数据帧的类型:
数据帧是最复杂的,包含了标准数据帧和扩展数据帧。数据帧以一个显性位(逻辑0)开始,以7个连续的隐性位结束。数据帧分别有仲裁段、控制段、数据段、CRC段、ACK段。
在这需要注意的是一个数据帧就是一个数据包,一个数据包包含了多个数据位,而一个数据位包含了SS段、PBS段、等等,也就是一个数据位包含了多个Tq,而Tq是时间单位
- 帧起始(SOF):帧起始只有一个数据位构成,是一个显性电平,用于通知其他各个节点,将要有数据传输,其他帧结点通过起始信号的电平跳变来进行硬同步。
- 仲裁段:当检测到起始信号时,说明有数据过来了,准备接收,但是是否接收呢还是由仲裁段来判断是否接受。当有两个或者多个报文被发送时,总线会根据仲裁段的内容判断决定哪个数据包能被传输。
仲裁段的内容主要为本数据帧的ID号(标识符),由图可知数据帧有两种格式,标准数据帧和扩展数据帧,主要区别就在仲裁段的ID信息长度不同,标准格式的ID11位,扩展数据帧格式29位,要多出18位
比如结点1和结点2都在发送报文,仲裁段的ID号是11位的,比如说前几个位都是相同的,直到图中黄色位置,结点1报文是隐性电平1,结点2是显性电平0。这时总线会表现出来显性电平0(因为是线与的特性),这时结点1就知道,现在可能是有比我更紧急的命令需要发送,会失去总线的控制权,转为接收。而结点2发现自己发送的和总线接受的还是相同的电平,所以仍然继续发送。可以看出来ID号越小,优先级越高。
- RTR位:远程传输请求位。他是用于区分数据帧和遥控帧的,显性电平时表示数据帧,否则就是遥控帧。对于一些设备,可发送可接受,它们的ID号手机一样的,如果是发送那RTR位就是0,标准数据帧。如果是接收,RTR位就是1,用于接收远端的数据。可以看出来对于同一个设备,数据帧的优先级要高于遥控帧
- IDE位:标识符扩展位,也叫ID号扩展位。用于区分标准格式还是扩展格式,显性电平时是标准格式、隐性电平时为扩展格式。
- SRR位:只存在于扩展格式中,用于替代标准格式中的RTR位,不同的是,都是表示数据帧时,SRR为隐性位,RTR为显性位,所以在两个ID号相同的标准格式报文与扩展格式报文中,标准格式报文优先级高。
- 控制段:r1和r0都是保留位,没有用,默认是显性电平。最主要的是DLC段:数据长度代码。它表示数据段能发送的字节个数,虽然说DCL段有4个数据位表示,最大能表示16,但是受数据段长度影响,数据段最大只能发送8个字节,所以DCL的最大值只能是8
- 数据段:数据段是整个数据帧的核心内容,是要发送的信息。最大可发送8个字节。MSB先行。
- CRC段:校验段。为了保证信息的正确传输,在CAN的报文中包含了15位的CRC校验码,一旦接收结点接收的CRC校验码和算出的CRC校验码不同,会想发送结点反馈错误信息,利用错误帧请求重新发送。在CRC之后还有一个CRC定界符,为隐性位,主要作用是把CRC校验码和后边的ACK应答信号隔开。
- ACK段:应答段。包含一个ACK槽位和一个ACK定界符位,和IIC的ACK类似,在ACK槽位中发送结点发送的是隐性电平,而接收结点在这一位中发送出显性位表示应答,在ACK槽和帧结束之间用ACK界定符隔开
4、STM32中CAN协议
STM32芯片具有bxCAN基本控制器,它支持CAN协议的2.0A和2.0B标准。2.0A不支持扩展帧,2.0B支持扩展帧
CAN控制器支持最高速率1Mb/s,可以实现自动接收和发送CAN报文,支持标准数据帧和扩展数据帧。外设中具有三个发送邮箱,发送报文的优先级可以使用软件控制,还可以记录发送的时间。具有2个3级深度的接收FIFO,共可以存放6个完整的报文段。可以使用过滤功能帧接收或者不接收某些ID号的报文。可配置自动重发、但是不支持DMA数据收发。
1、功能框图——主控器、主动核心
1、总体概念、总体描述
- CAN 2.0B主动核心:是CAN的控制内核,控制工作状态、工作模式、等等
- CAN发送邮箱:发送邮箱是一个缓存,有三个,要发送的数据先放在发送邮箱中,多个结点同时发送报文会有总线竞争。等总线空闲了就可以发送了。
- 接收接收FIFO:有两组,一共有6个。
- 接收滤波器:这个可以筛选ID,想要或者不想要的报文ID可以直接删选掉,只留下自己想要的。
STM32f103只有一个CAN设备,CAN1,105或者107才有CAN2
2、CAN的控制内核(CAN的控制和状态寄存器)
- DBF调试冻结功能:就是在使用mdk debug的时候是否禁止访问FIFO中的数据,可以设置这一位。
- TTCM时间触发模式:没有用到。用于配置CAN的时间触发通信模式,在此模式下,CAN会记录一些时间,会把这些报文的发送时间,接收时间分别保存在 CAN_RDTxR 和 CAN_TDTXRT寄存器中
- ABOM自动离线管理:需要注意的是,不管是否设置该位,都会进入离线模式,只不过处理方式不同。当发送结点的时候,如果一直错误,或者错误量超过一定值得时候,会进入自动离线状态,可以通过软件控制或者直接使用这个自动离线管理功能,他会在适当的时候自己恢复。
- AWUM自动唤醒功能:CAN外设可以软件使其进入低功耗的睡眠模式,如果使能了这个自动唤醒,当CAN检测到总线处于活动状态的时候会自动唤醒。
- NART自动重传:设置这个功能当报文发送失败后会自动重传,直到成功。若关闭则只发送一次。
- RFLM锁定模式:锁定FIFO,stm32的FIFO一共有6个。当6个邮箱全部存满时,如果这时锁定了FIFO,就会丢弃后来的报文。如果不锁定,新报文就会覆盖就报文,覆盖最旧的那个报文。
- TXFP报文发送优先级的判定方法:当有多个结点同时发送报文的时候(就是发送邮箱有多个等待发送的报文的时候),可以选择优先级是根据ID号还是存进邮箱的顺序来发送。
3、CAN的工作模式——四种
CAN的工作模式由CAN的时序寄存器的两个位决定,两个位共决定四种状态。两个位控制CAN的工作模式。
CAN的四种工作模式:
- 正常模式:就是最正常的模式,可以向总线发送数据也可以从总线接收数据。
- 静默模式:发送端在内部直接连接输出端,并且只有 == 1的时候才会发送数据到总线,但是能一直接收。只能向总线发送1,逻辑1是隐性位,它不会影响总线的状态。一般用于测试发送的数据对不对。
- 回环模式:能够向总线上发送数据,也是直接连接到接收端,但是总线上的数据不能被接收端接收,不接收总线上的内容。主要用于自检。
- 回环静默模式:不向总线上发送,也不从总线上接收,发送端直接连接内部的接收端,用于热自检。
4、stm32的位时序和波特率
CAN的标准协议和stm32协议的不同点就是,stm32把PTS和PBS1段合二为一了统一叫PBS1段
用下面这些寄存器来配置波特率、PBS1段、PBS2段。时间单位是Tq。
我们知道一个数据位包含若干个Tq,它是由SS段、PBS1段、PBS2段组成。配置完这三个时间之后可以得到整个数据位的时间,也就是整个数据位占多少个Tq。
其中tcan就是Tq,就是那个最小的时间单位
下面提供一种把波特率配置成1Mbps的方法
参数 |
说明 |
SS段 |
固定为1Tq |
PBS1段 |
设置为5Tq (实际TS1写入的值为4) |
PBS2段 |
设置为3Tq (实际TS1写入的值为2) |
Tpclk |
CAN是挂载在APB1上的,频率36MHZ,周期T= 1/36MHZ |
设置1Tq的时间长度 |
Tq = (3 + 1) * 1/36MHZ = 1/9 微妙 |
1位的时间长度 |
SS + PBS1 + PBS2 = 1Tq + 5Tq + 3Tq = 9Tq = 1微秒 |
波特率 |
计算每秒传输数据位的个数:1位需要9微妙的时间,波特路就是取到数, = 1MHZ |
5、CAN的发送邮箱
CAN一共有三个发送邮箱、最多可以缓冲三个等待发送的报文。
每个发送邮箱都有标识符寄存器、数据长度控制寄存器和两个数据寄存器,作用如下:
寄存器名 |
功能 |
标识符寄存器 |
存储待发送报文的ID、扩展ID、IDE、RTR位 |
数据长度控制寄存器 |
存储待发送报文的DCL段 |
低位数据寄存器 |
存储发送报文数据段的低4个字节 |
高位数据寄存器 |
存储发送报文数据段的高4个字节 |
向邮箱中写完数据需要使能发送请求
6、CAN的接收FIFO
CAN一共有两个接收FIFO,每个FIFO有三个邮箱,最多可以缓存6个收到的报文,当接收报文时FIFO的报文计数器会自增,而stm32内部读取FIFO数据之后,报文计数器会自减,通过状态寄存器可获知当前计数器的值,而在前面主控制寄存器的RFLM位,可以设置锁定模式,前边已经说过了,在锁定模式下,接收的新的报文会被丢弃,非锁定模式下会覆盖旧的报文。
CAN的发送邮箱和接收邮箱的结构是类似的,同样是那个表格,把发送邮箱各个段的数据放到接收邮箱中,不在画表。
7、验收筛选器
对于103系列,CAN的外设验收筛选器一共有14个筛选器组,每个筛选器组有两个寄存器,CAN1和CAN2共用的筛选器。
对于其他更高级的系列有28个筛选器组。
在CAN的协议中消息的标识符与结点的地址无关,但是与消息的内容有关,因此发送节点将报文广播给所有接收器时,接收结点会根据标识符(ID号)的值来确定该节点是否需要接收消息,为了简化软件工作,stm32CAN外设接收报文之前会先使用筛选器选择检查,只接受需要的报文到FIFO中。
筛选器工作的时候,可以调整筛选ID的长度以及过滤模式
根据筛选ID长度来分类:
- 检查STDID[10:0]、EXTID[17:0]、 IDE、RTR位,一共31位。
- 检查STDID[10:0]、EXTID[17:15]、IDE、RTR位,一共16位。
如果使用第一种模式,配置的是如下寄存器,一共28个筛选器组,每一个组可以由两个16位的寄存器组成,但是也可以配置成一个32位的,它由FS1R寄存器决定
根据过滤的方法可以分成以下两种模式:
- 标识符列表模式:要把接收的报文ID列成一个表,要求报文ID与列表中的标识符完全相同,才可以接收,作为筛选条件
- 掩码模式:把可接受报文ID某几位作为列表,这几位被称为掩码,可以理解为关键字搜索,只要掩码相同,就符合筛选要求,就可以接收报文。
**所以两种过滤模式两两组合,可以有4种筛选模式: (重点、难点) **
- 当FSC(滤波器的位宽)配置成32位的时候,并且使用标识符列表模式时,对于某一个寄存器组,它的两个32位寄存器(FxRx)的每个位都要一一对应。
- 当FSC(滤波器的位宽)配置成32位的时候,并且使用标识符掩码模式时,因为是筛选ID的某些位,我们在FxR2中把必须要匹配的位置1,在FxR1中对应FxR2,把FxR2中为1的ID抄写到FxR1中,FxR2为0的位不是筛选位,FxR1中就能随便写。
- 16位的模式大同小异,看表可知。就是把32位的寄存器分成两组来用了。
筛选器举例:我的ID如表所示,如果采用掩码模式,我把对应想要筛选的ID置1,在另一个寄存器中就可得到筛选之后的ID,就是掩码为1的ID不能变,掩码为0的ID,不重要,可随便写。
ID |
1 |
0 |
1 |
1 |
1 |
0 |
1 |
… |
掩码 |
1 |
1 |
1 |
0 |
0 |
0 |
1 |
… |
筛选的ID |
1 |
0 |
1 |
x |
x |
0 |
x |
… |
5、stm32 CAN初始化结构体讲解
CAN外设功能比较多,所以结构体也相对复杂,主要分成三种结构体
- 初始化结构体:CAN_InitTypeDef,主要配置波特率、每个位有多长等等。
- 发送以及接受结构体:CanTxMsg 和 CanRxMsg ,配置发送和接受的邮箱
- 筛选器结构体:CAN_FilterInitTypeDef
- CAN_Prescaler:分频器,配置配置时序寄存器的BRR位,大小为10位,设置的范围是11024,在古剑库配置的时候,会把你配置的值减1在写入BRR,所以范围就成了11024,而不是0~1023.
- CAN_Mode:设置CAN的四种工作模式,前边也写过了,实际是配置的两个寄存器位。
- CAN_SJW、CAN_BS1、CAN_BS2:这三个是一回事,SJW的值就是重新同步的量,BSx就是加减SJW之后的值
- CAN_TTCM:设置是否使用时间触发功能,时间触发功能在某些CAN的标准中会用到,这不使用
- CAN_ABOM:自动离线管理,前边介绍过了。
- 后边几个和前一个类似,没什么难理解的,都在主控控制寄存器中可以配置,前边也都介绍过了。
发送报文的结构体,里边定义了一个报文的各个段。使用CAN_Transmit函数初始化函数
- StdId、ExtId:是ID号的种类,这俩只能有一个有效,具体由IDE位控制,IDE就是来区别到底是标准帧还是扩展帧
- RTR:控制该帧是数据帧还是遥控帧。遥控帧就是是否需要从总线上接收数据。当配置成遥控帧时很显然数据DATA是无效的
下面是接收结构体,就是反过来了,一模一样,不在赘述。使用CAN_Receive函数初始化
CAN的筛选器结构体:重点难点,在细写一遍最后调用CAN_FilterInit函数
- 当筛选器工作在32位的标识符列表时:IdHigh 和 IdLow分别存储的是ID1的高16位和低16位。MaskIdHigh和MaskIdLow存储ID2的高16位和低16位。
- 当筛选器工作在16的标识符列表时:也就是2个32位的寄存器被砍成了4个16位的寄存器,四个寄存器存放的是完整的ID值。所以在这种模式下,可以存放四个ID号,ID1、ID2、ID3、ID4。在最后一组寄存器中,上边就是IdHigh 和 IdLow,下边俩就是MaskIdHigh和MaskIdLow
- 当筛选器工作在32的标识符掩码时:带Mask的存放的是掩码,不带mask的存放的是筛选之后的ID,32位的很好理解了最上边一行就是IdHigh 和 IdLow,下一行就是MaskIdHigh和MaskIdLow
- 当筛选器工作在16的标识符掩码时:它的第一行是IdHigh,第二行是MaskIdHigh。第三行IdLow,第四行MaskIdLow。因为mask是存放掩码的。在这个模式下IdHigh和MaskIdHigh组成一组,另一对组成一组
模式 |
CAN_IdHigh |
CAN_IdLow |
CAN_MaskIdHigh |
CAN_MaskIdLow |
32位标识符列表模式 |
ID1的高16位 |
ID1的低16位 |
ID2的高16位 |
ID2的低16位 |
16位标识符列表模式 |
ID1的完整数值 |
ID2的完整数值 |
ID3的完整数值 |
ID4的完整数值 |
32位标识符掩码模式 |
ID1的高16位 |
ID1的低16位 |
ID1掩码的高16位 |
ID1掩码的低16位 |
16位标识符掩码模式 |
ID1的完整值 |
ID2的完整值 |
ID1掩码的完整值 |
ID2掩码的完整值 |
- CAN_FilterMode:设置筛选器模式,列表模式还是掩码模式,通过过滤器模式寄存器配置。
- 最后一个参数是是否使用这个筛选器。都行,看情况。