【STM32 CAN通信实战指南】从原理到代码,手把手教你玩转CAN总线

[摘要]
CAN(Controller Area Network)是广泛应用于工业控制、汽车电子等领域的可靠通信协议。本文基于STM32F1系列微控制器,深入解析CAN总线原理,并提供完整的配置代码和实验流程,帮助开发者快速掌握CAN通信核心技术。


一、CAN总线基础原理

1.1 CAN协议核心特点

  • 多主结构:总线上所有节点地位平等,均可主动发送数据

  • 非破坏性仲裁:通过ID优先级解决总线冲突

  • 高可靠性:CRC校验、错误检测与自动重发机制

  • 双线差分信号:CAN_H和CAN_L组成抗干扰传输线

1.2 CAN帧格式(标准帧)

字段长度说明
SOF1 bit帧起始
ID(11位)11 bits报文标识符
RTR1 bit远程传输请求标志
IDE1 bit标识符扩展位(0=标准帧)
r01 bit保留位
DLC4 bits数据长度码(0-8字节)
Data Field0-8字节数据内容
CRC15 bits循环冗余校验码
ACK2 bits应答
EOF7 bits帧结束

1.3 STM32 CAN控制器(bxCAN)

  • 支持CAN 2.0A/B协议

  • 3个发送邮箱

  • 2个接收FIFO,每个FIFO 3级深度

  • 可配置位时间参数

  • 28个过滤器组(STM32F103)


二、硬件设计

2.1 典型电路连接

STM32 CAN_TX --> TJA1050 TXD
STM32 CAN_RX <-- TJA1050 RXD
TJA1050 CAN_H -- 120Ω -- CAN_H
TJA1050 CAN_L -- 120Ω -- CAN_L

2.2 关键参数计算

波特率计算公式
波特率 = APB1时钟 / (Prescaler * (BS1 + BS2 + 1))
例如:APB1=36MHz,目标波特率500kbps
设置Prescaler=6, BS1=5, BS2=3
实际波特率 = 36MHz / (6*(5+3+1)) = 500kbps


三、软件配置(基于STM32CubeMX+HAL库)

3.1 CubeMX配置步骤

  1. 选择CAN模式:NormalLoopback(自测试)

  2. 配置参数:

    • Prescaler: 分频系数

    • Time Quantum: 1/(APB1时钟/Prescaler)

    • BS1: 时间段1(5-20 Tq)

    • BS2: 时间段2(1-16 Tq)

  3. 启用CAN中断(可选)

3.2 过滤器配置

CAN_FilterTypeDef filter;

filter.FilterBank = 0;
filter.FilterMode = CAN_FILTERMODE_IDMASK;
filter.FilterScale = CAN_FILTERSCALE_32BIT;
filter.FilterIdHigh = 0x123 << 5;  // 标准ID左移5位
filter.FilterMaskIdHigh = 0x7FF <<5;
filter.FilterFIFOAssignment = CAN_RX_FIFO0;
filter.FilterActivation = ENABLE;
HAL_CAN_ConfigFilter(&hcan, &filter);

四、代码实现

4.1 CAN初始化

void MX_CAN_Init(void)
{
  hcan.Instance = CAN1;
  hcan.Init.Prescaler = 6;
  hcan.Init.Mode = CAN_MODE_NORMAL;
  hcan.Init.SyncJumpWidth = CAN_SJW_1TQ;
  hcan.Init.TimeSeg1 = CAN_BS1_5TQ;
  hcan.Init.TimeSeg2 = CAN_BS2_3TQ;
  hcan.Init.TimeTriggeredMode = DISABLE;
  hcan.Init.AutoBusOff = DISABLE;
  hcan.Init.AutoWakeUp = DISABLE;
  hcan.Init.AutoRetransmission = ENABLE;
  hcan.Init.ReceiveFifoLocked = DISABLE;
  hcan.Init.TransmitFifoPriority = DISABLE;
  
  HAL_CAN_Init(&hcan);
}

4.2 发送数据

void CAN_SendMessage(uint32_t id, uint8_t* data, uint8_t len)
{
  CAN_TxHeaderTypeDef txHeader;
  uint32_t txMailbox;
  
  txHeader.StdId = id;
  txHeader.RTR = CAN_RTR_DATA;
  txHeader.IDE = CAN_ID_STD;
  txHeader.DLC = len;
  txHeader.TransmitGlobalTime = DISABLE;
  
  if(HAL_CAN_AddTxMessage(&hcan, &txHeader, data, &txMailbox) != HAL_OK)
  {
    Error_Handler();
  }
}

4.3 接收数据(中断方式)

// 启动CAN接收
HAL_CAN_Start(&hcan);
HAL_CAN_ActivateNotification(&hcan, CAN_IT_RX_FIFO0_MSG_PENDING);

// 接收回调函数
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
  CAN_RxHeaderTypeDef rxHeader;
  uint8_t rxData[8];
  
  HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &rxHeader, rxData);
  
  printf("Received ID: 0x%03X, Data: ", rxHeader.StdId);
  for(int i=0; i<rxHeader.DLC; i++){
    printf("%02X ", rxData[i]);
  }
  printf("\n");
}

五、实验验证

5.1 硬件连接

  • 两个STM32开发板通过CAN收发器连接

  • 终端电阻配置:总线两端各接120Ω电阻

5.2 测试结果

发送端发送:ID=0x123, Data=AA 55 01 02
接收端显示:Received ID: 0x123, Data: AA 55 01 02

六、常见问题排查

  1. 无法进入中断

    • 检查NVIC中断使能

    • 确认过滤器配置正确

    • 验证HAL_CAN_Start()已调用

  2. 波特率不匹配

    • 使用示波器测量实际波特率

    • 重新计算时间参数

  3. 发送失败

    • 检查CAN控制器是否进入Bus-Off状态

    • 使用CAN分析仪监控总线活动


七、扩展应用

  • CANopen协议栈移植

  • 多节点组网通信

  • 汽车诊断协议(ISO-TP)实现

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值