STM32·

STM32篇——CAN 通信

ronger

ronger

7867 2

STM32 HAL 库 CAN 通信

1. 前期准备

安装好STM32CubeMX

安装好Clion

2. 创建项目

  1. 配置CAN外设

在上一章工程基础上添加CAN配置如下:

通过组合图中3处参数,设置CAN通信波特率为500K,如4所示。5处模式设置为Loopback,即自发自收模式,不需要外部CAN设备也可以测试功能,正常使用时设置为Normal。同时,开启CAN接收中断,点击6处的NVIC Settings,找到USB low priority or CAN RX0interrupts选中Enable。生成项目即可。

3. 编辑代码

  1. 启动CAN并开启中断

main.c中项目自动创建了CAN对象hcan

CAN_HandleTypeDef hcan;

并添加了CAN初始化的基本代码MX_CAN_Init(void),在该函数的最后手动添加启动CAN以及开启中断,代码如下:

/* USER CODE BEGIN CAN_Init 2 */
    //启动CAN
    if(HAL_CAN_Start(&hcan) != HAL_OK)
    {
        printf("CAN start Fail!\r\n");
    }
    //开启中断,FIFO 0接收消息中断
    HAL_CAN_ActivateNotification(&hcan,CAN_IT_RX_FIFO0_MSG_PENDING);
  /* USER CODE END CAN_Init 2 */
  1. 添加CAN过滤器设置

HAL库没有自动生成CAN过滤,需要进行手动设置,初始化代码如下:

void filter_init(void)
{
    HAL_StatusTypeDef HAL_Status;
    CAN_FilterTypeDef Filter0;
    Filter0.FilterBank = 1;//滤波器编号
    Filter0.FilterMode = CAN_FILTERMODE_IDMASK;
    Filter0.FilterScale = CAN_FILTERSCALE_32BIT;
    Filter0.FilterIdHigh = 0x00;
    Filter0.FilterIdLow = 0x00;
    Filter0.FilterMaskIdHigh = 0x00;
    Filter0.FilterMaskIdLow = 0x00;
    Filter0.FilterFIFOAssignment = CAN_FILTER_FIFO0;
    Filter0.FilterActivation = CAN_FILTER_ENABLE;

    HAL_Status = HAL_CAN_ConfigFilter(&hcan,&Filter0);
    if(HAL_Status != HAL_OK)
    {
        printf("CAN Filter set Fail!code:%d\r\n",HAL_Status);
        Error_Handler();
    }
}

main.cMX_CAN_Init(void)函数之后调用即可。 3. 配置CAN接收中断回调函数

当接收到CAN数据后,在回调函数中处理即可,在main.c重定义接收中断回调函数如下:

//重定义CAN接收中断回调函数
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
    HAL_StatusTypeDef HAL_Status;
    if(hcan->Instance == CAN1)
    {
        HAL_Status = HAL_CAN_GetRxMessage(hcan,CAN_RX_FIFO0,&RxHeaderCAN,RxDataCAN);
        if(HAL_Status == HAL_OK)
        {
            //处理接收数据
            CAN_Rx_Flag = 1;
        }
    }
}

如上代码所示,将接收数据存储在RxDataCAN[]数组中,置位接收完成标志位CAN_Rx_Flag。其中,RxHeaderCANRxDataCANCAN_Rx_Flag为自定义的全局变量。至此,完成了全部CAN驱动代码编写。

4. CAN 发送、接收示例

前面我们将CAN设置为Loopback模式,即可以接收到自己发送的数据。示例功能为:通过CAN发送数据,并接收它,串口打印,对比收发数据是否一致。

main.c中添加测试代码:

添加全局变量:

//CAN全局变量
CAN_TxHeaderTypeDef TxHeaderCAN;
CAN_RxHeaderTypeDef RxHeaderCAN;
uint8_t TxDataCAN[8],RxDataCAN[8];
uint8_t CAN_Rx_Flag=0;//CAN接收标志

添加发送数据函数:

void CAN_Test(void)
{
    //发送数据CAN
    TxHeaderCAN.ExtId = 0x1800F001;
    TxHeaderCAN.DLC = 8;
    TxHeaderCAN.IDE = CAN_ID_STD;
    TxHeaderCAN.RTR = CAN_RTR_DATA;
    TxHeaderCAN.StdId = 0x01;
    TxHeaderCAN.TransmitGlobalTime = ENABLE;

    uint32_t TxMailBox;
    HAL_StatusTypeDef HAL_Status;
    printf("\r\n\r\n------------------CAN通信测试------------------\r\n\r\n");
    for (int i = 0; i < 8; ++i) TxDataCAN[i] = i;
    printf("CAN发送数据:\r\n");
    for (int i = 0; i < 8; ++i) printf(" 0x%02x",TxDataCAN[i]);
    printf("\r\n");
    HAL_CAN_AddTxMessage(&hcan,&TxHeaderCAN,TxDataCAN,&TxMailBox);
}

main.c中调用上述CAN_Test()完成数据发送,在main.cwhile(1)循环中检测接收标志CAN_Rx_Flag,并打印接收数据,代码如下:

while (1)
  {
      //处理CAN接收数据
      if(CAN_Rx_Flag)
      {
          CAN_Rx_Flag = 0;//清空CAN接收标志
          printf("CAN接收数据:\r\n");
          for(int i = 0;i<8;i++) printf(" 0x%02x",RxDataCAN[i]);
          printf("\r\n");
      }
 }

5. 编译下载

将程序编译下载至开发板,并将开发板连接至PC,打开串口调试助手RYCOM,并设置为:115200+8+N+1,接收结果如下。

6. 小结

本章学习了CAN数据发送、接收功能的具体实现。

所属系列

从当前文章继续阅读它所在合集中的前后内容。

关于我和 Hugh 学嵌入式开发这件事 —— STM32 篇 第 10 / 17 篇
查看合集

> 本作品集内教程基于 [Hugh](https://rymcu.com/user/hugh) 的创作基础上进行修订发布 关于我和 Hugh 学嵌入式开发这件事

相关文章

优先推荐同专题、同标签和同作者内容,补足热门文章。

评论 2

登录 后参与评论

评论 2

2950448386
29504483867月21日 20:38

写的不错~

2950448386
2950448386 回复 @29504483867月21日 20:38

加油!!!!