CAN 通信协议学习笔记

CAN 总线从入门到 STM32 bxCAN 外设:硬件电路、电平标准、帧格式、位填充、位时序与同步、仲裁、错误处理。

CAN简介

CAN总线特征:

  • 两根通信线(CAN_H、CAN_L),无需共地
  • 差分信号,抗干扰
  • 高速CAN:125k-1mbps,<40m
  • 低速CAN:10k~125kbps, <1km
  • 异步通信(无时钟线),通信速率由设备各自约定
  • 半双工,可挂载多设备,多设备同时发送数据时通过仲裁判断先后顺序
  • 11位/29位报文ID,用于区分消息功能,同时决定优先级
  • 可配置1~8字节的有效载荷
  • 可实现广播式和请求式两种传输方式
  • 应答、CRC校验、位填充、位同步、错误处理等特性

主流通信协议

名称引脚双工时钟电平设备应用场景
UARTTX、RX全双工异步单端点对点两个设备互相通信
I2CSCL、SDA半双工同步单端多设备一个主控外挂多个模块
SPISCK、MOSI、MISO、SS全双工同步单端多设备一个主控外挂多个模块(高速)
CANCAN_H、CAN_L半双工异步差分多设备多个主控互相通信

CAN类似UART和IIC的结合

第一章

CAN硬件电路

主控会内置CAN控制器,借助CAN收发器挂载在CAN总线网络

高速CAN采用闭环网络,CAN的差分信号默认状态下(1,CANH=CANL),由电阻收紧,而电阻因为阻抗不大,因此电压跃变快,但是功耗高

image-20251023155654683

低速CAN使用开环网络,两端加开路的电阻,降低反射

image-20251023155742503

电平标准

差分信号,即电压差传输数据

高速CAN:

隐性电平是不碰两根线,电阻处为收紧状态(默认状态1,隐性)

显性电平是拉开两根线,电阻处为非收紧状态(显性可以控制总线,0强于1,所以能叫显性)

  • 电压差为0V时表示逻辑1(隐性电平)
  • 电压差为2V时表示逻辑0(显性电平)
image-20251023160648825

CAN收发器-TJA1050(高速CAN)

image-20251023162057153

CANH和CANL有电压差,RECEIVER输出1,下管导通,RXD为0(有电压差,逻辑0,显性)

CANH和CANL无电压差,RECEIVER输出0,上管导通,RXD为1(无电压差,逻辑1,隐性)

image-20251023162504583

TXD为0时,2,3的场效应管导通,CANH和CANL有电压差(逻辑0,显性)

而TXD悬空时,电流源默认让TXD为1

image-20251023163114449

CAN物理层特性

image-20251023163332184

第二章

CAN总线帧格式

主要看数据帧

帧类型用途
数据帧发送设备主动发送数据(广播式)
遥控帧接收设备主动请求数据(请求式)
错误帧某个设备检测出错误时向其他设备通知错误
过载帧接收设备通知其尚未做好接收准备
帧间隔用于将数据帧及遥控帧与前面的帧分离开

数据帧

  • SOF(Start of Frame):帧起始,表示后面一段波形为传输的数据位
  • ID(Identify):标识符,区分功能,同时决定优先级
  • RTR(Remote Transmission Request ):远程请求位,区分数据帧和遥控帧
  • IDE(Identifier Extension):扩展标志位,区分标准格式和扩展格式
  • SRR(Substitute Remote Request):替代RTR,协议升级时留下的无意义位
  • r0/r1(Reserve):保留位,为后续协议升级留下空间
  • DLC(Data Length Code):数据长度,指示数据段有几个字节
  • Data:数据段的1~8个字节有效数据
  • CRC(Cyclic Redundancy Check):循环冗余校验,校验数据是否正确
  • ACK(Acknowledgement):应答位,判断数据有没有被接收方接收
  • CRC/ACK界定符:为应答位前后发送方和接收方释放总线留下时间
  • EOF(End of Frame ):帧结束,表示数据位已经传输完毕

image-20251023163910230

标准格式

  1. 开始为空闲状态为隐性
  2. SOF为帧起始,表明开始一帧数据
  3. 起始帧后发送11位标识符报文,区分功能,同时决定优先级
  4. RTR为0:数据帧。为1:遥控帧
  5. IDE为0:标准格式。为1:扩展格式
  6. r0保留位,暂时无功能
  7. DLC为数据长度,0001发一个字节,1000发8字节
  8. Data根据DLC给几个字节能给范围0-64字节
  9. CRC为校验
  10. ACK应答位,发送方释放总线,如果接收方收到了,就抢占总线,发送方读取总线状态知道被接受
  11. CRC/ACK界定符是留出时间交出控制权
  12. EOF作为结束

遥控帧

适合使用频率低的数据

遥控帧无数据段,RTR为隐性电平1,其他部分与数据帧相同

如果有数据需要,首先接收方发出一个遥控帧,遥控帧包含报文ID,如果发送方有这个报文ID,就将数据发送出来,接收方可以及时获取数据

错误帧

总线所有设备监督总线数据,一旦发现错误,这些设备发出错误帧来破坏数据,同时终止当前的发送设备

image-20251023185816885

过载帧

接收方收到大量数据无法处理,发送过载帧,延缓发送方的数据发送,以平衡总线负载,避免数据丢失

帧间隔

将数据帧和遥控帧与前面的帧分离开

image-20251023190001992

位填充

规则:发送方每发送5个相同电平,自动追加相反电平的填充位,接收方检测到填充位,自动移除填充位。

即将发送: 100000110 10000011110 0111111111110 实际发送: 1000001110 1000001111100 011111011111010 实际接收: 1000001110 1000001111100 011111011111010 移除填充后: 100000110 10000011110 0111111111110

作用:

  • 增加定时信息,有利于接收方同步,防止波形长时间无变化(防止连续很多相同电平,接收方可能数错)
  • 将正常数据流与“错误帧”和“过载帧”区分(防止连续6个相同电平)
  • 保持CAN发送数据的活跃状态,防止认为总线空闲(防止连续11个隐性电平1)

波形实例

标准数据帧

11位报文ID:0x555,

RTR = 0 数据帧,IDE = 0,标准格式

DLC = 0001(注意其中第一个1为位填充) = 1,一个字节数据

Data = 10101010 = 0xAA

image-20251023191033968

扩展数据帧

扩展数据帧,报文ID为0x0789ABCD,数据长度1字节,数据内容为0x56

image-20251023192707532

第三章

接收方数据采样

  • CAN总线无时钟线,总线设备通过一个约定的波特率方式确定每个数据位的时长
  • 发送方以约定的位时长每个固定时间输出一个数据位
  • 接收方以约定的位时长每个固定时间采样总线电平,输入一个数据位
  • 理想采样是数据位中心附近

会遇到的问题

  • 接收方采样点没有对齐数据位中心附近

解决:第一个跳变沿对齐(硬同步)

  • 接收方刚开始采样正确,但是时钟有误差,随着误差积累,采样点逐渐偏离

解决:采样点动态调节,弥补时钟误差(再同步)

位时序

因为要调节采样点,所以会对一个数据位时长进行细分

  • 同步段(SS)
  • 传播时间段(PTS)
  • 相位缓冲段1(PBS1)
  • 相位缓冲段2(PBS2)

每个段又由若干个最小时间单位(Tq)构成

SS = 1Tq、PTS = 18Tq、PBS1 = 18Tq、PBS2 = 2~8Tq

image-20251023193938293

如果跳边沿在SS段,说明当前设备与波形达成同步,否则不同步,则需要调节时序使跳变沿正好在同步段

image-20251023194302175

硬同步

使第一次采样对齐

每个设备有一个位时序计时周期,当某设备发送报文,其他设备接收到SOF下降沿,会将位时序计时周期拨到SS段,与发送方保持同步(实际就是让第一个边沿段调整为SS段,类似于时区,绝对时刻不一样,但都规定为北京时间)

而此时接受段直接确定数据位采样点(PBS1和PBS2段中间)

硬同步解决没有对齐数据位中心附近,只要时钟没误差,就不会有问题

image-20251023200536351

再同步

解决时钟误差,若数据位边沿逐渐偏离SS段,此时接收方根据再同步补偿宽度值(sjw,是最大的补偿,如果误差1tq,sjw2,则补偿1tq;若误差3tq,则补偿2tq)加长PBS1段,或缩短PBS2段

再同步发生在,第一个下降沿之后每个数据位跳变边沿

image-20251023201451502

波特率计算

波特率 = 1/一个数据位的时长 = 1/(Tss+Tpts+Tpbs1+Tpbs2)

SS = 1Tq,PTS = 3Tq,PBS1 = 3Tq,PBS2 = 3Tq,Tq = 0.5us

则波特率 = 1 / (0.5us + 1.5us + 1.5us + 1.5us) = 200kbps

第四章

多设备同时发送遇到的问题

CAN总线只有一差分信号线,同时只能有一个设备操作总线

若多设备同时又发送需求,该如何分配总线资源?

资源分配规则1-先占先得

  • 若当前有设备操作总线发送数据帧/遥控帧,则其他设备不可发(可发错误帧/过载帧)
  • 任何设备检测到11连续隐性电平,认为总线空闲,才能发送
  • 若有设备有发送需求要等待总线空闲

而位填充的适用范围是从帧起始(SOF)到CRC序列结束,不包括CRC界定符、ACK域和EOF段

此时有ACK界定符一个隐性,EOF7个隐性,只需再等三个隐性即可继续发送。

但有可能不止一个信号在等待,多个设备同时到来(总线仲裁)

资源分配规则2-非破坏性仲裁

多设备发送需求同时到来,对仲裁段(ID+RTR)进行非破坏性仲裁,ID号小(优先级高)的取得控制权,ID号大(优先级低)仲裁失利,继续等待空闲

实现非破坏性仲裁两个需要的特性:

  • 线与特性:0 & X & X = 0,1 & 1 & 1 = 1
  • 回读机制:设备发出一个数据位后,读回总线电平状态,确认电平被发送。发送0读回0,发送1读回不一定是1

仲裁:发出数据1,读回(回读机制)数据0(被其他设备线与了)

非破坏性仲裁过程

数据位从前到后依次比较,出现差异且数据位为1的设备仲裁失利

单元1在仲裁段中某一个数据位发送1,回读出0,判断有其他设备在发生,但自己优先级低,放弃发送。但是总线电平依旧是单元2的,并没有被破坏

image-20251023204633782

数据帧和遥控帧优先级

数据帧和遥控帧ID号一样时,数据帧的优先级高于遥控帧(RTR决断,因为RTR = 0 为数据帧)

image-20251023205811312

标准格式和拓展格式的优先级

标准格式11位ID号和扩展格式29位ID号的高11位一样时,标准格式的优先级高于扩展格式(SRR必须始终为1,以保证此要求)

image-20251023205932744

第五章

错误类型

位错误、填充错误、CRC错误、格式错误、应答错误

image-20251023210342121

错误状态

  • 主动错误状态参与通信并检测到错误时发送主动错误帧(6个0),可以破坏别的设备的数据
  • 而频繁发送主动错误,说明这个设备不太可靠,就转到被动错误,收回他破坏其他设备通信的权利
  • 若还是频繁被动错误,则进入总线关闭
  • 如何判断:每个设备内部管理一个TEC和REC,根据TEC和REC确定自己状态(信誉分)
image-20251023212056785

错误计数器

信誉分积分:

image-20251023212321573

STM32 CAN外设

  • STM32内置bxCAN支持CAN2.0A和2.0B,可自动发报文,程序只需处理报文数据
  • 波特率最高1mbps
  • 3个可配置优先级的发送邮箱
  • 2个3级深度接收FIFO
  • 时间触发通信、自动离线恢复、自动唤醒、禁止自动重传、接收FIFO溢出处理方式可配置、发送优先级可配置、双CAN模式
  • STM32F103C8T6 CAN资源:CAN1

第一节

CAN网络拓扑

image-20251024152812279

STM32F103C8T6 CAN引脚默认复用

image-20251024153118991

重定义

image-20251024153129671

CAN收发器电路

注意TX,RX接法与串口区分

image-20251024153323173

image-20251024153328481

第二节

CAN框图

image-20251024154247741

对于STM32F103C8T6,没有CAN2,只有CAN1。

通过读写以下寄存器对CAN电路进行配置:

image-20251024154441586

3个主发送邮箱,每个可以存入一个CAN报文,若想发送一个报文,可以将报文放入空置邮箱,在设置寄存器请求发送

image-20251024154756599

接收部分包括过滤器和2个FIFO,过滤器设置过滤规则,告诉硬件想要的ID的报文,如果硬件收到相应ID的报文,将报文放入FIFO;如果都没用,就抛弃,减轻软件负担。

FIFO:先入先出,类似于队列,等待CPU读取

image-20251024155100846

CAN基本结构

image-20251024155405878

发送过程

选择空置邮箱-写入报文-配置寄存器请求发送

RQCP:请求完成

TXOK:发送成功

TME = 1:发送邮箱空

image-20251024160418572

发送流程:

  • 默认TME=1处于空置状态时,TXRQ(请求发送控制位)=1(产生发送请求)
  • 进入挂号状态TME=0,排队等到该邮箱为最高优先级发送报文
  • 进入预定状态,若优先级被比下去,则退回挂号状态
  • 处于预定的报文,探测到CAN总线=IDLE空闲,管理员将报文发送到CAN总线
  • 发送成功回到空置状态,发送失败时若启用NART=0(禁止自动重发)回到空置,若禁止,NART=1则回到预定等待发送(比如总线仲裁失败)

接收过程

接收到一个报文→匹配过滤器后进入FIFO 0或FIFO 1→CPU读取

FMP:报文数目

FOVR:FIFO溢出

image-20251024163116807
  • 接收到一个报文时,FMP=1,FOVR=0,依次接收后FMP递增
  • 有效报文存满FULL置1,在收到有效报文进入溢出FOVR=1
  • 若读取一个报文,RFOM=1,释放一次邮箱

注意:溢出状态释放一次是挂号2

发送和接收配置位

  • NART:NART=1关闭自动重传,CAN报文只发送一次,不管发送结果如何;置0,自动重传,直到发送成功
  • TXFP:TXFP=1,优先级按发送请求的顺序;置0,优先级按报文ID,标志符小的先发送(标志符相等,邮箱号小的先发送)
  • RFLM:置1,接收FIFO锁定,FIFO溢出,新报文丢弃;置0,FOFO溢出后最后收到报文被覆盖

标识符过滤器

x可以表示0-13,每个过滤器都有一套电路

  • 每个过滤器由2个32位寄存器组成,R1[31:0] R2[31:0]

  • 位宽设置,FSCx=0,16位,FSCx=1,32位

    • 若只有标准ID,则16位足矣,若有标准,有拓展需要用到32位
    • 16位的话两个32位寄存器能写4个ID号,32位写两个
  • 模式设置,

    • FBMx=0,屏蔽模式

      允许一类,使用了类似掩码功能,屏蔽的是不需要的ID号的位,如只需要用前三位,可以ID段前三位写001xxxxxxxx,屏蔽写11100000000,过滤ID前三位为001

    • FBMx=1,列表模式(允许个别)

  • 关联到队列,FFAx=0,关联FIFO0,否则关联FIFO1

  • 激活FACTx:FACTx=0,禁用,否则启用

image-20251024170732729

  • 列表模式

    • 想要的ID号写入R1或R2寄存器中

    • 位宽32位

      • STID高11位为标准ID
      • 前29位是拓展ID
      • 过滤拓展ID,IDE=1,过滤标准ID,IDE=0
      • RTR=1,过滤遥控帧,RTR=0,过滤数据帧
    • 位宽16位

      • 只使用标准ID,4个16位
  • 屏蔽模式

    • ID号过多时使用
    • 采用位与屏蔽,类似掩码功能
    • ID段有效位写实际,对应屏蔽位写1

过滤器配置示例

image-20251024190102576

第三节

测试模式

  • 静默模式:用于分析CAN总线的活动,不会对总线造成影响
  • 环回模式:用于自测试,同时发送的报文可以在CAN_TX引脚上检测到
  • 环回静默模式:用于热自测试,自测的同时不会影响CAN总线

image-20251024192633712

工作模式

  • 初始化模式:用于配置CAN时禁止收发
  • 正常模式
  • 睡眠模式:低功耗,CAN外设时钟停止,可以软件唤醒或硬件自动唤醒
  • AWUM:置1,自动唤醒,一旦检测到CAN总线活动,硬件就自动清零SLEEP,唤醒CAN外设;置0,手动唤醒,软件清零SLEEP,唤醒CAN外设
image-20251024193220836

位时间特性

STM32中,PDS和PBS1合在一起

  • SS = 1Tq BS1 = 116Tq BS2 = 18Tq
  • SJW=1~4Tq

image-20251024194312171

  • 波特率=APB1时钟频率/分频系数/1位Tq数

    =36Mhz/(BRP[9:0]+1)/(1+(TS1[3:0]+1)+(TS2[2:0]+1))

中断

CAN外设占用4个专用中断向量

  • 发送中断:发送邮箱空时产生

  • FIFO 0中断:收到一个报文/FIFO 0满/FIFO 0溢出时产生

  • FIFO 1中断:收到一个报文/FIFO 1满/FIFO 1溢出时产生

  • 状态改变错误中断:出错/唤醒/进入睡眠时产生

中断发生条件:

image-20251024195020980
使用 Hugo 构建
主题 Stack 由 Jimmy 设计