前言

        CAN总线(Controller Area Network Bus)控制器局域网总线

        CAN总线是由BOSCH公司开发的一种简洁易用、传输速度快、易扩展、可靠性高的串行通信总线,广泛应用于汽车、嵌入式、工业控制等领域

CAN总线特征:

        两根通信线(CAN_H、CAN_L),线路少

        差分信号通信,抗干扰能力强

        高速CAN(ISO11898):125k~1Mbps, <40m

        低速CAN(ISO11519):10k~125kbps, <1km

        异步,无需时钟线,通信速率由设备各自约定

        半双工,可挂载多设备,多设备同时发送数据时通过仲裁判断先后顺序

        11位/29位报文ID,用于区分消息功能,同时决定优先级

        可配置1~8字节的有效载荷 可实现广播式和请求式两种传输方式

        应答、CRC校验、位填充、位同步、错误处理等特性

CAN硬件电路

每个设备通过CAN收发器挂载在CAN总线网络上

CAN控制器引出的TX和RX与CAN收发器相连,

CAN收发器引出的CAN_H和CAN_L分别与总线的CAN_H和CAN_L相连

高速CAN使用闭环网络,CAN_H和CAN_L两端添加120Ω的终端电阻

低速CAN使用开环网络,CAN_H和CAN_L其中一端添加2.2kΩ的终端电阻

CAN电平标准

CAN总线采用差分信号,即两线电压差(VCAN_H-VCAN_L)传输数据位

  • 显性位(Dominant):差分电压 Vdiff=VCAN_H−VCAN_L≈2V,典型值为 CAN_H ≈ 3.5V,CAN_L ≈ 1.5V。
  • 隐性位(Recessive):差分电压接近0V,此时两线对地电压趋于相等,通常由终端电阻上拉/下拉维持偏置

高速CAN规定:     

        电压差为0V时表示逻辑1(隐性电平)   

         电压差为2V时表示逻辑0(显性电平)

低速CAN规定:     

        电压差为-1.5V时表示逻辑1(隐性电平)   

         电压差为3V时表示逻辑0(显性电平)

一:帧格式

1:CAN协议5种类型的帧

帧用途
数据帧 用于发送单元向接收单元传送数据的帧。
遥控帧 用于接收单元向具有相同 ID 的发送单元请求数据的帧。
错误帧 用于当检测出错误时向其它单元通知错误的帧。
过载帧 用于接收单元通知其尚未做好接收准备的帧。
帧间隔 用于将数据帧及遥控帧与前面的帧分离开来的帧。

数据帧各部分用途简介
SOF(Start of Frame):帧起始,表示后面一段波形为传输的数据位

ID(ldentify):标识符,区分功能,同时决定优先级  

RTR(Remote Transmission Request):远程请求位,区分数据帧和遥控帧。数据帧必须为显性0,遥控帧必须为隐性1。

IDE(ldentifier Extension):扩展标志位,区分标准格式和扩展格式。标准格式固定为显性0,扩展格式为隐性1。

SRR(Substitute Remote Request):替代RTR,协议升级时留下的无意义位

r0/r1(Reserve):保留位,为后续协议升级留下空间。现在没有使用到,必须为显性0。
DLC(Data Length Code):数据长度,指示数据段有几个字节

Data:数据段的1~8个字节有效数据
CRC(Cyclic RedundancyCheck):循环冗余校验,校验数据是否正确

ACK(Acknowledgement):应答位,判断数据有没有被接收方接收

CRC/ACK界定符:为应答位前后发送方和接收方释放总线留下时间

在CRC界定符发送方必须发隐性1(释放总线),ACK界定符接收方必须及时释放总线,交出控制权(隐性1)。

EOF(End of Frame):帧结束,表示数据位已经传输完毕

CRC校验参考:

14:HAL---CRC校验_hal crc-CSDN博客

B:数据帧

这里波形中间的数字1表示的是这一段波形占1位,并不表示这一位需要发隐性电平1;显性/隐性电平, 是通过颜色表示的(灰色表示必须发显性电平 0 ,蓝色表示发送显性电平或者隐性电平,白色表示必须发送隐性电平1)。

数据帧由7段组成。数据帧又分为标准帧(CAN2.0A)和扩展帧(CAN2.0B),主要体现在仲裁段和控制段

注意事项

        1.ACK槽可以允许多个接收方共同拉开总线(显性0),因为一个报文消息,可以被多个设备同时接受,所以多个设备可以在这里同时拉开,多个设备同时操作总线,输出显性0。

        2:并不是发送方把一段波形完整发出去,然后再接收应答的;而是,发送方和接收方共同完成一整个波形,发送方每发出一位,接收方就立刻收到这一位了,所以在这条时序的最后整个数据帧还没结束,接收方其实已经收完了 ,所以这里短暂交接权力,让接收方操作一下总线,产生应答,应答之后,发送方的整个数据帧才结束,也就是说,应答是实在发送过程之中的。

        3.扩展数据帧中的SRR为1.

说明(标准帧):

帧起始(SOF):因为CAN的电平默认位隐性电平 1,所以帧起始只有一位,显性电平0。

仲裁段:11位的ID+RTR位。多个节点竞争总线发送数据时,根据仲裁段的数据决定哪个节点优先占用总线。那个ID先出现显性电平(0)就优先占用总线。---->ID号小的优先级高。如果ID相同在更加RTR决定 (优先级详情在仲裁说明)

控制段:IDE+RB0+4位的DLC--->共六位

数据段:由DLC决定,范围为0-64位

CRC段:共16位,前15位是CRC校验码,最后一位是隐性电平(1),是CRC的段界定符。

ACK段:ACK位+ACK界定符。在CRC界定符发送方必须发隐性1(释放总线),发送节点ACK位位隐性电平(1),接收节点显性电平(0)。

结束段:帧结束是帧结束段,由7个隐性电平(1)表示。

扩展帧:

仲裁段:11位的ID+SRR+IDE+18位的扩展ID+RTR------>32位。

控制段:RB1+RB0+4位的DLC

ID:11+18 =29位,比标准帧多了18位

数据帧和遥控帧结束后,后面一般是帧空间或过载帧,用于分隔开数据帧或遥控帧

数据帧的发展历史

C:遥控帧

遥控帧无数据段,RTR为隐性电平1,其他部分与数据帧相同。遥控帧最主要的是ID号,表示我要请求找个数据的ID帧。

D:错误帧 

总线上所有设备都会监督总线的数据,一旦发现“位错误"或“填充错误"或“CRC错误”或“格式错误”或“应答错误”,这些设备便会发出错误帧来破坏数据,同时终止当前的发送设备

1:由6位的错误标志和8位的错误界定符组成
2:错误标志分为主动错误标志和被动错误标志两种

3:主动错误标志位6个显性0,被动错误标志为6个隐性1。主动错误标志位会破坏总线的数据,被动不会。

E:过载帧

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

G:帧间隔 

将数据帧和远程帧与前面的帧分离开

2:位填充

        位填充规则:发送方每发送5个相同电平后,自动追加一个相反电平的填充位接收方检测到填充位时,会自动移除填充位,恢复原始数据

位填充作用:

        就是防止数据波形长时间不变化,长时间持续不变的波形,对接收方的准确接收有不利的影响。

        增加波形的定时信息,利于接收方执行“再同步”,防止波形长时间无变化,导致接收方不能精确掌握数据采样时机

        将正常数据流与“错误帧”和“过载帧”区分开,标志“错误帧”和“过载帧”的特异性
        保持CAN总线在发送正常数据流时的活跃状态,防止被误认为总线空闲

位填充作用的区域:

        帧起始、仲裁场、控制场、数据场以及CRC序列

3:测量波形

标准数据帧,报文ID为0x555,数据埃度1字节,数据内容为0xAA

标准数据帧,报文ID为0x666,数据长度2字节,数据内容为0x12,0x34

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

标准遥控帧,报文ID为0x088,数据长度1字节,无数据内容

二:位同步

        挂载在CAN总线上的所有设备,初始都默认为接收方,当某一个设备想要广播自己的数据时,它就会主动出击,变成发送方,拉开或释放总线,使总线产生这样一段波形,波形的编码遵守帧格式的规定。

1.接收方数据采样

        CAN总线没有时钟线,总线上的所有设备通过约定波特率的方式确定每一个数据位的时长(异步)
        发送方以约定的位时长每隔固定时间输出一个数据位
        接收方以约定的位时长每隔固定时间采样总线的电平,输入一个数据位

        理想状态下,接收方能依次采样到发送方发出的每个数据位,且采样点位于数据位中心附近

2.接收方数据采样遇到的问题

接收方以约定的位时长进行采样,但是采样点没有对齐数据位中心附近(使用硬同步解决)

接收方刚开始采样正确,但是时钟有差,随着误差积累,采样点逐渐偏离(再同步解决)

3.位时序

        为了灵活调整每个采样点的位置,使采样点对齐数据位中心附近,CAN总线对每一个数据位的时长进行了更细的划分,分为同步段(SS)、传播时间段(PTS)、相位缓冲段1(PBS1)和相位缓冲段2(PBS2)每个段又由若干个最小时间单位(Tg)

        eg:发送显性电平(0) 被分为了4个段,同步段(SS)占1Tq、传播时间段(PTS)占12q、相位缓冲段1(PBS1)占13 和相位缓冲段2(PBS2)占3Tq

        采样点是指读取总线电平,并将读到的电平作为位值的点。
        根据位时序,就可以计算CAN通信的波特率。

        注意:节点监测到总线上信号的跳变在SS段范围内,表示节点与总线的时序是同步此时采样点的电平即该位的电平。

4.硬同步

        CAN为了实现对总线电平信号的正确采样,数据同步分为硬件同步和再同步

        硬件同步
        节点通过CAN总线发送数据,一开始发送帧起始信号。总线上其他节点会检测帧起始信号在不在位数据的SS段内,判断内部时序与总线是否同步。
        假如不在SS段内,这种情况下,采样点获得的电平状态是不正确的。所以,节点会使用硬件同步方式调整,把自己的SS段平移到检测到边沿的地方,获得同步,同步情况下,采样点获得的电平状态才是正确的。

        硬同步只在帧的第一个下降沿(SOF下降沿)有效

        经过硬同步后,若发送方和接收方的时钟没有误差,则后续所有数据位的采样点必然都会对齐数据位中心附近

图:可以看到节点检测到起始帧数据不在ss段,通过平移到检测到SS段

5.再同步

再同步补偿宽度值的最大限值为SJW=1~4Tq,如果SJW=2Tq,但是误差为1Tq,实际补偿1Tq。如果SJW=2Tq,但是误差为3Tq,实际补偿2Tq。

        若发送方或接收方的时钟有误差,随着误差积累,数据位边沿逐渐偏离SS段则此时接收方根据再同步补偿宽度值(SJW)通过加长PBS1段,或缩短PBS2段,以调整同步

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

再同步
        再同步利用普通数据位的边沿信号(帧起始信号是特殊的边沿信号)进行同步。
        再同步的方式分为两种情况:超前和滞后,即边沿信号与SS段的相对位置。

图:第一个边沿出现在SS段的后面,所以滞后了2个TQ

第二个边沿出现在SS段的前面,所以减少了2个TQ

SJW=1~4Tq

SJW:补偿的最大值,具体补偿多少个Tq,误差大小和SJM共同决定的

误差大小<=SJM       补偿误差大小个Tq

误差大小>SJM         不管误差多大,只会补偿SJM     指定的误差数

6.波特率介绍

        波特率是指单位时间内传输的码元数量,单位为波特(Baud)。

        码元:是数字通信中信号的基本单位,一个码元可以表示一个或多个比特(bit),具体取决于调制方式。例如:

比特率(Bit Rate)

定义:比特率是指单位时间内传输的二进制位数,单位为比特 / 秒(bit/s 或 bps)。
本质:直接衡量数据传输的速度,反映每秒传输的有效信息量

但是在二进制调制下,波特率的值=比特率的值

STM32 的 CAN 外设位时序分为三段:

  • 同步段 SYNC_SEG  (SS段)
  • 时间段 1 BS1(标注:PTS + PBS1)
  • 时间段 2 BS2  

波特率 = 1 / 一个数据位的时长 = 1 / (T*SS + T*PTS + T*PBS1 + T*PBS2)

例如:  SS = 1Tq,PTS = 3Tq,PBS1 = 3Tq,PBS2 = 3Tq     Tq = 0.5us   

                         波特率 = 1 / (0.5us + 1.5us + 1.5us + 1.5us) = 200kbps(千比特每秒)

1s=1000 000us           

具体的计算下下面的  8:位时间特性(波特率)

三:仲裁

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

CAN总线只有一对差分信号线,同一时间只能有一个设备操作总线发送数据,若多个设备同时有发送需求,该如何分配总线资源?

解决问题的思路:制定资源分配规则,依次满足多个设备的发送需求,确保同一时间只有一个设备操作总线

1.先占先得

        若当前已经有设备正在操作总线发送数据帧/遥控帧,则其他任何设备不能再同时发送数据帧/遥控帧(可以发送错误帧/过载帧破坏当前数据)----没有抢占式优先级

        任何设备检测到连续11个隐性电平,即认为总线空闲,只有在总线空闲时,设备才能发送数据帧/遥控帧

        一旦有设备正在发送数据帧/遥控帧,总线就会变为活跃状态,必然不会出现连续11个隐性电平,其他设备自然也不会破坏当前发送

        若总线活跃状态其他设备有发送需求,则需要等待总线变为空闲,才能执行发送需求

2.非破坏性仲裁

        若多个设备的发送需求同时到来或因等待而同时到来,则CAN总线协议会根据ID号(仲裁段)进行非破坏性仲裁,ID号小的(优先级高)取到总线控制权,ID号大的(优先级低)仲裁失利后将转入接收状态,等待下一次总线空闲时再尝试发送

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

         线与特性:总线上任何一个设备发送显性电平0时,总线就会呈现显性电平0状态,只有当所有设备都发送隐性电平1时,总线才呈现隐性电平1状态,即:0 & X & X = 0,1 & 1 & 1 = 1

        回读机制:每个设备发出一个数据位后,都会读回总线当前的电平状态,以确认自己发出的电平是否被真实的发送出去了,根据线与特性,发出0读回必然是0,发出1读回不一定是1

3.非破坏性仲裁过程

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

4.数据帧和遥控帧的优先级

ID号相同的情况下,数据帧的优先级高于遥控帧

RTR(Remote Transmission Request):远程请求位,区分数据帧和遥控帧。数据帧必须为显性0,遥控帧必须为隐性1

5.标准格式和扩展格式的优先级

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

SRR(Substitute Remote Request):替代RTR,协议升级时留下的无意义位

RTR(Remote Transmission Request):远程请求位,区分数据帧和遥控帧。数据帧必须为显性0,遥控帧必须为隐性1。

四:错误处理

1.错误类型

错误共有5种: 位错误、填充错误、CRC错误、格式错误、应答错误

2.错误状态

主动错误状态的设备正常参与通信并在检测到错误时发出主动错误帧

被动错误状态的设备正常参与通信但检测到错误时只能发出被动错误帧

总线关闭状态的设备不能参与通信

每个设备内部管理一个TEC和REC,根据TEC和REC的值确定自己的状态

TEC:发送错误计数器--->每当设备的发送数据时,发送错误一次TEC+1;发送成功一次TEC-1。REC:接受错误计数器--->每当设备的接收数据时,接收错误一次REC+1;接收错误一次REC-1。

3.错误计数器

五:STM32 CAN外设简介

STM32内置bxCAN外设(CAN控制器),支持CAN2.0A和2.0B,可以自动发送CAN报文和按照过滤器自动接收指定CAN报文,程序只需处理报文数据而无需关注总线的电平细节

波特率最高可达1兆位/秒

3个可配置优先级的发送邮箱 2

个3级深度的接收FIFO

14个过滤器组(互联型28个)

时间触发通信、自动离线恢复、    

自动唤醒、禁止自动重传、    

接收FIFO溢出处理方式可配置、    

发送优先级可配置、双CAN模式

STM32F103C8T6 CAN资源:CAN1 

上面为STM32F103C8T6的 (64K Flash(闪存), 20KRAM(随机存取存储器))-->中容量产品

1.CAN网拓扑结构

stm32内部有can控制器和外部的can收发器连接即可

2.CAN框图

简化

具有16位自由运行的定时器,可以定时触发通信,可以在最后两个数据字节发送时间戳。

每个CAN模块有两个FIFO单元,每个FIFO有3个接收邮箱,每个FIFO有独立的中断地址。

两个CAN模块共用28个筛选器组,筛选器用于配置可接收D 列表或掩码。数据帧和遥控帧根据 Ⅲ被筛选,只有通过筛选的帧才进入接收邮箱。帧的筛选完全由硬件完成减少处理器的负担。

3.发送过程

基本流程:选择一个空置邮箱→写入报文 →请求发送

x------------>表示任意值
RQCP:(Request completed)请求完成
TXRQ: 发送数据请求 (Transmit mailbox request)
TME:(Transmit mailbox empty)是发送邮箱空
ABRQ:发送中止位

4.接受过程

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

FMP:反映了当前接收 FIFO 中存放的报文数目。
FOVR:FIFO溢出标志位
RFOM1: 释放接收 FIFO 输出邮箱 (Release FIFO 1 output mailbox)
  发送和接收配置位
        NART:置1,关闭自动重传,CAN报文只被发送1次,不管发送的结果如何(成功、出错或仲裁丢失);置0,自动重传,CAN硬件在发送报文失败时会一直自动重传直到发送成功
        TXFP:置1,优先级由发送请求的顺序来决定,先请求的先发送;置0,优先级由报文标识符来决定,标识符值小的先发送(标识符值相等时,邮箱号小的报文先发送)
        RFLM:置1,接收FIFO锁定,FIFO溢出时,新收到的报文会被丢弃;置0,禁用FIFO锁定,FIFO溢出时,FIFO中最后收到的报文被新报文覆盖

5.标识符过滤器

        每个筛选器组包含两个32位寄存器,分别是CAN_FxR1和CAN_FxR。这两个寄存器可以被配置为两个32位长度筛选器或4个16位长度筛选器,筛选器可以是掩码模式或列表模式所以一个筛选器组有4种配置模式,如图18-8所示。

每个过滤器的核心由两个32位寄存器组成:R1[31:0]和R2[31:0]

FSCx:位宽设置     置0,16位;置1,32位

FBMx:模式设置     置0,屏蔽模式;置1,列表模式

FFAx:关联设置     置0,FIFO 0;置1,FIFO 1

FACTx:激活设置     置0,禁用;置1,启用

每个过滤器组 x 2 32 位寄存器, CAN_FxR0 和 CAN_FxR1组成。
1 32 位过滤器,包括: STDID[10:0](高11位的ID--》标准帧ID) EXTID[17:0](扩展ID18位) IDE RTR 位,剩余一位没有使用保持位0即可。扩展ID总共是29位,存入一个扩展ID,则需要占用前面11位标准ID的空间
2 16 位过滤器,包括: STDID[10:0](11位) IDE RTR EXTID[17:15](3位)
16位/列表: IDE RTR 和EXTID[17:15](3位)为5位。ID写入STDID[10:0](11位)所以需要<<5
16位/屏蔽: 和16位/列表一样
32位/列表: STDID[10:0](高11位的ID) EXTID[17:0](扩展ID18位) IDE和RTR位,剩余一位没有使用。ID写STDID,所以<<21                   写扩展ID写EXTID[17:0 所以<<3
(1)1个32位筛选器--标识符掩码模式。在这种模式下,寄存器CAN_FxRI存储一个32位ID,这个ID与11位标准ID(STID[10:0])、18 位扩展ID(EXID[17:0])、IDE 位、RTR位的位置对应关系如图18-8中的模式(1)所示。IDE为0时表示标准格式,否则表示扩展格式帧。
        CAN FxR2 存储一个 32位掩码,如果掩码为1,则表示该位必须与ID中的位一致,如果
为0,则表示不用一致。
        例如,如果让一个CAN节点只接收标准ID为奇数的标准格式数据,则设置寄存器CAN_FxR1表示的ID时,STID[0]位必须设置为1,IDE位必须设置为0(表示标准格式),RTR 位必须设置为0(表示数据)。设置寄存器CANFxR2表示的掩码时,对应的这些位必须设置为1,其他位设置为0。I和掩码的设置结果如表18-6所示,表中位的数据为“X”表示这个位可以是0,也可以是1。
        
2. 2个32位筛选器--标识符列表模式。在这种模式下,寄存器CAN_FxRI和CAN FR2各存储一个 32位ID,ID的组成与模式(1)相同。只有匹配这两个D的帧才能通过筛选.
(3)2个16位鍗选器--标识符掩码模式。在这种模式下,寄存器CAN_FxRI的低 16位组成一个ID,高16位组成一个掩码      寄存器CANFxR2的低16位组成一个ID,高16位组成一个掩码。16位D的组成如图18-8中的模式(3)所示。
(4)4个16位筛选器--标识符列表模式。在这种模式下,寄存器CANFxR1表示2个16位ID,寄存器CAN_FxR2表示2个16位D。16位ID的组成如图18-8中的模式(4)所示用户可以为一个FIFO设置多个筛选器组,但是一个选器组只能配置给一个FIFO,如果为FIFO设置了筛选器,并且接收的帧与所有鍗选器都不匹配,那么该会被丢弃。只要通过了一个筛选器,帧就会被存入接收邮箱。
EG:

“列表模式” 和 “屏蔽模式” 是总线过滤器(比如 CAN 总线过滤器)的两种核心 ID 匹配方式,核心区别是处理 “离散 ID” 还是 “连续 ID 区间”,具体解释如下:

一、列表 ID 模式:“枚举名单,精确匹配”

意思

要接收的离散、不连续的 ID,一个个 “列” 到寄存器里,硬件会检查总线 ID 是否 “命中列表中的任意一个 ID”,命中则接收,未命中则过滤。

特点

  • 适用场景:目标 ID 是分散的、无规律的(比如 0x123、0x234、0x567);
  • 配置方式:将每个目标 ID 存到寄存器的 “ID 槽” 中(比如 32 位寄存器拆成 2 个 16 位槽,每个槽存 1 个 ID);
  • 匹配逻辑:“精确匹配”—— 只有总线 ID 和列表中的某个 ID 完全一致,才会被接收。

二、屏蔽 ID 模式:“规则过滤,范围匹配”

意思

不用列具体 ID,而是通过 **“基地址 ID + 屏蔽码(Mask)” 定义一个 ID 区间 **,硬件会检查总线 ID 是否 “符合基地址 + 屏蔽码的规则”,符合则接收。

核心逻辑(基地址 + 屏蔽码)

  • 基地址 ID:是区间的 “基准值”(比如要匹配 0x200~0x2FF,基地址是 0x200);
  • 屏蔽码(Mask):标记 “哪些位是固定的、哪些位是可变的”——
    • Mask 中 “位为 0”:总线 ID 的对应位可以任意(即该位不限制)。
    • Mask 中 “位为 1”:总线 ID 的对应位必须和基地址 ID 的对应位完全一致

特点

  • 适用场景:目标 ID 是连续的、有规律的区间(比如 0x200~0x2FF、0x320~0x32F);
  • 配置方式:只需存 “基地址 ID” 和 “屏蔽码”,不用列所有 ID;
  • 匹配逻辑:“范围匹配”—— 覆盖一个连续的 ID 区间,不用逐个枚举,更节省寄存器资源。

三、列表模式 vs 屏蔽模式:核心区分

维度 列表模式 屏蔽模式
适用 ID 类型 离散、不连续的 ID 连续、有区间规律的 ID
配置内容 枚举具体 ID 基地址 ID + 屏蔽码
匹配方式 精确匹配列表中的 ID 按规则匹配 ID 区间
资源占用 每个 ID 占一个寄存器槽 1 组基地址 + 屏蔽码覆盖区间
灵活性 适合少量离散 ID 适合大量连续 ID

简单说:列表模式是 “名单制”(只放名单上的人),屏蔽模式是 “规则制”(符合规则的人都能进)

要不要我帮你整理一份两种模式的配置示例对比表

其实不是绝对不能把 0x234 放 R1 高位、0x345 放 R1 低位,而是从ID 管理逻辑、硬件匹配规则、实际使用习惯出发的常规分配方式,具体原因如下:

1. ID 的优先级 / 管理习惯

通常会按ID 的大小顺序、业务优先级分配高低位:

  • 比如 0x234(数值更小)、0x345(数值更大),习惯把 “优先级更高 / 数值更小” 的 ID 放在低位区域([15:0]),“次优先级 / 数值更大” 的放在高位区域([31:16]);
  • 这种顺序和我们日常 “先低后高” 的数值存储习惯一致(比如多字节数据的小端 / 大端排序逻辑),后续调试、维护时更容易核对 ID 和寄存器的对应关系。

2. 硬件匹配无差异,但需保持 “一致性”

从硬件过滤器的逻辑来看:只要 ID 被正确存到高低位区域(并按要求移位),不管谁放高、谁放低,匹配效果完全一样—— 因为 R1 的高低位是两个独立的 “ID 匹配槽”,硬件会同时检查这两个槽,只要总线 ID 命中其中一个,就会被接收。

但如果随意调换(比如把 0x234 放高位、0x345 放低位),虽然功能没问题,但会打破 “固定的分配规则”,后续如果扩展更多 ID(比如再加 0x456),容易搞混哪个 ID 对应哪个寄存器区域,增加出错概率。

3. 多 ID 扩展的规划

如果后续需要接收更多 ID(比如除了 0x234、0x345,还要加 0x567),R1 的高低位已经占满,就需要用 R2 的低位 —— 按 “先 R1 低位→R1 高位→R2 低位→R2 高位” 的顺序分配,能形成统一的扩展规则,避免混乱。

简单说:调换位置不影响功能,但按 “低位存先 ID、高位存后 ID” 的习惯分配,是为了规范管理、方便后续维护。如果项目里有明确的 ID 分配规则,也可以按规则来放,核心是保持一致性~

如何确认掩码的:

明确需要匹配的 ID 特征

首先确定你希望接收的消息 ID 有哪些共同特征。例如:

 
  • 接收所有 ID 为 0x200-0x2FF 的消息(高 3 位固定为 0x2)
  • 接收所有 ID 以 0x1234 开头的扩展帧
  • 接收所有遥控帧(RTR 位为 1)

2. 分析 ID 的位模式

将需要匹配的 ID 转换为二进制形式,找出它们的共同位。例如:

 

基础ID= 0x200;

0x200 = 0010 0000 0000
0x2FF = 0010 1111 1111
共同位: 10 XXXX XXXX (高4位固定,低8位可变)

3. 构建掩码值(屏蔽位为0-->表示无所谓)

掩码中对应共同位的位置设为 1,可变位设为 0。例如:

 Mask=0x700 (我们匹配的是标准ID,CAN的标准ID为11位)

共同位: 0010 XXXX XXXX
掩码:   X111 0000 0000 = 0x700

左移操作的差异

16 位模式下的左移

在 16 位模式中,标准帧 ID 通常左移 5 位,原因是:

 
  • 16 位寄存器中,高 11 位用于存储标准帧 ID
  • 低 5 位用于存储标志位或保留位
  

32 位模式下的左移

在 32 位模式中,左移操作根据处理的是标准帧还是扩展帧而不同:

 
  1. 标准帧 (11 位 ID)

    • 通常左移 21 位
    • 高 11 位用于存储标准帧 ID
    • 其余位用于标志位或保留位
  2. 扩展帧 (29 位 ID)

    • 通常左移 3 位
    • 高 29 位用于存储扩展帧 ID
    • 低 3 位用于存储标志位
模式分类 位宽模式 主要特点 配置方法 适用场景
屏蔽位模式 32位 1个ID+1个屏蔽码,屏蔽码决定ID中哪些位必须匹配,哪些位不关心 CAN_FxR1(FilterIdHigh +FilterIdLow)存ID,CAN_FxR2(FilterMaskIdLow+FilterMaskIdHigh)存屏蔽码 过滤一组标识符
16位 2个ID+2个屏蔽码,可独立设置两组过滤条件 FR1低16位存FilterIdLow(ID),高16位存FilterMaskIdLow(掩码)FR2低16位存FilterIdHigh(ID),高16位存FilterMaskIdHigh(掩码) 同时过滤两组不同规则的标识符
标识符列表模式 32位 2个完整ID,报文ID必须与其中一个完全匹配 CAN_FxR1CAN_FxR2各存一个完整的32位ID 精确过滤一个特定标识符
16位 4个独立ID,提供四个精确匹配项 FR1FR2寄存器各存放两个16位ID 精确过滤多个特定标识符

屏蔽为的RTR或者IDE为1表示对应的ID必须匹配。

为0 表示都可以

hal里面的代码

    /* Filter Scale */
    if (sFilterConfig->FilterScale == CAN_FILTERSCALE_16BIT)
    {
      /* 16-bit scale for the filter */
      CLEAR_BIT(can_ip->FS1R, filternbrbitpos);

      /* First 16-bit identifier and First 16-bit mask */
      /* Or First 16-bit identifier and Second 16-bit identifier */
      can_ip->sFilterRegister[sFilterConfig->FilterBank].FR1 =
        ((0x0000FFFFU & (uint32_t)sFilterConfig->FilterMaskIdLow) << 16U) |
        (0x0000FFFFU & (uint32_t)sFilterConfig->FilterIdLow);

      /* Second 16-bit identifier and Second 16-bit mask */
      /* Or Third 16-bit identifier and Fourth 16-bit identifier */
      can_ip->sFilterRegister[sFilterConfig->FilterBank].FR2 =
        ((0x0000FFFFU & (uint32_t)sFilterConfig->FilterMaskIdHigh) << 16U) |
        (0x0000FFFFU & (uint32_t)sFilterConfig->FilterIdHigh);
    }
		if(sFilterConfig->FilterScale)
    if (sFilterConfig->FilterScale == CAN_FILTERSCALE_32BIT)
    {
      /* 32-bit scale for the filter */
      SET_BIT(can_ip->FS1R, filternbrbitpos);

      /* 32-bit identifier or First 32-bit identifier */
      can_ip->sFilterRegister[sFilterConfig->FilterBank].FR1 =
        ((0x0000FFFFU & (uint32_t)sFilterConfig->FilterIdHigh) << 16U) |
        (0x0000FFFFU & (uint32_t)sFilterConfig->FilterIdLow);

      /* 32-bit mask or Second 32-bit identifier */
      can_ip->sFilterRegister[sFilterConfig->FilterBank].FR2 =
        ((0x0000FFFFU & (uint32_t)sFilterConfig->FilterMaskIdHigh) << 16U) |
        (0x0000FFFFU & (uint32_t)sFilterConfig->FilterMaskIdLow);
    }

    /* Filter Mode */
    if (sFilterConfig->FilterMode == CAN_FILTERMODE_IDMASK)
    {
      /* Id/Mask mode for the filter*/
      CLEAR_BIT(can_ip->FM1R, filternbrbitpos);
    }
    else /* CAN_FilterInitStruct->CAN_FilterMode == CAN_FilterMode_IdList */
    {
      /* Identifier list mode for the filter*/
      SET_BIT(can_ip->FM1R, filternbrbitpos);
    }

6:测试模式 

静默模式:用于分析CAN总线的活动,不会对总线造成影响

环回模式:用于自测试,同时发送的报文可以在CAN_TX引脚上检测到

环回静默模式:用于热自测试,自测的同时不会影响CAN总线

                        静默模式                                                         环回模式

                       环回静默模式

7:工作模式

初始化模式:用于配置CAN外设,禁止报文的接收和发送

正常模式:配置CAN外设后进入正常模式,以便正常接收和发送报文

睡眠模式:低功耗,CAN外设时钟停止,可使用软件唤醒或者硬件自动唤醒

AWUM:置1,自动唤醒,一旦检测到CAN总线活动,硬件就自动清零SLEEP,唤醒CAN外设;置0,手动唤醒,软件清零SLEEP,唤醒CAN外设

8:位时间特性(波特率)

下图为标称位时间指的是一个位传输的时间。

SS = 1Tq ;BS1 = 1~16Tq; BS2 = 1~8Tq; SJW=1~4Tq 

  波特率 = APB1时钟 (CAN挂载的总线)/ (Prescaler(分频系数) * (TimeSeg1(TBS1) + TimeSeg2(TBS2) + 1))

波特率 = APB1时钟频率 / 分频系数 / 一位的Tq数量 = 36MHz / (BRP[9:0]+1) / (TS1[3:0]+1) + (TS2[2:0]+1)+1)

  WRITE_REG(hcan->Instance->BTR, (uint32_t)(hcan->Init.Mode           |
                                            hcan->Init.SyncJumpWidth  |
                                            hcan->Init.TimeSeg1       |
                                            hcan->Init.TimeSeg2       |
                                            (hcan->Init.Prescaler - 1U)));

Prescaler 里面做了-1  和公式中的+1 相互抵消了

stm32F103can挂载在APB1 上 主频位 36MHZ

stm32F103can挂载在APB1 上 主频位 42MHZ

42 000 000 /3/ (10+3+1)=1000 000HZ

9:中断

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

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

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

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

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

10:时间触发通信

TTCM:置1,开启时间触发通信功能;置0,关闭时间触发通信功能

CAN外设内置一个16位的计数器,用于记录时间戳

TTCM置1后,该计数器在每个CAN位的时间自增一次,溢出后归零

每个发送邮箱和接收FIFO都有一个TIME[15:0]寄存器,发送帧SOF时,硬件捕获计数器值到

发送邮箱的TIME寄存器,接收帧SOF时,硬件捕获计数器值到接收FIFO的TIME寄存器

发送邮箱可配置TGT位,捕获计数器值的同时,也把此值写入到数据帧数据段的最后两个字节,为了使用此功能,DLC必须设置为8

11:错误处理和离线恢复

TEC和REC根据错误的情况增加或减少

ABOM:置1,开启离线自动恢复,进入离线状态后,就自动开启恢复过程;置0,关闭离线自动恢复,软件必须先请求进入然后再退出初始化模式,随后恢复过程才被开启

六:HAL

基本函数

消息发送

消息接收

 

标识符筛选器

 

 中断

7:代码

CAN:代码篇-CSDN博客

面试

https://blog.csdn.net/fish_study_csdn/article/details/131113850

https://www.nowcoder.com/discuss/735064325039144960

https://blog.csdn.net/m0_38106923/article/details/148596660

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐