STM32 CAN 通信

STM32 CAN 通信


文章目录

  • STM32 CAN 通信
  • 前言
  • 一、硬件连接
  • 二、软件配置
  • 三、CAN 通信流程
  • 四、错误处理与调试
  • 总结


前言

控制器局域网(Controller Area Network, CAN)是一种应用广泛的串行通信协议,特别适用于工业控制和汽车电子领域。STM32 微控制器内置了 CAN 控制器,支持 CAN 协议 2.0A 和 2.0B,能够实现高效可靠的分布式通信。
本文档旨在 STM32 平台上实现 CAN 通信功能,内容涵盖硬件连接、软件配置、通信流程。


一、硬件连接

1.1 CAN 物理层
CAN 总线采用差分信号传输,两根线分别为 CAN_H 和 CAN_L。在标准 CAN 网络中,需要在总线两端各接一个 120Ω 的终端电阻。典型的 CAN 收发器如 SN65HVD230 或 TJA1050 可实现 TTL 电平与 CAN 差分信号之间的转换。

1.2 STM32 与 CAN 收发器连接
以 STM32F4 系列为例,CAN1 的默认引脚为:
TX: PA11
RX: PA12
连接示意图:
STM32 CAN收发器
PA11 (TX) ────> TXD
PA12 (RX) <──── RXD
VCC ────> VCC
GND ────> GND


二、软件配置

2.1 开发环境
开发工具:STM32CubeIDE 或 Keil MDK
固件库:STM32Cube HAL 库
2.2 CAN 初始化配置
CAN 通信的初始化步骤包括:
使能 CAN 控制器和相关 GPIO 时钟
配置 CAN 引脚
配置 CAN 控制器参数(波特率、工作模式等)
激活 CAN 控制器

#include "stm32f4xx_hal.h"

CAN_HandleTypeDef hcan1;

void CAN1_Init(void)
{
  /* 使能CAN1和GPIOA时钟 */
  __HAL_RCC_CAN1_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();
  
  /* 配置CAN1引脚 */
  GPIO_InitTypeDef GPIO_InitStruct = {0};
  GPIO_InitStruct.Pin = GPIO_PIN_11 | GPIO_PIN_12;
  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
  GPIO_InitStruct.Alternate = GPIO_AF9_CAN1;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
  
  /* 配置CAN1 */
  hcan1.Instance = CAN1;
  hcan1.Init.Prescaler = 5;            /* 分频系数 */
  hcan1.Init.Mode = CAN_MODE_NORMAL;   /* 正常模式 */
  hcan1.Init.SyncJumpWidth = CAN_SJW_1TQ;
  hcan1.Init.TimeSeg1 = CAN_BS1_8TQ;
  hcan1.Init.TimeSeg2 = CAN_BS2_1TQ;
  hcan1.Init.TimeTriggeredMode = DISABLE;
  hcan1.Init.AutoBusOff = ENABLE;
  hcan1.Init.AutoWakeUp = DISABLE;
  hcan1.Init.AutoRetransmission = ENABLE;
  hcan1.Init.ReceiveFifoLocked = DISABLE;
  hcan1.Init.TransmitFifoPriority = DISABLE;
  
  if (HAL_CAN_Init(&hcan1) != HAL_OK)
  {
    Error_Handler();
  }
  
  /* 配置过滤器 */
  CAN_FilterTypeDef sFilterConfig = {0};
  sFilterConfig.FilterBank = 0;
  sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
  sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;
  sFilterConfig.FilterIdHigh = 0x0000;
  sFilterConfig.FilterIdLow = 0x0000;
  sFilterConfig.FilterMaskIdHigh = 0x0000;
  sFilterConfig.FilterMaskIdLow = 0x0000;
  sFilterConfig.FilterFIFOAssignment = CAN_RX_FIFO0;
  sFilterConfig.FilterActivation = ENABLE;
  sFilterConfig.SlaveStartFilterBank = 14;
  
  if (HAL_CAN_ConfigFilter(&hcan1, &sFilterConfig) != HAL_OK)
  {
    Error_Handler();
  }
  
  /* 启动CAN1 */
  if (HAL_CAN_Start(&hcan1) != HAL_OK)
  {
    Error_Handler();
  }
  
  /* 使能接收中断 */
  if (HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING) != HAL_OK)
  {
    Error_Handler();
  }
}

三、CAN 通信流程

3.1 波特率计算
波特率 = 时钟频率 / ((Prescaler) * (1 + TimeSeg1 + TimeSeg2))
3.2 发送数据
CAN 数据发送步骤:
创建 CAN_TXHeaderTypeDef 结构体并配置 ID、数据长度等
准备数据缓冲区
调用 HAL_CAN_AddTxMessage () 发送数据

void CAN1_SendMessage(uint32_t id, uint8_t *data, uint8_t length)
{
  CAN_TxHeaderTypeDef TxHeader;
  uint32_t TxMailbox;
  
  TxHeader.StdId = id;
  TxHeader.ExtId = 0;
  TxHeader.RTR = CAN_RTR_DATA;
  TxHeader.IDE = CAN_ID_STD;
  TxHeader.DLC = length;
  TxHeader.TransmitGlobalTime = DISABLE;
  
  if (HAL_CAN_AddTxMessage(&hcan1, &TxHeader, data, &TxMailbox) != HAL_OK)
  {
    Error_Handler();
  }
}

3.3 接收数据
CAN 数据接收可通过中断或轮询方式实现。使用中断方式时,需实现回调函数:

void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
  CAN_RxHeaderTypeDef RxHeader;
  uint8_t RxData[8];
  
  if (HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &RxHeader, RxData) != HAL_OK)
  {
    Error_Handler();
  }
  
  /* 处理接收到的数据 */
  printf("Received message: ID=0x%03X, DLC=%d\n", RxHeader.StdId, RxHeader.DLC);
  for (int i = 0; i < RxHeader.DLC; i++)
  {
    printf("Data[%d]=0x%02X ", i, RxData[i]);
  }
  printf("\n");
}

四、错误处理与调试

4.1 常见错误类型
CAN 总线可能出现的错误包括:
位错误(发送与接收不一致)
填充错误(违反位填充规则)
CRC 错误(循环冗余校验失败)
格式错误(帧格式不合法)
ACK 错误(未收到确认位)

4.2 调试建议
使用示波器检查 CAN_H 和 CAN_L 的波形
通过 LED 指示灯或串口输出监控 CAN 控制器状态
利用 STM32CubeMonitor 工具进行实时监控
检查终端电阻是否正确连接
确认波特率设置一致


总结

可以在 STM32 平台上实现基本的 CAN 通信功能。关键是正确配置波特率、过滤器和中断,以及合理处理发送和接收流程。在实际应用中,还需根据具体需求优化通信协议和错误处理机制。

你可能感兴趣的:(STM32 CAN 通信)