1.硬件上:CAN总线收发器一定需要匹配相应的支持FDCAN版本的收发器,就算是使用经典模式也必须选择FDCAN版本的收发器;
CAN总线波特率 = PLL1Q / Prescaler/(SEG1+SEG2+1),上图配置的fdCAN波特率为:25M/5/20=250kb/s
2,FDCAN 1配置:
ST官方例程省略配置DATA ,但是不推荐,容易出莫名奇妙的错误。
TxFifoQueueElmtsNbr 这个参数配置fifo数据,最大32,最好设置大点,否则容易阻塞。
其中粉红色为必须一致的参数配置,黄色的是必须注意的 ,绿色的是可更改参数;
FDCAN2和FDCAN1配置基本一致,不过配置完成后需要将 Message Ram Offset 在代码中修改为:
FDCAN2和FDCAN1配置基本一致,不过配置完成后需要将 Message Ram Offset 在代码中修改为:
hfdcan2.Init.MessageRAMOffset = hfdcan1.msgRam.EndAddress - SRAMCAN_BASE;
双CAN 收发正确配置函数,且 FDCAN1 配置为 fifo 0 接收中断 FDCAN2 配置为 fifo1 接收中断,并且可以配置不同的过滤器参数;
void MX_FDCAN1_Init(void)
{
hfdcan1.Instance = FDCAN1;
hfdcan1.Init.FrameFormat = FDCAN_FRAME_CLASSIC;
hfdcan1.Init.Mode = FDCAN_MODE_NORMAL;
hfdcan1.Init.AutoRetransmission = DISABLE;
hfdcan1.Init.TransmitPause = DISABLE;
hfdcan1.Init.ProtocolException = DISABLE;
hfdcan1.Init.NominalPrescaler = 5;
hfdcan1.Init.NominalSyncJumpWidth = 9;
hfdcan1.Init.NominalTimeSeg1 = 10;
hfdcan1.Init.NominalTimeSeg2 = 9;
hfdcan1.Init.DataPrescaler = 5;
hfdcan1.Init.DataSyncJumpWidth = 9;
hfdcan1.Init.DataTimeSeg1 = 10;
hfdcan1.Init.DataTimeSeg2 = 9;
hfdcan1.Init.MessageRAMOffset = 64;
hfdcan1.Init.StdFiltersNbr = 1;
hfdcan1.Init.ExtFiltersNbr = 1;
hfdcan1.Init.RxFifo0ElmtsNbr = 1;
hfdcan1.Init.RxFifo0ElmtSize = FDCAN_DATA_BYTES_8;
hfdcan1.Init.RxFifo1ElmtsNbr = 0;
hfdcan1.Init.RxFifo1ElmtSize = FDCAN_DATA_BYTES_8;
hfdcan1.Init.RxBuffersNbr = 0;
hfdcan1.Init.RxBufferSize = FDCAN_DATA_BYTES_8;
hfdcan1.Init.TxEventsNbr = 0;
hfdcan1.Init.TxBuffersNbr = 0;
hfdcan1.Init.TxFifoQueueElmtsNbr = 32;
hfdcan1.Init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION;
hfdcan1.Init.TxElmtSize = FDCAN_DATA_BYTES_8;
if (HAL_FDCAN_Init(&hfdcan1) != HAL_OK)
{
Error_Handler();
}
}
/* FDCAN2 init function */
void MX_FDCAN2_Init(void)
{
hfdcan2.Instance = FDCAN2;
hfdcan2.Init.FrameFormat = FDCAN_FRAME_CLASSIC;
hfdcan2.Init.Mode = FDCAN_MODE_NORMAL;
hfdcan2.Init.AutoRetransmission = DISABLE;
hfdcan2.Init.TransmitPause = DISABLE;
hfdcan2.Init.ProtocolException = DISABLE;
hfdcan2.Init.NominalPrescaler = 5;
hfdcan2.Init.NominalSyncJumpWidth = 9;
hfdcan2.Init.NominalTimeSeg1 = 10;
hfdcan2.Init.NominalTimeSeg2 = 9;
hfdcan2.Init.DataPrescaler = 5;
hfdcan2.Init.DataSyncJumpWidth = 9;
hfdcan2.Init.DataTimeSeg1 = 10;
hfdcan2.Init.DataTimeSeg2 = 9;
hfdcan2.Init.MessageRAMOffset = hfdcan2.Init.MessageRAMOffset = hfdcan1.msgRam.EndAddress - SRAMCAN_BASE;;
hfdcan2.Init.StdFiltersNbr = 1;
hfdcan2.Init.ExtFiltersNbr = 0;
hfdcan2.Init.RxFifo0ElmtsNbr = 0;
hfdcan2.Init.RxFifo0ElmtSize = FDCAN_DATA_BYTES_8;
hfdcan2.Init.RxFifo1ElmtsNbr = 2;
hfdcan2.Init.RxFifo1ElmtSize = FDCAN_DATA_BYTES_8;
hfdcan2.Init.RxBuffersNbr = 0;
hfdcan2.Init.RxBufferSize = FDCAN_DATA_BYTES_8;
hfdcan2.Init.TxEventsNbr = 0;
hfdcan2.Init.TxBuffersNbr = 0;
hfdcan2.Init.TxFifoQueueElmtsNbr = 32;
hfdcan2.Init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION;
hfdcan2.Init.TxElmtSize = FDCAN_DATA_BYTES_8;
if (HAL_FDCAN_Init(&hfdcan2) != HAL_OK)
{
Error_Handler();
}
}
过滤器配置
#include "bsp_fdcan.h"
#include "bsp_usart.h"
#include "fdcan.h"
FDCAN_HandleTypeDef bsp_hfdcan1;
FDCAN_HandleTypeDef bsp_hfdcan2;
FDCAN_TxHeaderTypeDef TxHeader;
FDCAN_RxHeaderTypeDef RxHeader;
//必须将此函数加入 生成的can初始化响应位置,否则将影响从fdcan2的使用
// hfdcan2.Init.MessageRAMOffset = hfdcan1.msgRam.EndAddress - SRAMCAN_BASE;
static uint32_t HAL_RCC_FDCAN_CLK_ENABLED=0;
/******************************************************************
* @brief 初始化配置FDCAN1 各项功能函数,开启FDCAN 收发
*
* @brief 过滤器模式为 范围模式 0x00 - 0x7ff 绑定过滤参数到fifo0
*
* @param
*
* @return
*******************************************************************/
void bsp_fdcan1_init(void)
{
/* 配置RX滤波器 */
FDCAN_FilterTypeDef FDCAN_RXFilter={0};
FDCAN_RXFilter.IdType=FDCAN_STANDARD_ID; //标准ID
FDCAN_RXFilter.FilterIndex=0; //滤波器索引
FDCAN_RXFilter.FilterType=FDCAN_FILTER_RANGE; //滤波器类型
FDCAN_RXFilter.FilterConfig=FDCAN_FILTER_TO_RXFIFO0; //过滤器0关联到FIFO0
FDCAN_RXFilter.FilterID1=0x00; //32位ID1
FDCAN_RXFilter.FilterID2=0x7FF; //32位ID2
if (HAL_FDCAN_ConfigFilter(&hfdcan1, &FDCAN_RXFilter) != HAL_OK)
{
Error_Handler();
}
if (HAL_FDCAN_ConfigGlobalFilter(&hfdcan1, FDCAN_REJECT, FDCAN_REJECT, FDCAN_FILTER_REMOTE, FDCAN_FILTER_REMOTE) != HAL_OK)
{
Error_Handler();
}
/* Start the FDCAN module */
if (HAL_FDCAN_Start(&hfdcan1) != HAL_OK)
{
Error_Handler();
}
/* 开启CAN 收发中断 */
if (HAL_FDCAN_ActivateNotification(&hfdcan1, FDCAN_IT_RX_FIFO0_NEW_MESSAGE, 0) != HAL_OK)
{
Error_Handler();
}
}
/******************************************************************
* @brief 初始化配置FDCAN1 各项功能函数,开启FDCAN 收发
*
* @brief 过滤器模式为 范围模式 0x00 - 0x7ff 绑定过滤参数到fifo1
*
* @param
*
* @return
*******************************************************************/
void bsp_fdcan2_init(void)
{
/* 配置RX滤波器 */
FDCAN_FilterTypeDef FDCAN_RXFilter={0};
FDCAN_RXFilter.IdType=FDCAN_STANDARD_ID; //标准ID
FDCAN_RXFilter.FilterIndex=0; //滤波器索引
FDCAN_RXFilter.FilterType=FDCAN_FILTER_RANGE; //滤波器类型
FDCAN_RXFilter.FilterConfig=FDCAN_FILTER_TO_RXFIFO1; //过滤器1关联到FIFO1
FDCAN_RXFilter.FilterID1=0x00; //32位ID1
FDCAN_RXFilter.FilterID2=0x7ff; //32位ID2
if (HAL_FDCAN_ConfigFilter(&hfdcan2, &FDCAN_RXFilter) != HAL_OK)
{
Error_Handler();
}
if (HAL_FDCAN_ConfigGlobalFilter(&hfdcan2, FDCAN_REJECT, FDCAN_REJECT, FDCAN_FILTER_REMOTE, FDCAN_FILTER_REMOTE) != HAL_OK)
{
Error_Handler();
}
/* Start the FDCAN module */
if (HAL_FDCAN_Start(&hfdcan2) != HAL_OK)
{
Error_Handler();
}
/* 开启CAN 收发中断 */
if (HAL_FDCAN_ActivateNotification(&hfdcan2, FDCAN_IT_RX_FIFO1_NEW_MESSAGE, 0) != HAL_OK)
{
Error_Handler();
}
}
/******************************************************************
* @brief FDCAN发送函数
*
* @brief函数使用方法备注
*
* @param can设备句柄
*
* @return
*******************************************************************/
void bsp_fdcan_send(FDCAN_HandleTypeDef* hfdcan,bsp_can_msg_t* msg)
{
TxHeader.Identifier = msg->cob_id;
TxHeader.IdType = FDCAN_STANDARD_ID;
/*判断数据帧类型*/
if(msg->rtr == 0)
TxHeader.TxFrameType = FDCAN_DATA_FRAME;
else if(msg->rtr == 1)
TxHeader.TxFrameType = FDCAN_REMOTE_FRAME;
/*判断参数是否合规*/
msg->len = msg->len >= 0 && msg->len <= 8 ? msg->len : 0;
/*更改fdcan数据长度定义*/
TxHeader.DataLength = msg->len<<16;
TxHeader.ErrorStateIndicator = FDCAN_ESI_ACTIVE;
TxHeader.BitRateSwitch = FDCAN_BRS_OFF;
TxHeader.FDFormat = FDCAN_CLASSIC_CAN;
TxHeader.TxEventFifoControl = FDCAN_NO_TX_EVENTS;
TxHeader.MessageMarker = 0;
HAL_FDCAN_AddMessageToTxFifoQ(hfdcan, &TxHeader, msg->data);
}
/******************************************************************
* @brief FDCAN1 接收回调函数
*
* @brief
*
* @param
*
* @return
*******************************************************************/
//FD CAN1 收取中断
void HAL_FDCAN_RxFifo0Callback(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs)
{
u8 msg[8];
if((RxFifo0ITs & FDCAN_IT_RX_FIFO0_NEW_MESSAGE) != RESET) //FIFO1新数据中断
{
/* 提取FIFO0中接收到的数据 */
HAL_GPIO_TogglePin(LED_ERROR_GPIO_Port,LED_ERROR_Pin);
HAL_FDCAN_GetRxMessage(hfdcan,FDCAN_RX_FIFO0,&RxHeader,msg);
// HAL_FDCAN_ActivateNotification(hfdcan, FDCAN_IT_RX_FIFO0_NEW_MESSAGE, 0);
}
HAL_FDCAN_ActivateNotification(hfdcan, FDCAN_IT_RX_FIFO0_NEW_MESSAGE, 0);
}
//FD CAN2 收取中断
void HAL_FDCAN_RxFifo1Callback(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo1ITs)
{
u8 msg[8];
if((RxFifo1ITs & FDCAN_IT_RX_FIFO1_NEW_MESSAGE) != RESET) //FIFO1新数据中断
{
/* 提取FIFO1中接收到的数据 */
HAL_GPIO_TogglePin(LED_RUN_GPIO_Port,LED_RUN_Pin);
HAL_FDCAN_GetRxMessage(hfdcan,FDCAN_RX_FIFO1,&RxHeader,msg);
HAL_FDCAN_ActivateNotification(hfdcan, FDCAN_IT_RX_FIFO1_NEW_MESSAGE, 0);
}
// HAL_FDCAN_ActivateNotification(hfdcan, FDCAN_IT_RX_FIFO0_NEW_MESSAGE, 0);
}
#ifndef __BSP_FDCAN_H__
#define __BSP_FDCAN_H__
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "bsp_sys.h"
typedef struct
{
u16 cob_id; // msg id
u8 rtr; //帧模式
u8 len; //数据长度
u8 data[8]; //数据域
}bsp_can_msg_t;
extern FDCAN_TxHeaderTypeDef TxHeader;
extern FDCAN_RxHeaderTypeDef RxHeader;
extern uint8_t FDCAN_TxData[8];
extern uint8_t FDCAN_RxData[8];
void bsp_fdcan1_init(void);
void bsp_fdcan2_init(void);
void bsp_fdcan_send(FDCAN_HandleTypeDef* hfdcan,bsp_can_msg_t* msg);
#ifdef __cplusplus
}
#endif
#endif /* __FDCAN_H__ */
FDCAN1_RXFilter.FilterType=FDCAN_FILTER_RANGE;
FDCAN1_RXFilter.FilterID1=开始id
FDCAN1_RXFilter.FilterID2=结束id