本帖最后由 宫影空明人不往 于 2023-7-30 20:21 编辑
前言
在上一篇帖子中,对CAN的一部分总线知识进行了介绍。这篇则是对APM32F103的CAN模块的应用进行讲解。
1.CAN模块框图
APM32F103的CAN模块可以分为三个方面组成,分别是CAN基础寄存器,发送邮箱以及过滤器和接收邮箱。
其中CAN基础寄存器主要对CAN的波特率,工作模式以及中断等进行配置。而发送邮箱则是存放我们需要发送到CAN总线上的信息。最后一部分则是通过设定好的过滤器将总线上的报文进行过滤并将确定接收的报文存放在接收邮箱中。
2.CAN基础寄存器
a.波特率
CAN波特率的计算即是1/位时间。通过上一篇CAN总线知识的帖子可以知道CAN的一位是由四个段组成,分别是同步段,传播时间段,相位缓冲段1以及相位缓冲段2。同时,每一个段由若干个时间单元组成。时间单元为CAN时钟分频后的一个单位时间。其中同步段为一个时间单元,而其他三个时间段由用户进行设置。配置CAN波特率主要通过CAN位时序寄存器,主要配置寄存器的分频系数以及时间段1和时间段2。具体如图所示:
这里的时间段1为传播时间段以及相位缓冲段1。因此,在配置位时序寄存器时,时间段1需要配置大于等于2,否则CAN无法正常通信。
通过上述的分析可以知道,CAN波特率的计算等于CAN时钟/(预分频系数(1+(时间段1+1)+(时间段2+1)))
当配置CAN波特率为1M时,CAN基础结构体设置如下:
/* CAN1 and CAN2 init */
canConfig.autoBusOffManage = DISABLE;
canConfig.autoWakeUpMode = DISABLE;
canConfig.nonAutoRetran = DISABLE;
canConfig.rxFIFOLockMode = DISABLE;
canConfig.txFIFOPriority = ENABLE;
canConfig.mode = CAN_MODE_NORMAL;
canConfig.syncJumpWidth = CAN_SJW_1;
canConfig.timeSegment1 = CAN_TIME_SEGMENT1_3;
canConfig.timeSegment2 = CAN_TIME_SEGMENT2_2;
canConfig.prescaler = 6;
预分频系数为6,时间段1为3,时间段2为2,而APM32F103CAN的时钟为36MHz,因此CAN的波特率为36/6/(1+2+3)=1MHz。
b.工作模式
CAN模块一共有四种工作模式,分别为静默模式,环回模式,静默环回模式以及正常模式。
静默模式则是CAN不会向总线发送信息,主要用于当做监听,而环回模式则是CAN不会接收总线上的信息,主要用于进行自测试。而静默环回模式则是两者的结合。而正常模式则是正常与总线进行通信的模式。
3.过滤器
过滤器是节点用于筛选信息的工具。通过判断ID是否是自己需要的再进行接收。过滤有两种模式,分别为:
列表模式;
掩码模式。
列表模式则是对整个ID号进行筛选,掩码模式则是对ID指定位置进行筛选。比如说下图的列表模式中,只有ID为123的报文通过了过滤器被接收,而掩码模式则前两个数字为12的ID的报文通过了过滤器被接收。
CAN的过滤器是两个32位寄存器为一组。当选择列表模式时,两个寄存器存放识别符;当选择掩码模式时,则第一个寄存器存放识别符,第二个寄存器存放筛选码。识别符的配置是有相应的格式的,由下图所示。
这里以16位过滤器进行解析,我们可以看见11位ID是左对齐的,因此在设置16位过滤器的时候需要将ID进行左移5位。同时看见[17:15]为EXTID,为保留位,在设置过滤远程帧时需左移3位。
比如说:
FilterStruct.filterNumber = 1;
FilterStruct.filterMode = CAN_FILTER_MODE_IDLIST;
FilterStruct.filterScale = CAN_FILTER_SCALE_16BIT;
FilterStruct.filterIdHigh = 0x0321 << 5;
FilterStruct.filterIdLow = 0x0321 << 5 | CAN_RTXR_REMOTE << 3;
FilterStruct.filterMaskIdHigh = 0x0000;
FilterStruct.filterMaskIdLow = 0x0000;
FilterStruct.filterFIFO = CAN_FILTER_FIFO_0;
FilterStruct.filterActivation = ENABLE;
在这个配置过滤器结构体中,配置的过滤器为16位过滤器,过滤的报文为ID为0x321的标准帧以及ID为0x321的远程帧。我们可以看见设置过滤器时将ID号左移了5位以及将远程帧左移了3位。因此,我们在配置过滤器时需要注意过滤器每一位的映像。
4.发送邮箱
发送邮箱则是配置发送的消息,包括:ID,扩展标识符,帧格式(数据帧,远程帧),数据长度以及字节数据。这些都是总线上报文所含有的信息。可以这么说,CAN模块向总线上发送报文就是将发送邮箱内的信息发送到总线上。同时,因为报文发送需要总线空闲,因此邮箱上的信息不能马上进行发送,可能会出现多个邮箱一起等待总线空闲,因此邮箱发送有优先级判定,优先级判定主要根据标识符(ID)或者请求次序。
同时,邮箱一共有四个状态,分别为空置,挂号,预定以及发送。其状态图如下:
邮箱一开始是空置状态,当请求发送后将进入挂号状态,这是就会判断自身优先级是否最高,如果是最高的优先级则进入预定状态,当总线空闲时就会进行发送,如果发送的时候进行仲裁并且失败后则退回预定状态,等待下一次总线空闲。这时候如果有更高优先级的邮箱请求发送的话,该邮箱则会退回到挂号状态,等待比他更高优先级的邮箱发送完毕。
5.接收邮箱
APM32F103的CAN接收邮箱为两个深度为3的队列。可在配置过滤器中指定某个接收邮箱进行接收。比如说上述过滤器代码配置中选择接收的邮箱为FIFO0。因为缓冲空间有限,因此当有新的报文被接收时而没有位置存储数据时,一是将新接收的数据丢弃,二就是覆盖原有的数据。因此,CAN通信需要主要数据及时接收。
APM32F103CAN模块的应用就简单讲解到这。对与CAN模块的简单使用其实很容易。首先就是配置好CAN的波特率,以及设置好CAN的过滤器配置,如果是需要发送,则将需要发送的信息填充在发送邮箱中并请求发送即可。这些在APM32F103的SDK中有都有合适的API调用。
需要注意的就是时间段1的配置(要大于等于2),以及CAN2的引脚重映射时需要将其放在REMAP1组其他重映射后面。这个在API中有提醒,具体原因并不知道,是在一次CAN2始终不能发送后排查错误发现的。对此大家有想法可以探讨下。
*
* @retval When you use GPIO_REMAP_CAN2, you must put this function last
* of all other ConfigPinRemap Function.
*/
void GPIO_ConfigPinRemap(GPIO_REMAP_T remap)
{
uint32_t val, mask, bitOffset, regOffset;
uint32_t regVal;
|