STM32H743自带CAN控制器,外部需要加一个CAN收发器,即可实现CAN总线通信
本次使用TJA1042T作为CAN收发器,进行FDCAN通信,其中仲裁的波特率为1M,数据段波特兰为5M
下面直接上配置及代码
FDCAN时钟配置
此处配置为80Mhz
参数配置

仲裁段波特率=80M/(1+63+16)=1M
数据段波特率=80M/(1+13+2)=5M
选择4个标准过滤器,4个扩展ID过滤器
接收使用1个FIFI0,1个FIFO1,元素大小64字节
发送使用1个专用发送BUFFER,1个FIFO
本次实际只用了4个扩展ID过滤器,1个专用发送BUFFER,其余虽然配置了,但没有使用
开启中断
FDCAN有两条中断线,可以分配中断到不同的中断线上,默认均在中断0上产生

生成代码
FDCAN初始化,由CubeMX生成
FDCAN_HandleTypeDef hfdcan2;
/* FDCAN2 init function */
void MX_FDCAN2_Init(void)
{
hfdcan2.Instance = FDCAN2;
hfdcan2.Init.FrameFormat = FDCAN_FRAME_FD_BRS;
hfdcan2.Init.Mode = FDCAN_MODE_NORMAL;
hfdcan2.Init.AutoRetransmission = ENABLE;
hfdcan2.Init.TransmitPause = DISABLE;
hfdcan2.Init.ProtocolException = ENABLE;
hfdcan2.Init.NominalPrescaler = 1;
hfdcan2.Init.NominalSyncJumpWidth = 3;
hfdcan2.Init.NominalTimeSeg1 = 63;
hfdcan2.Init.NominalTimeSeg2 = 16;
hfdcan2.Init.DataPrescaler = 1;
hfdcan2.Init.DataSyncJumpWidth = 2;
hfdcan2.Init.DataTimeSeg1 = 13;
hfdcan2.Init.DataTimeSeg2 = 2;
hfdcan2.Init.MessageRAMOffset = 0;
hfdcan2.Init.StdFiltersNbr = 4;
hfdcan2.Init.ExtFiltersNbr = 4;
hfdcan2.Init.RxFifo0ElmtsNbr = 1;
hfdcan2.Init.RxFifo0ElmtSize = FDCAN_DATA_BYTES_64;
hfdcan2.Init.RxFifo1ElmtsNbr = 1;
hfdcan2.Init.RxFifo1ElmtSize = FDCAN_DATA_BYTES_64;
hfdcan2.Init.RxBuffersNbr = 4;
hfdcan2.Init.RxBufferSize = FDCAN_DATA_BYTES_64;
hfdcan2.Init.TxEventsNbr = 0;
hfdcan2.Init.TxBuffersNbr = 1;
hfdcan2.Init.TxFifoQueueElmtsNbr = 1;
hfdcan2.Init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION;
hfdcan2.Init.TxElmtSize = FDCAN_DATA_BYTES_64;
if (HAL_FDCAN_Init(&hfdcan2) != HAL_OK)
{
Error_Handler();
}
}
过滤器配置
此处配置了4个过滤器,只接收ID为1,2,3,4的数据
将接收的数据放到4个接收Buffer中,通过RxBufferIndex索引选择RxBuffer
void FDCAN_Filter_Config(void)
{
sFilterConfig.IdType = FDCAN_EXTENDED_ID;
sFilterConfig.FilterIndex = 0;
sFilterConfig.FilterType = FDCAN_FILTER_DUAL;
sFilterConfig.FilterConfig = FDCAN_FILTER_TO_RXBUFFER;
sFilterConfig.FilterID1 = 0x01;
sFilterConfig.FilterID2 = 0x01;
sFilterConfig.RxBufferIndex = 0;
sFilterConfig.IsCalibrationMsg = 0;
HAL_FDCAN_ConfigFilter(&hfdcan2, &sFilterConfig);
sFilterConfig.IdType = FDCAN_EXTENDED_ID;
sFilterConfig.FilterIndex = 1;
sFilterConfig.FilterType = FDCAN_FILTER_DUAL;
sFilterConfig.FilterConfig = FDCAN_FILTER_TO_RXBUFFER;
sFilterConfig.FilterID1 = 0x02;
sFilterConfig.FilterID2 = 0x02;
sFilterConfig.RxBufferIndex = 1;
sFilterConfig.IsCalibrationMsg = 0;
HAL_FDCAN_ConfigFilter(&hfdcan2, &sFilterConfig);
sFilterConfig.IdType = FDCAN_EXTENDED_ID;
sFilterConfig.FilterIndex = 2;
sFilterConfig.FilterType = FDCAN_FILTER_DUAL;
sFilterConfig.FilterConfig = FDCAN_FILTER_TO_RXBUFFER;
sFilterConfig.FilterID1 = 0x03;
sFilterConfig.FilterID2 = 0x03;
sFilterConfig.RxBufferIndex = 2;
sFilterConfig.IsCalibrationMsg = 0;
HAL_FDCAN_ConfigFilter(&hfdcan2, &sFilterConfig);
sFilterConfig.IdType = FDCAN_EXTENDED_ID;
sFilterConfig.FilterIndex = 3;
sFilterConfig.FilterType = FDCAN_FILTER_DUAL;
sFilterConfig.FilterConfig = FDCAN_FILTER_TO_RXBUFFER;
sFilterConfig.FilterID1 = 0x04;
sFilterConfig.FilterID2 = 0x04;
sFilterConfig.RxBufferIndex = 3;
sFilterConfig.IsCalibrationMsg = 0;
HAL_FDCAN_ConfigFilter(&hfdcan2, &sFilterConfig);
//*******************下面为其他配置**************************
//拒绝接收匹配不成功的标准ID和扩展ID,不接受远程帧
HAL_FDCAN_ConfigGlobalFilter(&hfdcan2,FDCAN_REJECT,FDCAN_REJECT,FDCAN_REJECT_REMOTE,FDCAN_REJECT_REMOTE);
HAL_FDCAN_ConfigFifoWatermark(&hfdcan2,FDCAN_CFG_RX_FIFO0,1);
HAL_FDCAN_ConfigFifoWatermark(&hfdcan2,FDCAN_CFG_RX_FIFO1,1);
HAL_FDCAN_ActivateNotification(&hfdcan2, FDCAN_IT_TX_COMPLETE, FDCAN_TX_BUFFER0);
HAL_FDCAN_ActivateNotification(&hfdcan2, FDCAN_IT_RX_FIFO0_WATERMARK, 0);
HAL_FDCAN_ActivateNotification(&hfdcan2, FDCAN_IT_RX_FIFO1_WATERMARK, 0);
HAL_FDCAN_ActivateNotification(&hfdcan2, FDCAN_IT_RX_BUFFER_NEW_MESSAGE, 0);
if (HAL_FDCAN_Start(&hfdcan2) != HAL_OK)//启动FDCAN
{
Error_Handler();
}
/***********************************************************************/
}
全局过滤器配置
FDCAN中有个全局过滤器,决定匹配不成功的ID的数据是否存放
拒绝接收匹配不成功的标准ID和扩展ID,不接受远程帧
HAL_FDCAN_ConfigGlobalFilter(&hfdcan2,FDCAN_REJECT,FDCAN_REJECT,FDCAN_REJECT_REMOTE,FDCAN_REJECT_REMOTE);
中断配置:
//以下为配置中断
HAL_FDCAN_ConfigFifoWatermark(&hfdcan2,FDCAN_CFG_RX_FIFO0,1);//接收FIFO 0水印,本次实验未使用
HAL_FDCAN_ConfigFifoWatermark(&hfdcan2,FDCAN_CFG_RX_FIFO1,1);//接收FIFO 1 水印 本次实验未使用
HAL_FDCAN_ActivateNotification(&hfdcan2, FDCAN_IT_TX_COMPLETE, FDCAN_TX_BUFFER0);//专用缓冲区数据发送完成,产生中断
//以下为激活中断
HAL_FDCAN_ActivateNotification(&hfdcan2, FDCAN_IT_RX_FIFO0_WATERMARK, 0); //本次实验未使用
HAL_FDCAN_ActivateNotification(&hfdcan2, FDCAN_IT_RX_FIFO1_WATERMARK, 0);// 本次实验未使用
HAL_FDCAN_ActivateNotification(&hfdcan2, FDCAN_IT_RX_BUFFER_NEW_MESSAGE, 0);//接收缓冲区接收到新数据,产生中断
发送配置:
发送一个数据包,扩展ID,数据帧,固定64字节,FDCAN格式,波特率切换
void FDCAN_Send_Packet(uint32_t id,uint8_t *data)
{
FDCAN_TxHeaderTypeDef pTxHeader;
pTxHeader.Identifier=id;
pTxHeader.IdType=FDCAN_EXTENDED_ID;
pTxHeader.TxFrameType=FDCAN_DATA_FRAME;
pTxHeader.DataLength=FDCAN_DLC_BYTES_64;
pTxHeader.ErrorStateIndicator=FDCAN_ESI_ACTIVE;
pTxHeader.BitRateSwitch=FDCAN_BRS_ON;
pTxHeader.FDFormat=FDCAN_FD_CAN;
pTxHeader.TxEventFifoControl=FDCAN_NO_TX_EVENTS;
pTxHeader.MessageMarker=0;
HAL_FDCAN_AddMessageToTxBuffer(&hfdcan2, &pTxHeader, data,FDCAN_TX_BUFFER0);//使用发送缓冲区发送
HAL_FDCAN_EnableTxBufferRequest(&hfdcan2,FDCAN_TX_BUFFER0);//使能发送Buffer发送,不使能无法发送
}
接收回调函数:
进入中断后,首先判断是哪个RxBuffer产生的数据,再从RxBuffer中将数据取出
void HAL_FDCAN_RxBufferNewMessageCallback(FDCAN_HandleTypeDef *hfdcan)
{
if (hfdcan == &hfdcan2)
{
if(HAL_FDCAN_IsRxBufferMessageAvailable(&hfdcan2,0)==1)
{
HAL_FDCAN_GetRxMessage(&hfdcan2,FDCAN_RX_BUFFER0,&pRxHeader,FD_CAN_DATA1);
}else if(HAL_FDCAN_IsRxBufferMessageAvailable(&hfdcan2,1)==1)
{
HAL_FDCAN_GetRxMessage(&hfdcan2,FDCAN_RX_BUFFER1,&pRxHeader,FD_CAN_DATA2);
}else if(HAL_FDCAN_IsRxBufferMessageAvailable(&hfdcan2,2)==1)
{
HAL_FDCAN_GetRxMessage(&hfdcan2,FDCAN_RX_BUFFER2,&pRxHeader,FD_CAN_DATA3);
}else if(HAL_FDCAN_IsRxBufferMessageAvailable(&hfdcan2,3)==1)
{
HAL_FDCAN_GetRxMessage(&hfdcan2,FDCAN_RX_BUFFER3,&pRxHeader,FD_CAN_DATA4);
}
}
}
实验验证
MCU发送:
ZCANPRO上位机配置
仲裁段1M,数据段5M
上位机接收
MCU接收:
上位机发送
发送扩展帧,ID为0x04,64字节数据长度
RxBuffer接收
接收无误