STM32H7 FDCAN id过滤问题

相信使用到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了,于是好开心!!!!!!!!!!!!!!!

.................................................................................................

.................................................................................................

.................................................................................................

.................................................................................................

.................................................................................................

然而实现总是那么让人失望!

额我就是经历过,后来只能好好靠自己了,看了原子的资料都感觉不知所云,还是老老实实看配置源代码。还没想到真有点头绪。

 STM32H7 FDCAN id过滤问题_第1张图片

因为 #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

你可能感兴趣的:(STM32H7 FDCAN id过滤问题)