中科芯CKS32F107XX系列MCU的bxCAN介绍
MCU微课堂CKS32F107XX系列bxCAN介绍第70期2026.01.19
bxCAN简介
CKS32F107xx系列产品的bxCAN支持CAN协议2.0A和2.0B标准。 CAN控制器支持最高1Mb/s的通信速率;自动接收和发送CAN报文,支持标准ID和扩展ID报文;外设具有3个发送邮箱,可通过软件控制发送消息的优先级,并可记录发送时间;具有2个3级深度接收FIFO,可利用过滤功能只接收或不接收特定ID号的报文;可配置自动重传;它不支持使用DMA进行数据传输和接收。
图1是CKS32F107系列芯片的CAN外围架构图。图中有两组CAN控制器,其中CAN1为主设备。框图中的“存储访问控制器”由CAN1控制。 CAN2不能直接访问存储区域,因此使用CAN2时,必须使能CAN1外设的时钟。框图主要包括CAN控制核心、发送邮箱、接收FIFO和验收滤波器。
图1 CKS32F107系列CAN外设架构图
CAN控制内核CAN控制核心包含各种控制寄存器和状态寄存器。我们主要讲解主控寄存器CAN_MCR和位时序寄存器CAN_BTR。
主控寄存器CAN_MCR负责管理CAN的工作模式,主要包括以下几种工作模式:
DBF调试冻结功能DBF(Debug freeze):调试冻结,用它来设置CAN处于工作状态或禁止发送和接收。当发送和接收被禁用时,接收FIFO 中的数据仍然可以访问。这两种状态仅在芯片处于程序调试模式时使用,不会影响正常使用。
TTCM 时间触发通信模式TTCM(时间触发通信模式):时间触发模式,用于配置CAN 的时间触发通信模式。该模式下,CAN利用其内部定时器生成时间戳,可用于实现ISO 11898-4CAN标准的分时同步通信功能。 ABOM自动离线管理ABOM(Automatic Bus-off management):自动离线管理,用于设置是否使用自动离线管理功能。当节点检测到自己的发送错误或接收错误超过一定值时,会自动进入离线状态。在离线状态下,CAN无法接收或发送报文。离线时,您可以通过软件控制恢复或直接使用此自动离线管理功能,它会在适当的时间自动恢复。
AWUM 自动唤醒AWUM(自动总线关闭管理):自动唤醒功能,CAN 外设可以使用软件进入低功耗睡眠模式。如果启用此自动唤醒功能,CAN 将在检测到总线活动时自动唤醒。
NART 自动重传NART(无自动重传):报文的自动重传功能。设置该功能后,当消息发送失败时,会自动重发,直至成功。如果不使用该功能,则无论发送结果如何,消息都只会发送一次。
RFLM 锁定模式RFLM(接收FIFO 锁定模式):FIFO 锁定模式,该功能用于锁定接收FIFO。锁定后,当接收FIFO溢出时,下一条接收到的报文将被丢弃。如果没有锁定,下一条收到的消息将覆盖原来的消息。
TXFP消息发送优先级确定方法TXFP(Transmit FIFOpriority):消息发送优先级确定方法。当CAN外设的发送邮箱中有多个报文需要发送时,该函数可以控制是按照报文的ID优先级还是按照报文在邮箱中存储的顺序发送。
位定时寄存器(CAN_BTR)和波特率:CAN外设中的位定时寄存器CAN_BTR用于配置测试模式、波特率以及各个位内的段参数。
正常模式:正常模式是正常的CAN节点可以向总线发送和接收数据。
静默模式:在静默模式下,自身输出端的逻辑0数据会直接传送到自己的输入端,而逻辑1可以发送到总线,因此不能发送显性位(逻辑0)到总线,而只能发送隐性位(逻辑1)。输入可以从总线接收内容。由于它只能发送不强制影响总线状态的隐性位,因此称为静默模式。该模式一般用于监控。它可用于分析总线上的流量,而不会通过发送显性位来影响总线。
环回模式:在环回模式下,自身输出端的所有内容直接传输至自身输入端,同时输出端的内容也传输至总线。即总线还可以用来监听其发送内容。输入端只接收自己发送端的内容,不接收总线的内容。使用环回模式进行自检。
Loopback静默模式:该模式是上述两种模式的组合。其自身输出端的所有内容均直接传输至自身输入端,不会将显性位发送至总线影响总线,且无法通过总线监控其传输内容。输入端只接收自己发送端的内容,不接收总线的内容。这种方法可以在“热自检”时使用,即自检时,不会干扰总线。
位时序和波特率: CKS32F107 中CAN 的位时序如图2 所示。
图2 CAN位时序图
CKS32F107的CAN外设位时序仅包含三段,即同步段SYNC_SEG、位段BS1和位段BS2。采样点位于BS1和BS2段的交界处。 SYNC_SEG段的长度固定为1Tq,而BS1和BS2段可以在位定时寄存器CAN_BTR中设置其时间长度。它们可以在重新同步期间增长或缩短。 SJW 的长度也可以在位定时寄存器中配置。因此,通过配置位时序寄存器CAN_BTR的TS1[3:0]和TS2[2:0]寄存器位设置BS1和BS2段的长度后,我们可以确定每个CAN数据位的时间:
T1位=1Tq+TBS1+TBS2=NTq
单个时间片的长度Tq与CAN外设的时钟总线和分频器配置有关。 CAN1和CAN2外设均挂载在APB1总线上,位时序寄存器CAN_BTR中的BRP[9:0]寄存器位可以设置CAN外设时钟的分频值,因此:
Tq=(BRP[9:0]+1) x TPCLK
PCLK指的是APB1时钟,默认值为36MHz。
最后可以计算出CAN通信的波特率:BaudRate=1/NTq
CAN发送邮箱共有3个发送邮箱,即最多可以缓存3条要发送的邮件。每个发送邮箱包含标识符寄存器CAN_TIxR、数据长度控制寄存器CAN_TDTxR和2个数据寄存器CAN_TDLxR和CAN_TDHxR的功能如下表所示。当我们要使用CAN外设发送报文时,我们将报文的各个段分解并按照位置写入到这些寄存器中,并将标识符寄存器CAN_TIxR中的发送请求寄存器位TMIDxR_TXRQ设置为1来发送数据。
CAN接受FIFOCKS32F107系列共有2个接收FIFO。每个FIFO 有3 个邮箱,这意味着它最多可以缓存6 个接收到的消息。当接收到消息时,FIFO 的消息计数器将增加。 CKS32F107内部读取FIFO数据后,消息计数器会减少。我们可以通过状态寄存器知道消息计数器的值,通过前面主控寄存器的RFLM位可以设置锁定模式。在锁定模式下,当FIFO 溢出时,新消息将被丢弃。在非锁定模式下,当FIFO 溢出时,新消息将覆盖旧消息。与发送邮箱类似,每个接收FIFO 包含一个标识符寄存器CAN_RIxR、一个数据长度控制寄存器CAN_RDTxR 以及两个数据寄存器CAN_RDLxR 和CAN_RDHxR。它们的功能如发送邮箱寄存器表所示。通过中断或者状态寄存器知道接收FIFO有数据后,我们就可以读取这些寄存器的值,将接收到的报文加载到MCU的内存中。
验收筛选器CAN外设接受过滤器,共有28个过滤器组,每个过滤器组有2个寄存器,CAN1和CAN2共享过滤器。在CAN协议中,报文的标识符与节点地址无关,而是与报文内容有关。因此,当发送节点向所有接收者广播消息时,接收节点会根据消息标识符的值来判断软件是否需要该消息。为了简化软件的工作,CAN外设在接收报文之前会使用接受过滤器进行检查,只接收需要的报文放入FIFO中。
初始化结构
从CKS32F107的CAN外设我们知道它的功能非常多,涉及控制的寄存器也非常丰富。利用标准库提供的各种结构体和库函数可以简化这些控制过程。与其他外设一样,标准库提供了CAN初始化结构体和初始化函数来控制CAN的工作模式,提供了用于发送和接收消息的结构体和收发器函数,以及用于配置控制过滤器模式和ID的结构体。
清单1: 代码清单:CAN 初始化结构
类型定义结构{
uint16_tCAN_Prescaler;
uint8_tCAN_Mode;
uint8_tCAN_SJW;
uint8_tCAN_BS1;
uint8_tCAN_BS2;
功能状态CAN_TTCM;
功能状态CAN_ABOM;
功能状态CAN_AWUM;
功能状态CAN_NART;
功能状态CAN_RFLM;
功能状态CAN_TXFP;
CAN_InitTypeDef;
(1) CAN_预分频器
该成员设置CAN外设的时钟分频,可以控制时间片Tq的长度。这里设置的值最终会减1后再写入BRP寄存器位,这就是前面介绍的Tq计算公式:
Tq=(BRP[9:0]+1) x TPCLK
等价于:Tq=CAN_Prescaler x TPCLK
(2) CAN_模式
该成员设置CAN的工作模式,可设置为正常模式(CAN_Mode_Normal)、环回模式(CAN_Mode_LoopBack)、静默模式(CAN_Mode_Silent)和环回静默模式(CAN_Mode_Silent_LoopBack)。
(3)CAN_SJW
该成员可以配置SJW的限制长度,即CAN重新同步过程中一次可以增加或缩短的最大长度。可配置为1-4Tq (CAN_SJW_1/2/3/4tq)。
(4) CAN_BS1
该成员用于设置CAN位时序中BS1段的长度,可配置为1-16个Tq长度(CAN_BS1_1/2/3…16tq)。
(5)CAN_BS2
该成员用于设置CAN位时序中BS2段的长度。可配置为1-8 Tq 长度(CAN_BS2_1/2/3.8tq)。 SYNC_SEG、BS1 段和BS2 段的长度之和就是一个数据位的长度,也就是前面介绍的原始计算公式: T1bit=1Tq+TS1+TS2=1+ (TS1[3:0] +1)+ (TS2[2:0]+1) 等价于:T1bit=1Tq+CAN_BS1+CAN_BS2
(6)CAN_TTCM
该成员用于设置是否使用时间触发功能(ENABLE/DISABLE),该功能在一些CAN标准中使用。
(7) CAN_ABOM
该成员用于设置是否使用自动离线管理(ENABLE/DISABLE)。采用自动离线管理,可以在出现错误、离线后自动及时恢复节点,无需软件干预。
(8) CAN_AWUM
该成员用于设置是否使用自动唤醒功能(ENABLE/DISABLE)。自动唤醒功能使能后,检测到总线活动后会自动唤醒。
(9) CAN_ABOM
该成员用于设置是否使用自动离线管理功能(ENABLE/DISABLE)。采用自动离线管理,可以在发生错误时离线后自动及时恢复,无需软件干预。
(10)CAN_NART
该成员用于设置是否使用自动重传功能(ENABLE/DISABLE)。当使用自动重发功能时,消息会一直发送,直至成功。
(11)CAN_RFLM
该成员用于设置是否使用锁定接收FIFO(ENABLE/DISABLE)。锁定接收FIFO 后,如果FIFO 溢出,新数据将被丢弃。否则,当FIFO 溢出时,旧数据将被新数据覆盖。
(12)CAN_TXFP
该成员用于设置发送消息的优先级确定方法(ENABLE/DISABLE)。启用后,消息将按照发送邮箱中存储的顺序发送。否则,将根据消息ID 的优先级发送它们。配置完这些结构体成员后,我们调用库函数CAN_Init将这些参数写入CAN控制寄存器,实现CAN初始化。
CAN发送和接收结构
清单2: 代码清单:CAN 发送和接收结构
类型定义结构
{
uint32_t 标准ID;
uint32_t ExtId;
uint8_t IDE;
uint8_t RTR;
uint8_t DLC;
uint8_t 数据[8];
CanTxMsg;
类型定义结构
{
uint32_t 标准ID;
uint32_t ExtId;
uint8_t IDE;
uint8_t RTR;
uint8_t DLC;
uint8_t 数据[8];
uint8_t FMI;
CanRxMsg;
(1) 标准ID
该成员存储消息的11位标准标识符,范围从0-0x7FF。
(2)扩展ID
该成员存储消息的29位扩展标识符,范围为0-0x1FFFFFFF。 ExtId和StdId这两个成员是根据下面的IDE位进行配置的,只有一个有效。
(3) 集成开发环境
该成员存储扩展标志IDE位。当其值为宏CAN_ID_STD时,表示该报文是标准帧,StdId成员用于存储报文ID;当其值为宏CAN_ID_EXT时,表示该报文是扩展帧,ExtId成员用于存储报文ID。
(4)RTR
该成员存储消息类型标志RTR位。当其值为宏CAN_RTR_Data时,表示该报文是数据帧;当其值为宏CAN_RTR_Remote时,表示该消息是远程控制帧。由于远程控制帧没有数据段,当报文为远程控制帧时,后面的Data[8]成员的内容无效。
(5) DLC
该成员存储数据帧的数据段的长度。其取值范围为0-8。当消息为远程控制帧时,DLC值为0。
(6) 数据[8]
该成员存储数据帧中数据段的数据。
(7)FMI
该成员仅存在于接收结构中。它存储过滤器编号并指示该消息通过哪个过滤器并存储在接收FIFO 中。它可用于简化软件处理。当需要使用CAN发送报文时,首先定义一个上述发送类型的结构体,然后根据其成员将报文的内容赋给该结构体,最后调用库函数CAN_Transmit将这些内容写入发送邮箱来发送报文。接收报文时,通过检测标志位即可得知接收FIFO的状态。如果接收到报文,可以调用库函数CAN_Receive将接收FIFO的内容读入预定义的接收类型结构体中,然后访问该结构体来利用该报文。
CAN滤波器结构
清单3: 代码清单:CAN 过滤器结构
类型定义结构
{
uint16_t CAN_FilterIdHigh;
uint16_t CAN_FilterIdLow;
uint16_t CAN_FilterMaskIdHigh;
uint16_t CAN_FilterMaskIdLow;
uint16_t CAN_FilterFIFOAssignment;
uint8_t CAN_FilterNumber;
uint8_t CAN_FilterMode;
uint8_t CAN_FilterScale;
功能状态CAN_FilterActivation;
CAN_FilterInitTypeDef;
(1) CAN_FilterIdHigh
CAN_FilterIdHigh成员用于存储要过滤的ID。如果过滤器工作在32位模式,则存储过滤后ID的高16位;如果过滤器工作在16位模式,它会存储要过滤的完整ID。
(2) CAN_FilterIdLow
同样,CAN_FilterIdLow成员也用于存储要过滤的ID。如果过滤器工作在32位模式,则存储过滤后ID的低16位;如果过滤器工作在16位模式,它会存储要过滤的完整ID。
(3) CAN_FilterMaskIdHigh
CAN_FilterMaskIdHigh中存储的内容分为两种情况。当过滤器工作在标识符列表模式时,其功能与CAN_FilterIdHigh相同,存储需要过滤的ID。当过滤器工作在掩码模式时,会存储CAN_FilterIdHigh成员对应的掩码,与CAN_FilterIdLow组成一组过滤器。
(4) CAN_FilterMaskIdLow
同样,CAN_FilterMaskIdLow中存储的内容也分为两种情况。当过滤器工作在标识符列表模式时,其功能与CAN_FilterIdLow相同,存储需要过滤的ID。当过滤器工作在掩码模式时,会存储CAN_FilterIdLow成员对应的掩码,与CAN_FilterIdLow组成一组过滤器。
(5) CAN_FilterFIFO分配
该成员用于设置消息通过过滤器匹配后将存储在哪个接收FIFO中。其可选值为FIFO0 或FIFO1(宏CAN_Filter_FIFO0/1)。
(6) CAN_过滤器编号
该成员用于设置过滤器的数量,即该过滤器结构中配置哪一组过滤器。 CAN共有28个过滤器,因此其输入参数范围为0-27。
(7) CAN_FilterMode
该成员用于设置过滤器的工作模式,可以设置为列表模式(宏CAN_FilterMode_IdList)和掩码模式(宏CAN_FilterMode_IdMask)
(8) CAN_FilterScale
该成员用于设置滤波器比例,可设置为32位长(宏CAN_FilterScale_32bit)和16位长(宏CAN_FilterScale_16bit)
(9) CAN_Filter激活
该成员用于设置是否激活该过滤器(宏ENABLE/DISABLE)。配置完这些结构体成员后,我们调用库函数CAN_FilterInit将这些参数写入过滤器控制寄存器以使用过滤器。