首页 > 技术文章 > CAN总线

zhouyuqing1024 2019-11-14 20:29 原文

CAN 是什么?
CAN 是 Controller Area Network 的缩写(以下称为 CAN),是 ISO国际标准化的串行通信协议。

在当前的汽车产业中,出于对安全性、舒适性、方便性、低公害、低成本的要求,各种各样的电子控制系统
被开发了出来。由于这些系统之间通信所用的数据类型及对可靠性的要求不尽相同,由多条总线构成的情况很
多,线束的数量也随之增加。为适应“减少线束的数量”、“通过多个 LAN,进行大量数据的高速通信”的需
要,1986 年德国电气商博世公司开发出面向汽车的 CAN 通信协议。此后,CAN 通过 ISO11898 及 ISO11519 进
行了标准化,现在在欧洲已是汽车网络的标准协议。
现在,CAN 的高性能和可靠性已被认同,并被广泛地应用于工业自动化、船舶、医疗设备、工业设备等方面。
图 1 是车载网络的构想示意图。CAN 等通信协议的开发,使多种 LAN 通过网关进行数据交换得以实现。

总线拓扑图
 CAN-bus 主要特性 

1) 多主控制。
 在总线空闲时,所有的单元都可以开始发送消息(多主控制)。
 最先访问总线的单元可获得发送权。
 多个单元同时发送时,发送高优先级 ID 消息的单元可获得发送权。
2) 消息的发送

在 CAN 协议中,所有的消息都以固定的格式发送。总线空闲时,所有与总线相连的单元都可以
开始发送新的消息。两个以上的单元同时发送消息是,根据标示符(Identifier 以下称 ID)决定
优先级。ID 并不是发送的目的地址,而是表示访问总线的消息的优先级。两个以上的单元同时
开始发送消息时,对各消息 ID 的每个位进行逐个仲裁。仲裁获胜(被判定为高优先级)的单元
可继续发送消息,仲裁失利的单元则立刻停止发送而转为接收模式。

3) 系统的柔软性
 与总线相连的单元没有类似于“地址”的信息,因此在总线上增加单元时,连接在总线上的其他单
元的软硬件及应用层都不需要改变。
4) 通信速度
 根据网络的规模,可设置合适的通信速度。在同一网络中,所有单元必须设置统一的通信速度。
5) 远程数据请求
 任意单元都可以发送“遥控帧”来请求其他单元发出数据。
6) 错误检测功能—错误通知功能—错误恢复功能
 所有单元都可检测错误(检测功能)。  检测出错的单元会立即通知其他所有单元(错误通知功能)。
 发送出错的单元,会立即停止当前发送,并不断重新发送此消息,直到发送成功为止(错误恢复
功能)。
7) 故障封闭
 CAN 可以判断出错误的类型是总线上暂时的错误(如外部噪声等)还是持续的数据错误(如单
元内部的故障、驱动器故障、断线等)。由此功能,当总线上发生持续数据错误时,可将引起此
故障的单元从总线上隔离出去。
8) 连接
 CAN 总线是可以同时连接多个单元的总线。可连接的单元总数理论上是没有限制的,但实际上
可连接的单元数受总线上的时间延迟及电气负载的限制,降低通信速度,可连接的单元数增加;
提高通信速度,则可连接的单元数减少。

1.4 ISO/OSI 基本参照模型 

 OSI(Open System Interconnect),即开放式系统互联。 一般都叫 OSI 参考模型,是 ISO(国际标准化组织)

组织在 1985 年研究的网络互联模型。该体系结构标准定义了网络互连的七层框架(物理层、数据链路层、网络
层、传输层、会话层、表示层和应用层),即 OSI 开放系统互连参考模型。在这一框架下进一步详细规定了每
一层的功能,以实现开放系统环境中的互连性、互操作性和应用的可移植性。如图 1.2 。
 

 

 

上三层总称应用层,用来控制软件方面。下四层总称数据流层,用来管理硬件。除了物理层之外其他层都
是用软件实现的。数据在发至数据流层的时候将被拆分。在传输层的数据叫段,网络层叫包,数据链路层叫帧,
物理层叫比特流,这样的叫法叫 PDU(协议数据单元)。
1.5 CAN 的分层结构
 
 

 

 

1.6 CAN 总线物理层的定义
CAN 协议经 ISO 标准后,有 ISO11898 标准和 ISO11519-2 标准两种。ISO11898 标准和 ISO11519-2 标准
对数据链路层定义相同,但对物理层定义不同。如图 1.4。
1) 关于 ISO11898
 ISO11898 是通信速度为 125kbps~1Mbps 的 CAN 高速通信标准。
2) 关于 ISO11519
 ISO11519 是通信速度 为 125kbps 以下的的 CAN 低速通信标准。
 

 

 

 

8. CAN 总线协议
8.1 帧的种类
通信是通过以下 5 种类型的帧进行的。
• 数据帧
• 遥控帧
• 错误帧
• 过载帧
• 帧间隔  
另外,数据帧和遥控帧有标准格式和扩展格式两种格式。标准格式有 11 个位的标识符(Identifier: 以下称 ID),
扩展格式有 29 个位的 ID。
各种帧的用途如表 7 所示,各种帧的构成如图 11~图 15 所示。
表 7. 帧的种类及用途
帧            帧用途
数据帧   用于发送单元向接收单元传送数据的帧。
遥控帧   用于接收单元向具有相同 ID 的发送单元请求数据的帧。
错误帧   用于当检测出错误时向其它单元通知错误的帧。
过载帧   用于接收单元通知其尚未做好接收准备的帧。
帧间隔   用于将数据帧及遥控帧与前面的帧分离开来的帧。

 

 

 

 

 

 

 

 

8.2 数据帧
数据帧由 7 个段构成。
数据帧的构成如图 16 所示。
(1) 帧起始
表示数据帧开始的段。
(2) 仲裁段
表示该帧优先级的段。
(3) 控制段
表示数据的字节数及保留位的段。
(4) 数据段
数据的内容,可发送 0~8 个字节的数据。
(5) CRC 段
检查帧的传输错误的段。
(6) ACK 段
表示确认正常接收的段。
(7) 帧结束
表示数据帧结束的段。
下面对帧的构成进行说明。

 

 

(1) 帧起始(标准、扩展格式相同)
表示帧开始的段。1 个位的显性位。
总线上的电平有显性电平和隐性电平两种。
总线上执行逻辑上的线“与”时,显性电平的逻辑值为“0”,隐性电平为“1”。
“显性”具有“优先”的意味,只要有一个单元输出显性电平,总线上即为显性电平。并且,“隐
性”具有“包容”的意味,只有所有的单元都输出隐性电平,总线上才为隐性电平。(显性电平比
隐性电平更强。)
显性电平和隐性电平

 (2) 仲裁段

表示数据的优先级的段。
标准格式和扩展格式在此的构成有所不同。
【注】 *1 ID 
标准格式的 ID 有 11 个位。从 ID28 到 ID18 被依次发送。禁止高 7 位都为隐性。
(禁止设定:ID=1111111XXXX)
扩展格式的 ID 有 29 个位。基本 ID 从 ID28 到 ID18,扩展 ID 由 ID17 到 ID0 表示。基本 ID 和
标准格式的 ID 相同。禁止高 7 位都为隐性。(禁止设定:基本 ID=1111111XXXX
【注】 *1 ID
(3) 控制段
控制段由 6 个位构成,表示数据段的字节数。标准格式和扩展格式的构成有所不同。
【注】 *1 保留位(r0、r1)
保留位必须全部以显性电平发送。但接收方可以接收显性、隐性及其任意组合的电平。
*2 数据长度码(DLC)
数据长度码与数据的字节数的对应关系如表 8 所示。
数据的字节数必须为 08 字节。但接收方对 DLC = 915 的情况并不视为错误。
表 8. 数据长度码和字节数的关系
数据长度码
数据字节数
   DLC3  DLC2  DLC1   DLC0 
0     D     D     D     D 
1     D     D     D    R 
2     D     D     R     D 
3     D     D     R     R 
4     D     R     D     D 
5     D     R     D     R 
6     D     R     R     D 
7     D     R     R     R 
8     R     D     D     D 

“D”:显性电平 “R”:隐性电平        
【注】数据长度码(DLC)、、表 8. 数据长度码和字节数的关系
(4) 数据段(标准、扩展格式相同)
数据段可包含 0~8 个字节的数据。从 MSB(最高位)开始输出。
(5) CRC 段(标准/扩展格式相同)
CRC 段是检查帧传输错误的帧。由 15 个位的 CRC 顺序和 1 个位的 CRC 界定符(用于分隔的位)构成。
 
*1 CRC 顺序
CRC 顺序是根据多项式生成的 CRC 值,CRC 的计算范围包括帧起始、仲裁段、控制段、数据
段。
接收方以同样的算法计算 CRC 值并进行比较,不一致时会通报错误。
*1 CRC 顺序
(6) ACK 段
ACK 段用来确认是否正常接收。由 ACK 槽(ACK Slot)和 ACK 界定符 2 个位构成。
发送 ACK
发送 ACK 的是在既不处于总线关闭态也不处于休眠态的所有接收单元中,接收到正常消息的单元(发送单元不发送 ACK)。所谓正常消息是指不含填充错误、格式错误、CRC 错误的消息。
【注】 *1 发送单元的 ACK 段
发送单元在 ACK 段发送 2 个位的隐性位。
*2 接收单元的 ACK 段
接收到正确消息的单元在 ACK 槽(ACK Slot)发送显性位,通知发送单元正常接收结束。这称作“发 送 ACK”或者“返回 ACK”
发送 ACK
(7) 帧结束
帧结束是表示该该帧的结束的段。由 7 个位的隐性位构成。
8.3 遥控帧
接收单元向发送单元请求发送数据所用的帧。遥控帧由 6 个段组成。遥控帧没有数据帧的数据段。
遥控帧的构成如图 24 所示。
(1) 帧起始(SOF)
表示帧开始的段。
(2) 仲裁段
表示该帧优先级的段。可请求具有相同 ID 的数据帧。
(3) 控制段
表示数据的字节数及保留位的段。
(4) CRC 段
检查帧的传输错误的段。
(5) ACK 段
表示确认正常接收的段。
(6) 帧结束
表示遥控帧结束的段。
8.3 遥控帧
• 数据帧和遥控帧的不同
 遥控帧的 RTR 位为隐性位,没有数据段。
 没有数据段的数据帧和遥控帧可通过 RTR 位区别开来。
• 遥控帧没有数据段,数据长度码该如何表示?
 遥控帧的数据长度码以所请求数据帧的数据长度码表示。
• 没有数据段的数据帧有何用途?
 例如,可用于各单元的定期连接确认/应答、或仲裁段本身带有实质性信息的情况下。
遥控帧和数据帧
8.4 错误帧
用于在接收和发送消息时检测出错误通知错误的帧。错误帧由错误标志和错误界定符构成。
错误帧的构成如图 25 所示。
(1) 错误标志
错误标志包括主动错误标志和被动错误标志两种。
 主动错误标志:6 个位的显性位。
 被动错误标志:6 个位的隐性位。
(2) 错误界定符
错误界定符由 8 个位的隐性位构成。
8.4 错误帧 
8.5 过载帧
过载帧是用于接收单元通知其尚未完成接收准备的帧。过载帧由过载标志和过载界定符构成。
过载帧的构成如图 26 所示。
(1) 过载标志
6 个位的显性位。
过载标志的构成与主动错误标志的构成相同。
(2) 过载界定符
8 个位的隐性位。
过载界定符的构成与错误界定符的构成相同。

8.6 帧间隔
帧间隔是用于分隔数据帧和遥控帧的帧。数据帧和遥控帧可通过插入帧间隔将本帧与前面的任何帧(数据帧、
遥控帧、错误帧、过载帧)分开。
过载帧和错误帧前不能插入帧间隔。
帧间隔的构成如图 27 所示。
(1) 间隔
3 个位的隐性位。
(2) 总线空闲
隐性电平,无长度限制(0 亦可)。
本状态下,可视为总线空闲,要发送的单元可开始访问总线。
(3) 延迟传送(发送暂时停止)
8 个位的隐性位。
只在处于被动错误状态的单元刚发送一个消息后的帧间隔中包含的段。
8.5 过载帧 8.6 帧间隔

 

 
8.9 错误的种类
错误共有 5 种。多种错误可能同时发生。
• 位错误
• 填充错误
• CRC 错误
• 格式错误
• ACK 错误
8.11 位时序
由发送单元在非同步的情况下发送的每秒钟的位数称为位速率。一个位可分为 4 段。
• 同步段(SS)
• 传播时间段(PTS)
• 相位缓冲段 1(PBS1)
• 相位缓冲段 2(PBS2)
这些段又由可称为 Time Quantum(以下称为 Tq)的最小时间单位构成。
1 位分为 4 个段,每个段又由若干个 Tq 构成,这称为位时序。
1 位由多少个 Tq 构成、每个段又由多少个 Tq 构成等,可以任意设定位时序。通过设定位时序,多个单元可
同时采样,也可任意设定采样点。
各段的作用和 Tq 数如表 11 所示。1 个位的构成如图 32 所示。
8.14 再同步
在接收过程中检测出总线上的电平变化时进行的同步调整。
每当检测出边沿时,根据 SJW 值通过加长 PBS1 段,或缩短 PBS2 段,以调整同步。但如果发生了超出 SJW
值的误差时,最大调整量不能超过 SJW 值。
 
init_can1(21,11,4,1,0);//-----CAN总线通信速度:125K--16个Tq
/*
函数功能:初始化CAN1
函数形参:brp:分频器;tbs1:时间段1;tbs2:时间段2;tsjw:同步跳转;mode:模式
*/
u8 init_can1(u8 brp, u8 tbs1, u8 tbs2, u8 tsjw, u8 mode)
{
    u16 cnt=0;

    RCC->AHB1ENR|=1<<0;      //使能PORTA口时钟 
    
    GPIOA->MODER &= ~(3<<22);
    GPIOA->MODER |= (2<<22); //PA11 复用功能
    GPIOA->MODER &= ~(3<<24);
    GPIOA->MODER |= (2<<24); //PA12 复用功能 
    
    GPIOA->OTYPER &= ~(3 << 11);//类型  推挽
    
    GPIOA->OSPEEDR &= ~(0xf<< 22);//速度  50M
    GPIOA->OSPEEDR |= 0xa << 22;  
    
    GPIOA->AFR[1] &= ~(0XF << 12);
    GPIOA->AFR[1] |= 9 << 12;  //PA11  can1功能   AF9
    GPIOA->AFR[1] &= ~(0XF << 16);
    GPIOA->AFR[1] |= 9 << 16;  //PA12  can1功能   AF9
    
    
    RCC->APB1ENR |= 1<<25;//使能CAN1时钟 CAN1使用的是APB1的时钟(max:42M)
    
    CAN1->MCR = 0;        //退出睡眠模式(同时设置所有位为0)
    /*     
        非时间触发通信模式
        软件自动离线管理
        睡眠模式通过软件唤醒(清除CAN1->MCR的SLEEP位)
        报文不锁定,新的覆盖旧的
        优先级由报文标识符决定
    */
    
    CAN1->MCR |= 1<<0;    //请求CAN进入初始化模式
    while ((CAN1->MSR & 1 << 0) == 0)
    {
        if (++cnt > 100)
        {
            return 2;    //进入初始化模式失败----超时监测
        }
    }
    
    CAN1->MCR |= 1<<16;
    CAN1->MCR |= 1<<6;
    CAN1->MCR |= 1<<5;
    CAN1->MCR |= 1<<4;    //禁止报文自动重发
    
    CAN1->BTR = 0;    //清除原来的设置.
    CAN1->BTR |= mode<<30;    //模式设置 0,工作模式;1,回环模式;
    CAN1->BTR |= (tsjw - 1) << 24;     //重新同步跳跃宽度(Tsjw)为tsjw+1个时间单位
    CAN1->BTR |= (tbs2 - 1) << 20;     //Tbs2=tbs2+1个时间单位
    CAN1->BTR |= (tbs1 - 1) << 16;    //Tbs1=tbs1+1个时间单位
    CAN1->BTR |= (brp - 1) ;      //分频系数(Fdiv)为brp+1
                                //波特率:Fpclk1/((Tbs1+Tbs2+1)*Fdiv)
    
    CAN1->MCR &= ~(1<<0);        //请求CAN退出初始化模式
    while ((CAN1->MSR & 1<<0) == 1)
    {
        if (++cnt > 0XFFF0)
        {
            return 3;//退出初始化模式失败
        }
    }
    
    //过滤器初始化
    CAN1->FMR |= 1<<0;        //过滤器组工作在初始化模式
    CAN1->FA1R &= ~(1<<0);    //过滤器0先关闭
    
    CAN1->FS1R |= 1<<0;         //过滤器0位宽为32位.
    CAN1->FM1R &= ~1;            //过滤器0工作在标识符屏蔽位模式
    
    CAN1->FFA1R &= ~1;        //过滤器0关联到FIFO_0
    
    CAN1->sFilterRegister[0].FR1 = 0;//32位ID
    CAN1->sFilterRegister[0].FR2 = 0;//32位MASK
    //任何一个ID都可以进来
    
    CAN1->FA1R |= 1<<0;        //激活过滤器0
    CAN1->FMR &= ~1;            //过滤器组进入正常模式

    return 0;
}   
函数形参:brp:分频器;tbs1:时间段1;tbs2:时间段2;tsjw:同步跳转;

 

推荐阅读