基于STM32H743的调试记录5——FDCAN

H743的CAN介绍

对比F1、F4系列的单片机,H7的CAN做出了全面的优化升级;相较于之前的CAN设有固定的滤波器组,和FIFO;H7则直接使用了10KB的共享消息RAM进行数据的存储与配置。使得数据的处理量大大增加。

初始化CAN1

FDCAN_HandleTypeDef FDCAN1_Handler;
FDCAN_RxHeaderTypeDef FDCAN1_RxHeader;
FDCAN_TxHeaderTypeDef FDCAN1_TxHeader;

//初始化FDCAN1,波特率为500Kbit/S
//配置FDCAN1的时钟源为PLL1Q=200Mhz
//presc:分频值,取值范围1~512
//ntsjw:重新同步跳跃时间单元.范围:1~128
//ntsg1: 取值范围2~256
//ntsg2: 取值范围2~128
//mode:FDCAN_MODE_NORMAL,普通模式;FDCAN_MODE_EXTERNAL_LOOPBACK,回环模式;
//返回值:0,初始化OK;
//    其他,初始化失败; 
u8 FDCAN1_Mode_Init(u16 presc,u8 ntsjw,u16 ntsg1,u8 ntsg2,u32 mode)
{
    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.DataPrescaler = 0x0A;      /* CAN时钟分配设置,一般设置为1即可,全部由PLL配置好,tq = NominalPrescaler x (1/ fdcan_ker_ck),范围1-32 */
	FDCAN1_Handler.Init.DataSyncJumpWidth = 0x04;  /* 用于动态调节  Phase_Seg1和 Phase_Seg1,所以不可以比Phase_Seg1和 Phase_Seg1大,范围1-16 */
	FDCAN1_Handler.Init.DataTimeSeg1 = 0x05; 		/* 特别注意这里的Seg1,这里是两个参数之和,对应位时间特性图的 Pro_Seg + Phase_Seg1,范围 */
	FDCAN1_Handler.Init.DataTimeSeg2 = 0x04;       /* 对应位时间特性图的 Phase_Seg2 */    
   
    FDCAN1_Handler.Init.MessageRAMOffset=0;                         //信息RAM偏移   /* CAN1和CAN2共享2560个字, 这里CAN1分配前1280字 */

	FDCAN1_Handler.Init.StdFiltersNbr = 0;         			/* 设置标准ID过滤器个数,范围0-128 */       
	FDCAN1_Handler.Init.ExtFiltersNbr = 2;         			/* 设置扩展ID过滤器个数,范围0-64 */  

    FDCAN1_Handler.Init.RxFifo0ElmtsNbr = 4;                   /* 设置Rx FIFO0的元素个数,范围0-64 */   //通常 1个滤波器在列表模式下是两个 数据元素
	FDCAN1_Handler.Init.RxFifo0ElmtSize = FDCAN_DATA_BYTES_8; 	/* 设置Rx FIFO0中每个元素大小,支持8,12,16,20,24,32,48或者64字节 */   
	
	FDCAN1_Handler.Init.RxFifo1ElmtsNbr = 0;                   /* 设置Rx FIFO1的元素个数,范围0-64 */
	FDCAN1_Handler.Init.RxFifo1ElmtSize = FDCAN_DATA_BYTES_8;  /* 设置Rx FIFO1中每个元素大小,支持8,12,16,20,24,32,48或者64字节 */	
	
	FDCAN1_Handler.Init.RxBuffersNbr = 0;                      /* 设置Rx Buffer个数,范围0-64 */
	FDCAN1_Handler.Init.RxBufferSize = 0;                      /* 设置Rx Buffer中每个元素大小,支持8,12,16,20,24,32,48或者64字节 */	

    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_EXTENDED_ID;                       //扩展帧ID
    FDCAN1_RXFilter.FilterIndex=0;                                  //滤波器索引                   
    FDCAN1_RXFilter.FilterType=FDCAN_FILTER_DUAL;                   //滤波器类型  专用ID
    FDCAN1_RXFilter.FilterConfig=FDCAN_FILTER_TO_RXFIFO0;           //过滤器0关联到FIFO0  
    FDCAN1_RXFilter.FilterID1=0x0CF00400;                             //发动机转速 扭矩          //32位ID
    FDCAN1_RXFilter.FilterID2=0x18FEF700;                           /发动机输入电压         //如果FDCAN配置为传统模式的话,这里是32位掩码
    if(HAL_FDCAN_ConfigFilter(&FDCAN1_Handler,&FDCAN1_RXFilter)!=HAL_OK) return 2;//滤波器初始化

    FDCAN1_RXFilter.IdType=FDCAN_EXTENDED_ID;                       //扩展帧ID
    FDCAN1_RXFilter.FilterIndex=1;                                  //滤波器索引                   
    FDCAN1_RXFilter.FilterType=FDCAN_FILTER_DUAL;                   //滤波器类型  专用ID
    FDCAN1_RXFilter.FilterConfig=FDCAN_FILTER_TO_RXFIFO0;           //过滤器0关联到FIFO0  
    FDCAN1_RXFilter.FilterID1=0x18FEEE00;                             ///发动机冷却液温度        //32位ID
    FDCAN1_RXFilter.FilterID2=0xFFFFFFFF;                               //如果FDCAN配置为传统模式的话,这里是32位掩码
    if(HAL_FDCAN_ConfigFilter(&FDCAN1_Handler,&FDCAN1_RXFilter)!=HAL_OK) return 2;//滤波器初始化
    
    HAL_FDCAN_ConfigGlobalFilter(&FDCAN1_Handler,FDCAN_REJECT,FDCAN_REJECT,ENABLE,ENABLE);  
    HAL_FDCAN_Start(&FDCAN1_Handler);                               //开启FDCAN
    HAL_FDCAN_ActivateNotification(&FDCAN1_Handler,FDCAN_IT_RX_FIFO0_NEW_MESSAGE,0);
    return 0;
}

注意滤波器的个数和元素的对应 这里使用的是列表法过滤数据
只使用了FIFIO0的接收!

初始化CAN2

//初始化FDCAN2,波特率为500Kbit/S
//配置FDCAN1的时钟源为PLL1Q=200Mhz
//presc:分频值,取值范围1~512
//ntsjw:重新同步跳跃时间单元.范围:1~128
//ntsg1: 取值范围2~256
//ntsg2: 取值范围2~128
//mode:FDCAN_MODE_NORMAL,普通模式;FDCAN_MODE_EXTERNAL_LOOPBACK,回环模式;
//返回值:0,初始化OK;
//    其他,初始化失败; 
u8 FDCAN2_Mode_Init(u16 presc,u8 ntsjw,u16 ntsg1,u8 ntsg2,u32 mode)
{
    FDCAN_FilterTypeDef FDCAN2_RXFilter;
        
    //初始化FDCAN1
    HAL_FDCAN_DeInit(&FDCAN2_Handler);                              //先清除以前的设置
    FDCAN2_Handler.Instance=FDCAN2;
    FDCAN2_Handler.Init.FrameFormat=FDCAN_FRAME_CLASSIC;            //传统模式 不变波特率
    FDCAN2_Handler.Init.Mode=mode;                                  //普通模式
    FDCAN2_Handler.Init.AutoRetransmission=DISABLE;                 //关闭自动重传!传统模式下一定要关闭!!!
    FDCAN2_Handler.Init.TransmitPause=DISABLE;                      //关闭传输暂停
    FDCAN2_Handler.Init.ProtocolException=ENABLE;                  //协议异常处理
    FDCAN2_Handler.Init.NominalPrescaler=presc;                     //分频系数
    FDCAN2_Handler.Init.NominalSyncJumpWidth=ntsjw;                 //重新同步跳跃宽度
    FDCAN2_Handler.Init.NominalTimeSeg1=ntsg1;                      //tsg1范围:2~256
    FDCAN2_Handler.Init.NominalTimeSeg2=ntsg2;                      //tsg2范围:2~128

    FDCAN2_Handler.Init.DataPrescaler = 0x0A;      /* CAN时钟分配设置,一般设置为1即可,全部由PLL配置好,tq = NominalPrescaler x (1/ fdcan_ker_ck),范围1-32 */
	FDCAN2_Handler.Init.DataSyncJumpWidth = 0x04;  /* 用于动态调节  Phase_Seg1和 Phase_Seg1,所以不可以比Phase_Seg1和 Phase_Seg1大,范围1-16 */
	FDCAN2_Handler.Init.DataTimeSeg1 = 0x05; 		/* 特别注意这里的Seg1,这里是两个参数之和,对应位时间特性图的 Pro_Seg + Phase_Seg1,范围 */
	FDCAN2_Handler.Init.DataTimeSeg2 = 0x04;       /* 对应位时间特性图的 Phase_Seg2 */    
   
    FDCAN2_Handler.Init.MessageRAMOffset=1280;                         //信息RAM偏移   /* CAN1和CAN2共享2560个字, 这里CAN1分配前1280字 */

	FDCAN2_Handler.Init.StdFiltersNbr = 0;         			/* 设置标准ID过滤器个数,范围0-128 */       
	FDCAN2_Handler.Init.ExtFiltersNbr = 1;         			/* 设置扩展ID过滤器个数,范围0-64 */  
    
    FDCAN2_Handler.Init.RxFifo0ElmtsNbr = 2;                   /* 设置Rx FIFO0的元素个数,范围0-64 */   //通常 1个滤波器在列表模式下是两个 数据元素
	FDCAN2_Handler.Init.RxFifo0ElmtSize = FDCAN_DATA_BYTES_8; 	/* 设置Rx FIFO0中每个元素大小,支持8,12,16,20,24,32,48或者64字节 */   
	
	FDCAN2_Handler.Init.RxFifo1ElmtsNbr = 0;                   /* 设置Rx FIFO1的元素个数,范围0-64 */
	FDCAN2_Handler.Init.RxFifo1ElmtSize = FDCAN_DATA_BYTES_8;  /* 设置Rx FIFO1中每个元素大小,支持8,12,16,20,24,32,48或者64字节 */	
	
	FDCAN2_Handler.Init.RxBuffersNbr = 0;                      /* 设置Rx Buffer个数,范围0-64 */
	FDCAN2_Handler.Init.RxBufferSize = 0;                      /* 设置Rx Buffer中每个元素大小,支持8,12,16,20,24,32,48或者64字节 */	


    FDCAN2_Handler.Init.TxEventsNbr=0;                              //发送事件编号
    FDCAN2_Handler.Init.TxBuffersNbr=0;                             //发送缓冲编号
    FDCAN2_Handler.Init.TxFifoQueueElmtsNbr=1;                      //发送FIFO序列元素编号
    FDCAN2_Handler.Init.TxFifoQueueMode=FDCAN_TX_FIFO_OPERATION;    //发送FIFO序列模式
    FDCAN2_Handler.Init.TxElmtSize=FDCAN_DATA_BYTES_8;              //发送大小:8字节
    if(HAL_FDCAN_Init(&FDCAN2_Handler)!=HAL_OK) return 1;           //初始化FDCAN
  
    //配置RX滤波器   
    FDCAN2_RXFilter.IdType=FDCAN_STANDARD_ID;                       //标准帧ID  //扩展帧ID
    FDCAN2_RXFilter.FilterIndex=0;                                  //滤波器索引                   
    FDCAN2_RXFilter.FilterType=FDCAN_FILTER_DUAL;                   //滤波器类型  列表 FDCAN_FILTER_DUAL  掩码 FDCAN_FILTER_MASK  范围FDCAN_FILTER_RANGE
    FDCAN2_RXFilter.FilterConfig=FDCAN_FILTER_TO_RXFIFO0;           //过滤器0关联到FIFO0  
    FDCAN2_RXFilter.FilterID1=0x179;                               //32位ID
    FDCAN2_RXFilter.FilterID2=0x180;                               //如果FDCAN配置为传统模式的话,这里是32位掩码
    if(HAL_FDCAN_ConfigFilter(&FDCAN2_Handler,&FDCAN2_RXFilter)!=HAL_OK) return 2;//滤波器初始化
     
    FDCAN2_RXFilter.IdType=FDCAN_STANDARD_ID;                       //标准帧ID  //扩展帧ID
    FDCAN2_RXFilter.FilterIndex=1;                                  //滤波器索引                   
    FDCAN2_RXFilter.FilterType=FDCAN_FILTER_DUAL;                   //滤波器类型  列表 FDCAN_FILTER_DUAL  掩码 FDCAN_FILTER_MASK  范围FDCAN_FILTER_RANGE
    FDCAN2_RXFilter.FilterConfig=FDCAN_FILTER_TO_RXFIFO0;           //过滤器0关联到FIFO0  
    FDCAN2_RXFilter.FilterID1=0x285;                               //32位ID
    FDCAN2_RXFilter.FilterID2=0x188;                               //如果FDCAN配置为传统模式的话,这里是32位掩码
    if(HAL_FDCAN_ConfigFilter(&FDCAN2_Handler,&FDCAN2_RXFilter)!=HAL_OK) return 2;//滤波器初始化
     
    FDCAN2_RXFilter.IdType=FDCAN_STANDARD_ID;                       //标准帧ID  //扩展帧ID
    FDCAN2_RXFilter.FilterIndex=2;                                  //滤波器索引                   
    FDCAN2_RXFilter.FilterType=FDCAN_FILTER_DUAL;                   //滤波器类型  列表 FDCAN_FILTER_DUAL  掩码 FDCAN_FILTER_MASK  范围FDCAN_FILTER_RANGE
    FDCAN2_RXFilter.FilterConfig=FDCAN_FILTER_TO_RXFIFO0;           //过滤器0关联到FIFO0  
    FDCAN2_RXFilter.FilterID1=0x288;                               //32位ID
    FDCAN2_RXFilter.FilterID2=0x488;                               //如果FDCAN配置为传统模式的话,这里是32位掩码
    if(HAL_FDCAN_ConfigFilter(&FDCAN2_Handler,&FDCAN2_RXFilter)!=HAL_OK) return 2;//滤波器初始化
        
    HAL_FDCAN_ConfigGlobalFilter(&FDCAN2_Handler,FDCAN_REJECT,FDCAN_REJECT,ENABLE,ENABLE);  
    HAL_FDCAN_Start(&FDCAN2_Handler);                               //开启FDCAN
    HAL_FDCAN_ActivateNotification(&FDCAN2_Handler,FDCAN_IT_RX_FIFO0_NEW_MESSAGE,0);
    return 0;
}

注意: FDCAN2_Handler.Init.MessageRAMOffset=1280; //信息RAM偏移 /* CAN1和CAN2共享2560个字, 这里CAN1分配前1280字 */ 这里标注里内存地址的偏移量 本文均分了内存 可以根据实际情况分配

引脚分配

//FDCAN1底层驱动,引脚配置,时钟使能
//HAL_FDCAN_Init()调用
//hsdram:FDCAN1句柄
//FDCAN2底层驱动,引脚配置,时钟使能
//HAL_FDCAN_Init()调用
//hsdram:FDCAN1句柄
void HAL_FDCAN_MspInit(FDCAN_HandleTypeDef* hfdcan)
{
    GPIO_InitTypeDef GPIO_Initure;
    RCC_PeriphCLKInitTypeDef FDCAN_PeriphClk;
    
    __HAL_RCC_FDCAN_CLK_ENABLE();                   //使能FDCAN1时钟
    __HAL_RCC_GPIOA_CLK_ENABLE();			        //开启GPIOA时钟
    __HAL_RCC_GPIOB_CLK_ENABLE();			        //开启GPIOB时钟
    //FDCAN1时钟源配置为PLL1Q
    FDCAN_PeriphClk.PeriphClockSelection=RCC_PERIPHCLK_FDCAN;
    FDCAN_PeriphClk.FdcanClockSelection=RCC_FDCANCLKSOURCE_PLL;
    HAL_RCCEx_PeriphCLKConfig(&FDCAN_PeriphClk);
	if(hfdcan == &FDCAN1_Handler)
    {
        GPIO_Initure.Pin=GPIO_PIN_11|GPIO_PIN_12;       //PA11,12
        GPIO_Initure.Mode=GPIO_MODE_AF_PP;              //推挽复用
        GPIO_Initure.Pull=GPIO_PULLUP;                  //上拉
        GPIO_Initure.Speed=GPIO_SPEED_FREQ_MEDIUM;      //超高速
        GPIO_Initure.Alternate=GPIO_AF9_FDCAN1;         //复用为CAN1
        HAL_GPIO_Init(GPIOA,&GPIO_Initure);             //初始化
        
        
        HAL_NVIC_SetPriority(FDCAN1_IT0_IRQn, 2, 0);
        HAL_NVIC_SetPriority(FDCAN1_IT1_IRQn, 2, 0);
        HAL_NVIC_SetPriority(FDCAN_CAL_IRQn, 2, 0);
        HAL_NVIC_EnableIRQ(FDCAN1_IT0_IRQn);
        HAL_NVIC_EnableIRQ(FDCAN1_IT1_IRQn);
        HAL_NVIC_EnableIRQ(FDCAN_CAL_IRQn);
    }
    if(hfdcan == &FDCAN2_Handler)
    {
        GPIO_Initure.Pin=GPIO_PIN_13|GPIO_PIN_12;       //PB13,12
        GPIO_Initure.Mode=GPIO_MODE_AF_PP;              //推挽复用
        GPIO_Initure.Pull=GPIO_PULLUP;                  //上拉
        GPIO_Initure.Speed=GPIO_SPEED_FREQ_MEDIUM;      //超高速
        GPIO_Initure.Alternate=GPIO_AF9_FDCAN2;         //复用为CAN2
        HAL_GPIO_Init(GPIOB,&GPIO_Initure);             //初始化
        
        
        HAL_NVIC_SetPriority(FDCAN2_IT0_IRQn, 3, 0);
        HAL_NVIC_SetPriority(FDCAN2_IT1_IRQn, 3, 0);
        HAL_NVIC_SetPriority(FDCAN_CAL_IRQn, 2, 0);
        HAL_NVIC_EnableIRQ(FDCAN2_IT0_IRQn);
        HAL_NVIC_EnableIRQ(FDCAN2_IT1_IRQn);
        HAL_NVIC_EnableIRQ(FDCAN_CAL_IRQn);
    }
   
}

注意使用CubeMX分配的时候 PA11 PA12引脚会可能分开注意区分

中断服务函数

//FDCAN1中断服务函数
void FDCAN1_IT0_IRQHandler(void)
{
    HAL_FDCAN_IRQHandler(&FDCAN1_Handler);
}

void FDCAN2_IT0_IRQHandler(void)
{
	HAL_FDCAN_IRQHandler(&FDCAN2_Handler);
}

// void FDCAN1_IT1_IRQHandler(void)
// {
// 	HAL_FDCAN_IRQHandler(&FDCAN1_Handler);
// }

// void FDCAN2_IT1_IRQHandler(void)
// {
// 	HAL_FDCAN_IRQHandler(&FDCAN2_Handler);
// }

根据接收的数据分别启动中断服务函数

中断回调函数 数据处理

void FDCAN_CAL_IRQHandler(void)  //中断服务函数
{
	HAL_FDCAN_IRQHandler(&FDCAN1_Handler);
	
	HAL_FDCAN_IRQHandler(&FDCAN2_Handler);
}
//FIFO0回调函数
void HAL_FDCAN_RxFifo0Callback(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs)
{ 
    u8 rxdata[8];
    if(hfdcan == &FDCAN1_Handler)
    {
        if((RxFifo0ITs&FDCAN_IT_RX_FIFO0_NEW_MESSAGE)!=RESET)   //FIFO1新数据中断
        {
            //提取FIFO0中接收到的数据
            HAL_FDCAN_GetRxMessage(hfdcan,FDCAN_RX_FIFO0,&FDCAN1_RxHeader,rxdata);
            get_can_data(&FDCAN1_RxHeader,rxdata);  //解析CAN报文
            HAL_FDCAN_ActivateNotification(hfdcan,FDCAN_IT_RX_FIFO0_NEW_MESSAGE,0);
        }
    }
    if(hfdcan == &FDCAN2_Handler)
    {
        if((RxFifo0ITs&FDCAN_IT_RX_FIFO0_NEW_MESSAGE)!=RESET)   //FIFO1新数据中断
        {
            //提取FIFO0中接收到的数据
            HAL_FDCAN_GetRxMessage(hfdcan,FDCAN_RX_FIFO0,&FDCAN2_RxHeader,rxdata);
            get_can_data(&FDCAN2_RxHeader,rxdata);  //解析CAN报文
            HAL_FDCAN_ActivateNotification(hfdcan,FDCAN_IT_RX_FIFO0_NEW_MESSAGE,0);
        }
    }
   
}
//接收的数据解析
void get_can_data(FDCAN_RxHeaderTypeDef *pRxHeader,uint8_t *pRxData)//CAN报文解析
{
    if(pRxHeader == &FDCAN1_RxHeader)
    {
        switch (pRxHeader->Identifier)
        {

            case 0x18FEEE00: //冷却液温度
             break;
            default:
                break;
        }
    }
    if(pRxHeader == &FDCAN2_RxHeader)
    {
        switch (pRxHeader->Identifier)
        {
         case 0x18FEEE00: //冷却液温度
           
            break;
        default:
            break;
        }
    }
}

发送数据

//can发送一组数据	
// FDCAN_HandleTypeDef *hfdcan CAN通道
//ID_Number:数据帧的ID
//ID_type: 数据帧的类型  FDCAN_EXTENDED_ID 扩展帧  FDCAN_STANDARD_ID 标准帧
//ID_frame:数据帧的格式  FDCAN_DATA_FRAME  数据帧  FDCAN_REMOTE_FRAME 远程帧		     
//msg:数据指针.
//adddr 起始地址
//返回值:0,成功;
//		 其他,失败;
u8 FDCAN_Send_Msg(FDCAN_HandleTypeDef *hfdcan,u32 ID_Number,u32 ID_type,u32 ID_frame,u8* msg,u8 adddr)
{	
   u8 send_data[8];
   my_strcpy_addr_array(send_data,msg,adddr,8);
   if(hfdcan->Instance==FDCAN1)
   {
        FDCAN1_TxHeader.Identifier=ID_Number;                      //32位ID
        FDCAN1_TxHeader.IdType=ID_type;                            //数据帧种类
        FDCAN1_TxHeader.TxFrameType=ID_frame;                     //数据帧类型
        FDCAN1_TxHeader.DataLength=(u32)8<<16;                            //数据长度
        FDCAN1_TxHeader.ErrorStateIndicator=FDCAN_ESI_ACTIVE;            
        FDCAN1_TxHeader.BitRateSwitch=FDCAN_BRS_OFF;               //关闭速率切换
        FDCAN1_TxHeader.FDFormat=FDCAN_CLASSIC_CAN;                //传统的CAN模式
        FDCAN1_TxHeader.TxEventFifoControl=FDCAN_NO_TX_EVENTS;     //无发送事件
        FDCAN1_TxHeader.MessageMarker=0;                           
        
        if(HAL_FDCAN_AddMessageToTxFifoQ(&FDCAN1_Handler,&FDCAN1_TxHeader,send_data)!=HAL_OK) return 1;//发送
        return 0;	
   }
   else if (hfdcan->Instance==FDCAN2)
   {
        FDCAN2_TxHeader.Identifier=ID_Number;                      //32位ID
        FDCAN2_TxHeader.IdType=ID_type;                            //数据帧种类
        FDCAN2_TxHeader.TxFrameType=ID_frame;                     //数据帧类型
        FDCAN2_TxHeader.DataLength=(u32)8<<16;                            //数据长度
        FDCAN2_TxHeader.ErrorStateIndicator=FDCAN_ESI_ACTIVE;            
        FDCAN2_TxHeader.BitRateSwitch=FDCAN_BRS_OFF;               //关闭速率切换
        FDCAN2_TxHeader.FDFormat=FDCAN_CLASSIC_CAN;                //传统的CAN模式
        FDCAN2_TxHeader.TxEventFifoControl=FDCAN_NO_TX_EVENTS;     //无发送事件
        FDCAN2_TxHeader.MessageMarker=0;                           
        
        if(HAL_FDCAN_AddMessageToTxFifoQ(&FDCAN2_Handler,&FDCAN2_TxHeader,send_data)!=HAL_OK) return 1;//发送
        return 0;	
   }
   return 0;   
}

### STM32G473 FDCAN1 和 FDCAN2 的差异 对于STM32G473系列微控制器而言,FDCAN模块提供了两种独立的操作模式——经典CAN和CAN FD(Flexible Data-rate)。该芯片内部配置有两个FDCAN接口:FDCAN1和FDCAN2。尽管这两个接口都遵循相同的协议标准并且具有相似的功能特性,但在实际应用中存在一些细微差别。 #### 1. 硬件资源分配不同 - **FDCAN1**通常连接到更多的外部设备或传感器,在某些封装形式下可能拥有更丰富的I/O引脚支持[^1]。 - **FDCAN2**可能会被设计用于特定的应用场景,比如仅作为调试端口或是与其他较少数量的外设通信。 #### 2. 中断优先级设置区别 为了满足不同的实时性和可靠性需求, - **FDCAN1**往往会被赋予较高的中断优先级别以便快速响应重要事件; - 对于**FDCAN2**来说,则可以根据具体应用场景灵活调整其对应的NVIC (Nested Vectored Interrupt Controller) 配置来平衡性能与功耗之间的关系。 #### 3. 默认工作状态预设不一致 当初始化MCU时,默认情况下两个FDCAN实例的工作参数可能是不一样的: - 而 **FDCAN2** 则或许处于禁用状态直到应用程序显式启动它为止。 需要注意的是上述描述基于一般性的假设条件;具体的实现细节应当参照官方数据手册以及相关技术文档获取最准确的信息。 ```c // 初始化FDCAN1为例 void MX_FDCAN1_Init(void) { hfdcan1.Instance = FDCAN1; // ...其他必要的初始化代码... } // 同理可定义针对FDCAN2的初始化函数MX_FDCAN2_Init() ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值