目录
参考:
过滤器的理解
STM32 参考手册中提到:bxCAN 控制器为应用程序提供了 28个位宽可变的、可配置的过滤器组(0~28))(103只有14个)每个过滤器组的位宽都可以独立配置。可以配置成 16 位或者 32 位。过滤器组还可配置为屏蔽位模式(标识符掩码)或标识符列表模式。
每个过滤器组x由2个32位寄存器,CAN_FxR1和 CAN_FxR2组成
先看一个过滤器组:如图
这里的 ID 并不是发送数据帧里面的ID,此ID非彼ID,硬件上属于不同的 register,这里的 ID 就是你需要去设置来达到你想要过滤接收某个数据 ID 的一串标识符,然后过滤器会根据你所设置的标识符 ID 来决定是不是要接受发过来的数据。
映射: 以映射的格式往 FxR1/2 中写入要进行过滤的 标识符ID 和掩码,很重要,必要按照格式来
屏蔽位模式:
参考图中 FBMX = 0 的情况
比如说我设置 标识符ID 为 0x300 ,在屏蔽位模式下,如果我的掩码设置为 0X3FF , 那么过滤器就可以接受也仅能接受 帧ID 为 0X300 的帧数据,因为掩码会和 标识符ID 一起来共同配合,来完成过滤,掩码的 ‘1’ 表示接受的 帧ID 的相应位必须和 FxR1 中相应位的 标识符ID 一致,‘0’:表示收到的 帧ID 中的相应位的不一定非要与设置的 标识符ID 一样。如果掩码设置为 0x300,那么过滤器就可以接受 0X300~0X3FF的 帧ID 数据
标识符列表模式:
参考图中 FBMX = 1 的情况
在2个32位过滤器情况下,CAN_FXR1和CAN_FXR2都作为 标识符ID,这种情况就很简单了,只有收到的 帧ID 必须和CAN_FXR1或者CAN_FXR2完全一致才能接受,就是一组过滤器只能接受两种不同的特定 帧ID
配置过滤器
标识符列表模式:
CAN_FilterInitStructure.CAN_FilterNumber=0; /*过滤器0*/
CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdList; /*标识符列表模式*/
CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit;
CAN_FilterInitStructure.CAN_FilterIdHigh=0x0040;
/*可以通过的标准帧ID设置为 0X0002*/
CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;
CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0060;
/*可以通过的标准帧ID 设置为 0X0003*/
CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;
CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_Filter_FIFO0;
/*过滤器组关联到FIFO0*/
CAN_FilterInitStructure.CAN_FilterActivation=ENABLE;
CAN_FilterInit(&CAN_FilterInitStructure);
上述用标识符列表模式,按照 “映射” 的格式配置 FxR1/2 寄存器,将可以通过的标准帧 ID 设置为了 0X0002 和 0X0003
屏蔽位模式:
将上述代码改为如下:
CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask;/*屏蔽位模式*/
CAN_FilterInitStructure.CAN_FilterIdHigh=0x0000;
CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;
CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0xFF00;
CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;
屏蔽位模式,在标准帧格式下设置成如上所示,可以通过的标准帧位 0X0000~0X0007
若想使用屏蔽位模式达到通过的标准帧为0X0000 ~ 0X0005,可以将代码修改成如下格式:
CAN_FilterInitStructure.CAN_FilterNumber=0; /*过滤器0*/
CAN_FilterInitStructure.CAN_FilterIdHigh=0x0000;
CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;
CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0xFF80;
CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;
/*可以通过的标准帧ID为 0X0000~0x0003*/
CAN_FilterInit(&CAN_FilterInitStructure);
CAN_FilterInitStructure.CAN_FilterNumber=1; /*过滤器1*/
CAN_FilterInitStructure.CAN_FilterIdHigh=0x0080;
CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;
CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0xFFC0;
CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;
/*可以通过的标准帧ID为 0X0004~0x0005*/
CAN_FilterInit(&CAN_FilterInitStructure);
使用两组过滤器进行过滤,需要注意的是,这里所有的过滤器组的组合工作方式不是像净水器一样一层层嵌套过滤。而是只要能通过任何一个过滤器组的帧 ID,都可以被保留。
比如 IDx 不能通过过滤器组0,但能通过过滤器组1。那么 IDx 就可以被通过 。在上述代码中,过滤器组0 过滤出来 0x0000~0x0003, 在过滤器组 1 上,由于mask 限制了 STID[2~1] 为10,所以过滤器组1 只能过滤出 0X0004 和 0X0005。所以最终可以被通过的标准帧ID 就为 0X0000 ~0x0005。
bxCAN波特率配置
bxCAN相关代码参考
CAN_InitStructure.CAN_TTCM=DISABLE; //非时间触发通信模式
CAN_InitStructure.CAN_ABOM=DISABLE; //软件自动离线管理
CAN_InitStructure.CAN_AWUM=DISABLE; //睡眠模式通过软件唤醒(清除CAN->MCR的SLEEP位
CAN_InitStructure.CAN_NART=ENABLE; //禁止报文自动传送
CAN_InitStructure.CAN_RFLM=DISABLE; //报文不锁定,新的覆盖旧的
CAN_InitStructure.CAN_TXFP=DISABLE; //优先级由报文标识符决定
CAN_InitStructure.CAN_Mode= mode; //模式设置
CAN_InitStructure.CAN_SJW=tsjw;
//重新同步跳跃宽度(Tsjw)为tsjw+1个时间单位 CAN_SJW_1tq~CAN_SJW_4tq
CAN_InitStructure.CAN_BS1=tbs1; //Tbs1范围CAN_BS1_1tq ~CAN_BS1_16tq
CAN_InitStructure.CAN_BS2=tbs2; //Tbs2范围CAN_BS2_1tq ~ CAN_BS2_8tq
CAN_InitStructure.CAN_Prescaler=brp; //分频系数(Fdiv)为brp+1
CAN_Init(CAN1, &CAN_InitStructure); // 初始化CAN1
前面6个成员变量用来设置寄存器CAN_MCR,也就是设置CAN通信相关的控制位
后面5个成员变量用来设置寄存器CAN_BTR,用来设置模式以及波特率相关的参数
CAN_SJW:再同步补偿宽度,因为时钟频率偏差,传送延迟等,各单元有同步误差,SJW为补偿此误差的最大值
来看看发送的结构体
typedef struct
{
uint32_t StdId; /*!< Specifies the standard identifier.
This parameter can be a value between 0 to 0x7FF. */
uint32_t ExtId; /*!< Specifies the extended identifier.
This parameter can be a value between 0 to 0x1FFFFFFF. */
uint8_t IDE; /*!< Specifies the type of identifier for the message that
will be transmitted. This parameter can be a value
of @ref CAN_identifier_type */
uint8_t RTR; /*!< Specifies the type of frame for the message that will
be transmitted. This parameter can be a value of
@ref CAN_remote_transmission_request */
uint8_t DLC; /*!< Specifies the length of the frame that will be
transmitted. This parameter can be a value between
0 to 8 */
uint8_t Data[8]; /*!< Contains the data to be transmitted. It ranges from 0
to 0xFF. */
} CanTxMsg;
StdId:标准帧ID,如果你要发送扩展帧,可以不用管它
ExtId:扩展帧ID,如果你要发送标准帧,可以不用管它
IDE:你是想发送标准帧还是扩展帧
RTR:你是要发送数据帧还是远程帧
DLC:你想发送数据的长度
Data[8]:你想要发送的数据