STM32H743使用FDCAN+TJA1042T配合CubeMX及HAL库实现仲裁段1M速率,数据段5M速率的FDCAN总线传输记录

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接收

接收无误

以上为FDCAN,简单使用方式

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值