bxCAN简介
CKS32F107xx系列产品的bxCAN支持CAN协议2.0A和2.0B标准。 该CAN 控制器支持最高的通讯速率为1Mb/s;可以自动地接收和发送CAN报文,支持使用标准ID和扩展ID的报文;外设中具有3个发送邮箱,发送报文的优先级可以使用软件控制,还可以记录发送的时间;具有2个3级深度的接收FIFO,可使用过滤功能只接收或不接收某些ID号的报文;可配置成自动重发;不支持使用 DMA进行数据收发。
图1是CKS32F107系列芯片的CAN外设架构图,图里具有2组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(Time triggered communication mode):时间触发模式,它用于配置CAN的时间触发通信模式,在此模式下,CAN使用它内部定时器产生时间戳,利用它可以实现ISO 11898-4CAN标准的分时同步通信功能。 ABOM自动离线管理 ABOM(Automatic bus-off management): 自动离线管理,它用于设置是否使用自动离线管理功能。当节点检测到它发送错误或接收错误超过一定值时,会自动进入离线状态,在离线状态中,CAN不能接收或发送报文。处于离线状态的时候,可以软件控制恢复或者直接使用这个自动离线管理功能,它会在适当的时候自动恢复。
AWUM 自动唤醒 AWUM(Automatic bus-off management):自动唤醒功能,CAN 外设可以使用软件进入 低功耗的睡眠模式,如果使能了这个自动唤醒功能,当 CAN检测到总线活动的时候,会自动唤醒。
NART 自动重传NART(No automatic retransmission): 报文自动重传功能,设置这个功能后,当报文发送失败时会自动重传至成功为止。若不使用这个功能,无论发送结果如何,消息只发送一次。
RFLM锁定模式RFLM(Receive FIFO locked mode):FIFO 锁定模式,该功能用于锁定接收FIFO。锁定后,当接收FIFO溢出时,会丢弃下一个接收的报文。若不锁定,则下一个接收到的报文会覆盖原报文。
TXFP报文发送优先级的判定方法TXFP(Transmit FIFO priority):报文发送优先级的判定方法,当CAN外设的发送邮箱中有多个待发送报文时,本功能可以控制它是根据报文的ID优先级还是报文存进邮箱的顺序来发送。
位时序寄存器(CAN_BTR)及波特率:CAN外设中的位时序寄存器CAN_BTR用于配置测试模式、波特率以及各种位内的段参数。
正常模式:正常模式下就是一个正常的CAN节点,可以向总线发送数据和接收数据。
静默模式:静默模式下,它自己的输出端的逻辑0数据会直接传输到它自己的输入端,逻辑1可以被发送到总线,所以它不能向总线发送显性位(逻辑0),只能发送隐性位(逻辑1)。输入端可以从总线接收内容。由于它只可发送的隐性位不会强制影响总线的状态,所以把它称为静默模式。这种模式一般用于监测,它可以用于分析总线上的流量,但又不会因为发送显性位而影响总线。
回环模式:回环模式下,它自己的输出端的所有内容都直接传输到自己的输入端,输出端的内容同时也会被传输到总线上,即也可使用总线监测它的发送内容。输入端只接收自己发送端的内容,不接收来自总线上的内容。使用回环模式可以进行自检。
回环静默模式:该模式是以上两种模式的结合,自己的输出端的所有内容都直接传输到自己的输入端,并且不会向总线发送显性位影响总线,不能通过总线监测它的发送内容。输入端只接收自己发送端的内容,不接收来自总线上的内容。这种方式可以在“热自检”时使用,即自我检查的时候,不会干扰总线。
位时序及波特率: CKS32F107中CAN的位时序如图2所示。

图2 CAN位时序图
CKS32F107的CAN外设位时序中只包含3段,分别是同步段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数据位的时间:
T1bit =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接受FIFO
CKS32F107系列一共有2个接收FIFO,每个FIFO中有3个邮箱,即最多可以缓存6个接收到的报文。当接收到报文时,FIFO的报文计数器会自增,而CKS32F107内部读取FIFO数据之后,报文计数器会自减,我们通过状态寄存器可获知报文计数器的值,而通过前面主控制寄存器的RFLM位,可设置锁定模式,锁定模式下FIFO溢出时会丢弃新报文,非锁定模式下FIFO溢出时新报文会覆盖旧报文。跟发送邮箱类似,每个接收FIFO中包含有标识符寄存器CAN_RIxR、数据长度控制寄存器CAN_RDTxR及2个数据寄存器CAN_RDLxR、CAN_RDHxR,它们的功能见表发送邮箱的寄存器。通过中断或状态寄存器知道接收FIFO有数据后,我们再读取这些寄存器的值即可把接收到的报文加载到MCU的内存中。

验收筛选器
CAN 外设的验收筛选器,一共有28个筛选器组,每个筛选器组有2个寄存器,CAN1和CAN2共用筛选器。在CAN协议中,消息的标识符与节点地址无关,但与消息内容有关。因此,发送节点将报文广播给所有接收器时,接收节点会根据报文标识符的值来确定软件是否需要该消息,为了简化软件的工作,CAN外设接收报文前会先使用验收筛选器检查,只接收需要的报文到FIFO中。
初始化结构体
从CKS32F107的CAN外设我们了解到它的功能非常多,控制涉及的寄存器也非常丰富,而使用标准库提供的各种结构体及库函数可以简化这些控制过程。跟其它外设一样,标准库提供了CAN初始化结构体及初始化函数来控制CAN的工作方式,提供了收发报文使用的结构体及收发函数,还有配置控制筛选器模式及ID 的结构体。
列表1: 代码清单:CAN初始化结构体
typedef struct{
uint16_tCAN_Prescaler;
uint8_tCAN_Mode;
uint8_tCAN_SJW;
uint8_tCAN_BS1;
uint8_tCAN_BS2;
FunctionalState CAN_TTCM;
FunctionalState CAN_ABOM;
FunctionalState CAN_AWUM;
FunctionalState CAN_NART;
FunctionalState CAN_RFLM;
FunctionalState CAN_TXFP;
} CAN_InitTypeDef;(1) CAN_Prescaler
本成员设置CAN外设的时钟分频,它可控制时间片Tq的时间长度,这里设置的值最终会减1后再写入BRP寄存器位,即前面介绍的Tq计算公式:
Tq = (BRP[9:0]+1) x TPCLK
等效于:Tq = CAN_Prescaler x TPCLK
(2) CAN_Mode
本成员设置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发送及接收结构体
typedef struct
{uint32_t StdId;
uint32_t ExtId;
uint8_t IDE;
uint8_t RTR;
uint8_t DLC;
uint8_t Data[8];
} CanTxMsg;
typedef struct
{
uint32_t StdId;
uint32_t ExtId;
uint8_t IDE;
uint8_t RTR;
uint8_t DLC;
uint8_t Data[8];
uint8_t FMI;
} CanRxMsg;
(1) StdId
本成员存储的是报文的11位标准标识符,范围是0-0x7FF。
(2) ExtId
本成员存储的是报文的29位扩展标识符,范围是0-0x1FFFFFFF。ExtId 与 StdId这两个成员根据下面的IDE位配置,只有一个是有效的。
(3) IDE
本成员存储的是扩展标志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) Data[8]
本成员存储的就是数据帧中数据段的数据。
(7)FMI
本成员只存在于接收结构体,它存储了筛选器的编号,表示本报文是经过哪个筛选器存储进接收FIFO的,可以用它简化软件处理。当需要使用CAN发送报文时,先定义一个上面发送类型的结构体,然后把报文的内容按成员赋值到该结构体中,最后调用库函数CAN_Transmit把这些内容写入到发送邮箱即可把报文发送出去。 接收报文时,通过检测标志位获知接收FIFO的状态,若收到报文,可调用库函数CAN_Receive把接收FIFO中的内容读取到预先定义的接收类型结构体中,然后再访问该结构体即可利用报文了。
CAN筛选器结构体
列表3: 代码清单:CAN筛选器结构体
typedef struct
{
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;
FunctionalState 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_FilterFIFOAssignment
本成员用于设置当报文通过筛选器的匹配后,该报文会被存储到哪一个接收 FIFO,它的可选值为 FIFO0或FIFO1(宏CAN_Filter_FIFO0/1)。
(6) CAN_FilterNumber
本成员用于设置筛选器的编号,即本过滤器结构体配置的是哪一组筛选器,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_FilterActivation
本成员用于设置是否激活这个筛选器 (宏 ENABLE/DISABLE)。 配置完这些结构体成员后,我们调用库函数CAN_FilterInit 即可把这些参数写入到筛选控制寄存器中,从而使用筛选器。
来源:中科芯MCU
免责声明:本文为转载文章,转载此文目的在于传递更多信息,版权归原作者所有。本文所用视频、图片、文字如涉及作品版权问题,请联系小编进行处理(联系邮箱:cathy@eetrend.com)。