STM32G0B1RCT6系列FDCAN的使用。

1.代码配置

1.1外设配置

1.1.1 时钟配置
 void Drv_RccConfig(void)
{
	
    /** 
			系统时钟使能 
			APB1:低速总线
			APB2:高速总线
	*/
	  
    LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_SYSCFG);
    LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_PWR);

    /** GPIO 时钟使能 */
    LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOA);
    LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOB);
    LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOC);
    LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOD);
    
     /** 外设时钟使能 */
    LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_ADC);
    LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_DMA1);
    
	LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_TIM15);
    LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_TIM16);
   
    LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_TIM17);
		
    LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_FDCAN);
}

初始化RCC振荡器,选择内部高速总线

使能GPIOA,B,C,D.

使能对应的中断TIM16,TIM17时钟

使能FDCAN的时钟

1.1.2 引脚配置
void Drv_GpioConfig(void)
{
	  RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
      LL_GPIO_InitTypeDef GPIO_InitStruct = {0};

      GPIO_InitStruct.Pin =  LL_GPIO_PIN_4| LL_GPIO_PIN_5;
	  GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
	  GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW;
      GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
      GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
      GPIO_InitStruct.Alternate = GPIO_AF3_FDCAN1;
      LL_GPIO_Init(GPIOC, &GPIO_InitStruct);
}

注意对应的引脚,本例为PC4,PC5。

功能设置成复用推挽输出。复用功能设置成 GPIO_AF3_FDCAN1。

1.1.3 FDCAN初始化 
void Drv_IntCan(void)
{
     FDCAN_HandleTypeDef    hcan1;
     HAL_NVIC_SetPriority(TIM17_FDCAN_IT1_IRQn, 0, 0);
     HAL_NVIC_EnableIRQ(TIM17_FDCAN_IT1_IRQn);

     //FDCAN_FilterTypeDef sFilterConfig;
	
	hcan1.Instance = FDCAN1;                          ///<寄存器基地址
    hcan1.Init.ClockDivider = FDCAN_CLOCK_DIV1;       ///<时钟分配器 不分频
    hcan1.Init.FrameFormat = FDCAN_FRAME_CLASSIC;     ///<经典模式
    hcan1.Init.Mode = FDCAN_MODE_NORMAL;              ///<正常模式
    hcan1.Init.AutoRetransmission = DISABLE;          ///<不启动自动重传模式
    hcan1.Init.TransmitPause = DISABLE;               ///<不启动传输暂停模式
    hcan1.Init.ProtocolException = DISABLE;           ///<不启动异常传输功能

    /*   我使用的时钟频率
	     波特率:125K
	     BAUD=Freq/Clock Divider/Prescaler/(Seg1+Seg2+1)
	     125K=16M/1/4/(27+4+1) = 125K
	  */

   hcan1.Init.NominalPrescaler         = 4;///<仲裁段时钟分频,传统CAN模式时只设置这一段即可
    hcan1.Init.NominalSyncJumpWidth     = 1;          ///<仲裁段同步跳转段的宽度
    hcan1.Init.NominalTimeSeg1      = 27;						  ///<仲裁段时间段1 
    hcan1.Init.NominalTimeSeg2      = 4 ;   ///<仲裁段时间段2 
    hcan1.Init.DataPrescaler            = 4;          ///<数据段时钟分频,若工作于传统模式,不需要设置数据段参数
    hcan1.Init.DataSyncJumpWidth        = 1;
    hcan1.Init.DataTimeSeg1             = 27;
    hcan1.Init.DataTimeSeg2             = 4;
    hcan1.Init.StdFiltersNbr            = 1;          ///<标准帧滤波器数量
    hcan1.Init.ExtFiltersNbr            = 5;          ///<扩展帧滤波器数量
    hcan1.Init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION;// 发送模式:先入先出 
    if (HAL_FDCAN_Init(&hcan1) != HAL_OK)
    {
//  Error_Handler();
    }
}

上面是发送和接收需要最基础的配置。前面两行是使能中断。后面是配置一些模式,波特率,然后进行初始化。我的注释写的很详细。下面是接收需要配置的一些东西,比如滤波器等。 

///<FDCAN滤波器结构定义
    sFilterConfig.IdType = FDCAN_STANDARD_ID;
    sFilterConfig.FilterIndex = 0;
    sFilterConfig.FilterType = FDCAN_FILTER_MASK;
    sFilterConfig.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
    sFilterConfig.FilterID1 = 0;
    sFilterConfig.FilterID2 = 0;
    if (HAL_FDCAN_ConfigFilter(&hcan1, &sFilterConfig) != HAL_OK)
    {
        //Error_Handler();
    }

    sFilterConfig.IdType = FDCAN_EXTENDED_ID;
    sFilterConfig.FilterIndex = 0;
    sFilterConfig.FilterType = FDCAN_FILTER_MASK;
    sFilterConfig.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
    sFilterConfig.FilterID1 =  0;
    sFilterConfig.FilterID2 =  0;
    ///进行一些初始化操作
    if (HAL_FDCAN_ConfigFilter(&hcan1, &sFilterConfig) != HAL_OK)
    {
        //Error_Handler();
    }

    if (HAL_FDCAN_ConfigGlobalFilter(&hcan1, FDCAN_REJECT, FDCAN_REJECT, FDCAN_FILTER_REMOTE, FDCAN_FILTER_REMOTE) != HAL_OK)
    {
        //Error_Handler();
    }

    HAL_FDCAN_ConfigInterruptLines(&hcan1, FDCAN_IT_RX_FIFO0_NEW_MESSAGE, FDCAN_INTERRUPT_LINE1);
    /* Activate Rx FIFO 0 new message notification */
    if (HAL_FDCAN_ActivateNotification(&hcan1, FDCAN_IT_RX_FIFO0_NEW_MESSAGE, 0) != HAL_OK)
    {
        //Error_Handler();
    }
    
    if (HAL_FDCAN_ConfigTxDelayCompensation(&hcan1, 5, 0) != HAL_OK)
    {
        //Error_Handler();
    }
    if (HAL_FDCAN_EnableTxDelayCompensation(&hcan1) != HAL_OK)
    {
        //Error_Handler();
    }

现在基本配置基本已经配置好了。 

1.2 发送和接收

1.2.1 发送配置。
static void test()
{
	FDCAN_TxHeaderTypeDef TxHeader;
	static u8 s_u8TxData[8];
	static u8 s_u8Flag = 0;
    TxHeader.Identifier           =  0x111;
    //TxHeader.Identifier = 0x111;
    TxHeader.IdType                 = FDCAN_EXTENDED_ID;
    TxHeader.TxFrameType            = FDCAN_DATA_FRAME;
    TxHeader.DataLength             = FDCAN_DLC_BYTES_8;
    TxHeader.ErrorStateIndicator    = FDCAN_ESI_ACTIVE;
    TxHeader.BitRateSwitch          = FDCAN_BRS_OFF;
     TxHeader.FDFormat               = FDCAN_CLASSIC_CAN;
    TxHeader.TxEventFifoControl     = FDCAN_NO_TX_EVENTS;
    TxHeader.MessageMarker          = 0;
		
	s_u8TxData[0] = 0x01;
    s_u8TxData[1] = 0xF0;
    s_u8TxData[2] = 0x16;
    s_u8TxData[3] = 0x01;
    s_u8TxData[4] = 0xFF;
    s_u8TxData[5] = 0xFF;
    s_u8TxData[6] = 0xFF;
    s_u8TxData[7] = 0xFF;

    if (HAL_FDCAN_AddMessageToTxFifoQ(&hcan1, &TxHeader, s_u8TxData) != HAL_OK)
	{
	    s_u8Flag = 1;
	}
	else
	{
	    s_u8Flag = 0;
	}
}

发送重点

hcan1->State 正常发送情况应该是busy

hcan1->ErrorCode 错误码是0

hcan1->LatestTxFifoQRequest 这个应该是在0,2,4来回跳。

 

1.2.2 接收配置
void TIM17_FDCAN_IT1_IRQHandler(void)
{
    /* USER CODE BEGIN TIM17_FDCAN_IT1_IRQn 0 */
	  //FDCAN_HandleTypeDef  hcan1;
    HAL_FDCAN_IRQHandler(&hcan1);
    
}

void HAL_FDCAN_RxFifo0Callback(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs)
{
      static u8 s_u8Rxdata[8];
	  FDCAN_RxHeaderTypeDef  Rx0Msg;
	
		if ((RxFifo0ITs & FDCAN_IT_RX_FIFO0_NEW_MESSAGE) != 0)
    {
        /* Retrieve Rx messages from RX FIFO0 */
        if (HAL_FDCAN_GetRxMessage(&hcan1, FDCAN_RX_FIFO0, &Rx0Msg, s_u8RxData) != HAL_OK)
		{   
            //接收错误
           ;
         }
         else
        {
            ;
        } 
    }
} 

只要可以进中断就基本没问题。 重点看自己配置的是FIFO0还是FIFO1

 
 

 

  • 9
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值