相信使用到h7系列单片机的伙计们都会发现CAN变成了FDCAN ,额其实质都是CAN只不过功能和效率上都比较好,具体看介绍就行。现在主要讲下FDCAN的过滤id问题,本来STM32的FDCAN使用的人也不多,网上并没有明确的解答,只是有网友提示下需要配置全局过滤器。后来我也尝试不行,只好看着资料和代码一步步试试。
我们先了解下过滤器的掩码问题,其实除H7系列外的can都有这个概念,也比较好解决。
假设id为32位,我们想要过滤某一个固定id号,如 : CAN_FilterID=0x00007F7F;
其掩码号也必须是32位,用CAN_FilterMaskId表示,CAN_FilterMaskId=0xFFFFFFFF;
你想要得到的ID=CAN_FilterID&CAN_FilterMaskId 其实这个关系就是每一位求与运算。
加入我们想要一个范围 0x00000020~0x00000030
CAN_FilterID=0x00000020; 0000 0000 0000 0000 0000 0000 0010 0000
CAN_FilterMaskId=0xFFFFFFF0; 1111 1111 1111 1111 1111 1111 1111 0000
掩码为1的位对应的过滤器ID是固定,0对应的就可以随意。
额有了其实CAN是11位和29位,而且stm32的普通CAN 11位或29位放在最高位。
好了回归话题,FDCAN使用hal库,看下正点原子的例程:
FDCAN_FilterTypeDef FDCAN1_RXFilter;
//初始化FDCAN1
HAL_FDCAN_DeInit(&FDCAN1_Handler); //先清除以前的设置
FDCAN1_Handler.Instance=FDCAN1;
FDCAN1_Handler.Init.FrameFormat=FDCAN_FRAME_CLASSIC; //传统模式
FDCAN1_Handler.Init.Mode=mode; //回环测试
FDCAN1_Handler.Init.AutoRetransmission=DISABLE; //关闭自动重传!传统模式下一定要关闭!!!
FDCAN1_Handler.Init.TransmitPause=DISABLE; //关闭传输暂停
FDCAN1_Handler.Init.ProtocolException=DISABLE; //关闭协议异常处理
FDCAN1_Handler.Init.NominalPrescaler=presc; //分频系数
FDCAN1_Handler.Init.NominalSyncJumpWidth=ntsjw; //重新同步跳跃宽度
FDCAN1_Handler.Init.NominalTimeSeg1=ntsg1; //tsg1范围:2~256
FDCAN1_Handler.Init.NominalTimeSeg2=ntsg2; //tsg2范围:2~128
FDCAN1_Handler.Init.MessageRAMOffset=0; //信息RAM偏移
FDCAN1_Handler.Init.StdFiltersNbr=0; //标准信息ID滤波器编号
FDCAN1_Handler.Init.ExtFiltersNbr=0; //扩展信息ID滤波器编号
FDCAN1_Handler.Init.RxFifo0ElmtsNbr=1; //接收FIFO0元素编号
FDCAN1_Handler.Init.RxFifo0ElmtSize=FDCAN_DATA_BYTES_8; //接收FIFO0元素大小:8字节
FDCAN1_Handler.Init.RxBuffersNbr=0; //接收缓冲编号
FDCAN1_Handler.Init.TxEventsNbr=0; //发送事件编号
FDCAN1_Handler.Init.TxBuffersNbr=0; //发送缓冲编号
FDCAN1_Handler.Init.TxFifoQueueElmtsNbr=1; //发送FIFO序列元素编号
FDCAN1_Handler.Init.TxFifoQueueMode=FDCAN_TX_FIFO_OPERATION; //发送FIFO序列模式
FDCAN1_Handler.Init.TxElmtSize=FDCAN_DATA_BYTES_8; //发送大小:8字节
if(HAL_FDCAN_Init(&FDCAN1_Handler)!=HAL_OK) return 1; //初始化FDCAN
//配置RX滤波器
FDCAN1_RXFilter.IdType=FDCAN_STANDARD_ID; //标准ID
FDCAN1_RXFilter.FilterIndex=0; //滤波器索引
FDCAN1_RXFilter.FilterType=FDCAN_FILTER_MASK; //滤波器类型
FDCAN1_RXFilter.FilterConfig=FDCAN_FILTER_TO_RXFIFO0; //过滤器0关联到FIFO0
FDCAN1_RXFilter.FilterID1=0x0000; //32位ID
FDCAN1_RXFilter.FilterID2=0x0000; //如果FDCAN配置为传统模式的话,这里是32位掩码
if(HAL_FDCAN_ConfigFilter(&FDCAN1_Handler,&FDCAN1_RXFilter)!=HAL_OK) return 2;//滤波器初始化
HAL_FDCAN_Start(&FDCAN1_Handler); //开启FDCAN
HAL_FDCAN_ActivateNotification(&FDCAN1_Handler,FDCAN_IT_RX_FIFO0_NEW_MESSAGE,0);
return 0;
上述并没有配置过过滤器,任何ID都可以接收。主要配置参量:FDCAN1_RXFilter
其结构体:
typedef struct
{
uint32_t IdType; /*!< Specifies the identifier type.
This parameter can be a value of @ref FDCAN_id_type */
uint32_t FilterIndex; /*!< Specifies the filter which will be initialized.
This parameter must be a number between:
- 0 and 127, if IdType is FDCAN_STANDARD_ID
- 0 and 63, if IdType is FDCAN_EXTENDED_ID */
uint32_t FilterType; /*!< Specifies the filter type.
This parameter can be a value of @ref FDCAN_filter_type.
The value FDCAN_EXT_FILTER_RANGE_NO_EIDM is permitted
only when IdType is FDCAN_EXTENDED_ID.
This parameter is ignored if FilterConfig is set to
FDCAN_FILTER_TO_RXBUFFER */
uint32_t FilterConfig; /*!< Specifies the filter configuration.
This parameter can be a value of @ref FDCAN_filter_config */
uint32_t FilterID1; /*!< Specifies the filter identification 1.
This parameter must be a number between:
- 0 and 0x7FF, if IdType is FDCAN_STANDARD_ID
- 0 and 0x1FFFFFFF, if IdType is FDCAN_EXTENDED_ID */
uint32_t FilterID2; /*!< Specifies the filter identification 2.
This parameter is ignored if FilterConfig is set to
FDCAN_FILTER_TO_RXBUFFER.
This parameter must be a number between:
- 0 and 0x7FF, if IdType is FDCAN_STANDARD_ID
- 0 and 0x1FFFFFFF, if IdType is FDCAN_EXTENDED_ID */
uint32_t RxBufferIndex; /*!< Contains the index of the Rx buffer in which the
matching message will be stored.
This parameter must be a number between 0 and 63.
This parameter is ignored if FilterConfig is different
from FDCAN_FILTER_TO_RXBUFFER */
uint32_t IsCalibrationMsg; /*!< Specifies whether the filter is configured for
calibration messages.
This parameter is ignored if FilterConfig is different
from FDCAN_FILTER_TO_RXBUFFER.
This parameter can be:
- 0 : ordinary message
- 1 : calibration message */
}FDCAN_FilterTypeDef;
后面两个RxBufferIndex,IsCalibrationMsg都不需要关注。
FDCAN1_RXFilter.IdType=FDCAN_STANDARD_ID; //我们选用标准id就可以 11位
FDCAN1_RXFilter.FilterIndex=0; //滤波器索引号这个可以0~63个索引号 你只有一个0就可以
FDCAN1_RXFilter.FilterType=FDCAN_FILTER_MASK; //滤波器类型 这里使用掩码方式 还有范围,二者或一方式
FDCAN1_RXFilter.FilterConfig=FDCAN_FILTER_TO_RXFIFO0; //过滤器0关联到FIFO0
FDCAN1_RXFilter.FilterID1=0x000; //你使用传统的fdcan的话就是0~7fff
FDCAN1_RXFilter.FilterID2=0x7ff; //也是上面一样0~7fff,写入7ff则代表全部是1,11个1,说明id是唯一,精确指定。
然后可以了?你可以试试在正点哪里改烧进去会不会只是接收0x0的id号。
。。。
。。。
。。。
。。。
恩其实是不行的,上面还不知道这个id号是要过来掉还是不要过来掉,对吧。那必须使用这个函数在配置下:
/**
* @brief Configure the FDCAN global filter.
* @param hfdcan: pointer to an FDCAN_HandleTypeDef structure that contains
* the configuration information for the specified FDCAN.
* @param NonMatchingStd: Defines how received messages with 11-bit IDs that
do not match any element of the filter list are treated.
This parameter can be a value of @arg FDCAN_Non_Matching_Frames.
* @param NonMatchingExt: Defines how received messages with 29-bit IDs that
do not match any element of the filter list are treated.
This parameter can be a value of @arg FDCAN_Non_Matching_Frames.
* @param RejectRemoteStd: Enable or disable the remote standard frames rejection.
This parameter can be set to ENABLE or DISABLE.
* @param RejectRemoteExt: Enable or disable the remote extended frames rejection.
This parameter can be set to ENABLE or DISABLE.
* @retval HAL status
*/
HAL_StatusTypeDef HAL_FDCAN_ConfigGlobalFilter(FDCAN_HandleTypeDef *hfdcan,
uint32_t NonMatchingStd,
uint32_t NonMatchingExt,
uint32_t RejectRemoteStd,
uint32_t RejectRemoteExt)
函数第一个参数就不用说,第二个从字面也可以知道不匹配的标准ID,第三个不匹配的扩展ID,第四个拒绝远程标准帧,第五个拒绝远程扩展帧。所以我们只需要接收id为0的数据帧,因此配置如下:
HAL_FDCAN_ConfigGlobalFilter(&FDCAN1_Handler,FDCAN_REJECT, FDCAN_REJECT, DISABLE, DISABLE);
第二个参数不匹配的标准id拒绝。
恩OK了,于是好开心!!!!!!!!!!!!!!!
.................................................................................................
.................................................................................................
.................................................................................................
.................................................................................................
.................................................................................................
然而实现总是那么让人失望!
额我就是经历过,后来只能好好靠自己了,看了原子的资料都感觉不知所云,还是老老实实看配置源代码。还没想到真有点头绪。
因为 #define IS_FDCAN_MAX_VALUE(VALUE, MAX) ((VALUE) <= (MAX))
所以前面的FDCAN1_Handler.Init.StdFiltersNbr和FDCAN1_Handler.Init.RxFifo0ElmtsNbr=1;肯定有问题。
于是接着修改发现竟然可以了。
整体代码如下:
FDCAN1_Handler.Init.FrameFormat=FDCAN_FRAME_CLASSIC; //传统模式
FDCAN1_Handler.Init.Mode=mode; //回环测试
FDCAN1_Handler.Init.AutoRetransmission=DISABLE; //关闭自动重传!传统模式下一定要关闭!!!
FDCAN1_Handler.Init.TransmitPause=DISABLE; //关闭传输暂停
FDCAN1_Handler.Init.ProtocolException=DISABLE; //关闭协议异常处理
FDCAN1_Handler.Init.NominalPrescaler=presc; //分频系数
FDCAN1_Handler.Init.NominalSyncJumpWidth=ntsjw; //重新同步跳跃宽度
FDCAN1_Handler.Init.NominalTimeSeg1=ntsg1; //tsg1范围:2~256
FDCAN1_Handler.Init.NominalTimeSeg2=ntsg2; //tsg2范围:2~128
FDCAN1_Handler.Init.MessageRAMOffset=0; //信息RAM偏移
FDCAN1_Handler.Init.StdFiltersNbr=1; //标准信息ID滤波器编号
FDCAN1_Handler.Init.ExtFiltersNbr=0; //扩展信息ID滤波器编号
FDCAN1_Handler.Init.RxFifo0ElmtsNbr=1; //接收FIFO0元素编号
FDCAN1_Handler.Init.RxFifo0ElmtSize=FDCAN_DATA_BYTES_8; //接收FIFO0元素大小:8字节
FDCAN1_Handler.Init.RxBuffersNbr=0; //接收缓冲编号
FDCAN1_Handler.Init.TxEventsNbr=0; //发送事件编号
FDCAN1_Handler.Init.TxBuffersNbr=0; //发送缓冲编号
FDCAN1_Handler.Init.TxFifoQueueElmtsNbr=1; //发送FIFO序列元素编号
FDCAN1_Handler.Init.TxFifoQueueMode=FDCAN_TX_FIFO_OPERATION; //发送FIFO序列模式
FDCAN1_Handler.Init.TxElmtSize=FDCAN_DATA_BYTES_8; //发送大小:8字节
if(HAL_FDCAN_Init(&FDCAN1_Handler)!=HAL_OK) return 1; //初始化FDCAN
//配置RX滤波器
FDCAN1_RXFilter.IdType=FDCAN_STANDARD_ID; //标准ID
FDCAN1_RXFilter.FilterIndex=0; //滤波器索引
FDCAN1_RXFilter.FilterType=FDCAN_FILTER_MASK; //滤波器类型
FDCAN1_RXFilter.FilterConfig=FDCAN_FILTER_TO_RXFIFO0; //过滤器0关联到FIFO0
FDCAN1_RXFilter.FilterID1=0x000; //32位ID
FDCAN1_RXFilter.FilterID2=0x7ff; //如果FDCAN配置为传统模式的话,这里是32位掩码
if(HAL_FDCAN_ConfigFilter(&FDCAN1_Handler,&FDCAN1_RXFilter)!=HAL_OK) return 2;//滤波器初始化
HAL_FDCAN_ConfigGlobalFilter(&FDCAN1_Handler,FDCAN_REJECT, FDCAN_REJECT, DISABLE, DISABLE);//FDCAN_ACCEPT_IN_RX_FIFO0
HAL_FDCAN_Start(&FDCAN1_Handler); //开启FDCAN
HAL_FDCAN_ActivateNotification(&FDCAN1_Handler,FDCAN_IT_RX_FIFO0_NEW_MESSAGE,0);
return 0;
如果你想一个范围的可以修改:
FDCAN1_RXFilter.FilterType=FDCAN_FILTER_RANGE;
FDCAN1_RXFilter.FilterID1=开始id
FDCAN1_RXFilter.FilterID2=结束id
就可以了。小弟技术不怎么只能靠这样方式一步一步解决,有说错地方请指出!
参考论坛:
https://community.st.com/s/question/0D50X00009XkaTdSAJ/stm32h7-fdcan-filter