单片机CAN总线数据自收发

1、简介

使用STM32F407IGHX单片机(C板)CAN1、CAN2短接,进行数据自收发。

2.CubeMax初始化配置

CAN通讯介绍:CAN总线与单片机

1.rcc配置

2.sys配置

3.时钟树配置

4.CAN配置

需要注意是第六点,根据C板手册所示,CAN1输出接口为PD0、PD1,如下图所示:

CAN2配置跟CAN1一致,不需要单独配置引脚,C板CAN2输出引脚与默认配置一致。

5.触发按键配置

6.文件导出

3 Keil端程序书写

3.1.初始化配置

1.过滤器配置

要想使用CAN总线首先需要对过滤器进行配置。

/* USER CODE BEGIN 4 */
//CAN初始化
void CAN_ConfigFilter()
{
//过滤器配置
  CAN_FilterTypeDef sFilterConfig;//建立过滤器结构体
  sFilterConfig.FilterActivation = CAN_FILTER_ENABLE;
  sFilterConfig.FilterBank = 0;
  sFilterConfig.FilterFIFOAssignment = CAN_FilterFIFO0;
  sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
  sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;
  sFilterConfig.FilterIdHigh = 0x0000;//32 位 ID          不使用过滤器
  sFilterConfig.FilterIdLow = 0x0000;
  sFilterConfig.FilterMaskIdHigh = 0x0000;//32 位 MASK
  sFilterConfig.FilterMaskIdLow = 0x0000;    
  sFilterConfig.SlaveStartFilterBank = 14;
   if(HAL_CAN_ConfigFilter(&hcan1, &sFilterConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sFilterConfig.FilterBank = 14;
    if(HAL_CAN_ConfigFilter(&hcan2, &sFilterConfig) != HAL_OK)
  {
    Error_Handler();
  }
}
/* USER CODE END 4 */

2.CAN启动配置

在过滤器配置后进行CAN启动配置,先启动CAN1在启动CAN2,代码如下所示:

    if(HAL_CAN_ConfigFilter(&hcan2, &sFilterConfig) != HAL_OK)
    {
    Error_Handler();
    }
    //启动CAN
    if(HAL_CAN_Start(&hcan1)!= HAL_OK)
    {
        Error_Handler();
    }
    if(HAL_CAN_Start(&hcan2)!= HAL_OK)
    {
        Error_Handler();
    }

3.打开中断

在CAN启动后,进行CAN中断配置,代码如下所示:

    //打开接收中断
    if(HAL_CAN_ActivateNotification(&hcan1,CAN_IT_RX_FIFO0_MSG_PENDING|CAN_IT_RX_FIFO1_MSG_PENDING)!= HAL_OK)
    {
        Error_Handler();
    }
    if(HAL_CAN_ActivateNotification(&hcan2,CAN_IT_RX_FIFO0_MSG_PENDING|CAN_IT_RX_FIFO1_MSG_PENDING)!= HAL_OK)
    {
        Error_Handler();
    }

整个初始化函数代码如下所示:

//CAN初始化
void CAN_ConfigFilter()
{
    //过滤器配置
    CAN_FilterTypeDef sFilterConfig;//建立过滤器结构体
    sFilterConfig.FilterActivation = CAN_FILTER_ENABLE;
    sFilterConfig.FilterBank = 0;
    sFilterConfig.FilterFIFOAssignment = CAN_FilterFIFO0;
    sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
    sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;
    sFilterConfig.FilterIdHigh = 0x0000;//32 位 ID          不使用过滤器
  sFilterConfig.FilterIdLow = 0x0000;
  sFilterConfig.FilterMaskIdHigh = 0x0000;//32 位 MASK
  sFilterConfig.FilterMaskIdLow = 0x0000;    
  sFilterConfig.SlaveStartFilterBank = 14;
    
   if(HAL_CAN_ConfigFilter(&hcan1, &sFilterConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sFilterConfig.FilterBank = 14;
    if(HAL_CAN_ConfigFilter(&hcan2, &sFilterConfig) != HAL_OK)
  {
    Error_Handler();
  }
    //启动CAN
    if(HAL_CAN_Start(&hcan1)!= HAL_OK)
    {
        Error_Handler();
    }
    if(HAL_CAN_Start(&hcan2)!= HAL_OK)
    {
        Error_Handler();
    }
    //打开接收中断
    if(HAL_CAN_ActivateNotification(&hcan1,CAN_IT_RX_FIFO0_MSG_PENDING|CAN_IT_RX_FIFO1_MSG_PENDING)!= HAL_OK)
    {
        Error_Handler();
    }
    if(HAL_CAN_ActivateNotification(&hcan2,CAN_IT_RX_FIFO0_MSG_PENDING|CAN_IT_RX_FIFO1_MSG_PENDING)!= HAL_OK)
    {
        Error_Handler();
    }
}
/* USER CODE END 4 */

4.函数声明与主函数调用

在main.h中对上诉函数进行声明,如下所示:

/* USER CODE BEGIN Includes */
void CAN_ConfigFilter();
/* USER CODE END Includes */

声明完后,在主函数进行初始化,如下所示:

/* USER CODE BEGIN 2 */
  CAN_ConfigFilter();
  /* USER CODE END 2 */

5.定义数组、发送接收结构体

/* USER CODE BEGIN PV */
uint8_t txData[8],rxData0[8],rxData1[8];
CAN_TxHeaderTypeDef txHeader;
CAN_RxHeaderTypeDef rxHeader0,rxHeader1;
bool Pa0Pressed = false;
uint16_t txID = 0x200;
uint32_t txMailbox;
/* USER CODE END PV */

6、按键触发

引用头文件

/* USER CODE BEGIN Includes */
#include "stdbool.h"
/* USER CODE END Includes */

7. CAN配置

while (1)
  {
        if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0) == 0 && !Pa0Pressed){
            Pa0Pressed = true;
            txHeader.StdId = txID;
        txHeader.IDE = CAN_ID_STD;
        txHeader.RTR = CAN_RTR_DATA;
        txHeader.DLC = 8;
            *((uint32_t*)(txData)) = HAL_GetTick();
            if(HAL_CAN_GetTxMailboxesFreeLevel(&hcan1) != 0){
                HAL_CAN_AddTxMessage(&hcan1,&txHeader,txData,&txMailbox);
            }
        }
        else if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0) == 1 && !Pa0Pressed){
            Pa0Pressed = false;
        }
        HAL_Delay(100);

8 中断回调函数

/* USER CODE BEGIN 4 */
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
    if(hcan->Instance==CAN2)
    {
        HAL_CAN_GetRxMessage(&hcan2,CAN_FILTER_FIFO0,&rxHeader0,rxData0);//获取数据
    }
}
void HAL_CAN_RxFifo10MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
    if(hcan->Instance==CAN2)
    {
        HAL_CAN_GetRxMessage(&hcan1,CAN_FILTER_FIFO1,&rxHeader1,rxData1);//获取数据
    }
 
}

猜你喜欢

转载自blog.csdn.net/weixin_44597885/article/details/129392494
今日推荐