STM32——CAN总线

发布于:2025-06-06 ⋅ 阅读:(16) ⋅ 点赞:(0)

STM32——CAN总线


1. CAN总线基础概念

1.1 CAN总线简介

控制器局域网(Controller Area Network, CAN)是由Bosch公司开发的串行通信协议,专为汽车电子和工业控制设计,具有以下核心特性:

  • 多主控制架构:所有节点均可主动发送数据
  • 差分信号传输:CAN_H与CAN_L双绞线抗干扰
  • 非破坏性仲裁:基于ID优先级的冲突解决机制
  • 高可靠性:CRC校验、错误帧检测等安全机制

图表

CAN_H/CAN_L
CAN_H/CAN_L
CAN_H/CAN_L
节点1
CAN总线
节点2
节点3
终端电阻 120Ω

1.2 CAN物理层结构

组件 功能说明 典型参数
CAN控制器 协议处理、帧过滤 集成在STM32内部
CAN收发器 电平转换(TTL↔差分) TJA1050, SN65HVD
双绞线 信号传输介质 特性阻抗120Ω
终端电阻 消除信号反射 120Ω两端各1个

物理连接示意图

STM32          CAN收发器         CAN总线
|------|        |------|        |--------|
|      | TX ----| TXD  |        | CAN_H  |
| CAN  |        |      |--------|        |
| 控制 | RX ----| RXD  |        | CAN_L  |
||        |------|        |--------|
|------|VCC(5V)

2. STM32 CAN控制器架构

2.1 功能框图

CAN核心
发送邮箱
接收FIFO
过滤器组
控制逻辑
CAN TX
CAN RX
标识符匹配
波特率控制

2.2 关键功能单元

  1. 发送邮箱:3个独立邮箱(F1/F4系列)
    • 优先级管理机制
    • 自动重传功能
  2. 接收FIFO:2个FIFO(FIFO0/FIFO1)
    • 每个FIFO深度3个报文
    • 可配置溢出处理
  3. 过滤器组:最多28个(F4系列)
    • 工作模式:掩码模式/列表模式
    • 尺度选择:16位/32位

3. CAN通信协议详解

3.1 数据帧结构

┌───┬───────┬──────┬───┬───────┬──────┬──────┬───┬───┐
│SOF│Arbitr.│Control│IDE│Data  │ CRC  │ ACK  │EOF│IFS│
│111/29610-641627  |3  |
└───┴───────┴──────┴───┴───────┴──────┴──────┴───┴───┘
  • SOF:帧起始(显性电平)
  • Arbitration:ID+ RTR位(11位标准/29位扩展)
  • Control:DLC(数据长度0-8字节)
  • CRC:15位校验 + 1位界定符
  • ACK:应答槽 + 应答界定符

3.2 波特率配置

计算公式

波特率 = APB1时钟 / (Prescaler * (BS1 + BS2 + 1))

位时间组成

┌───┬──────────────┬──────────────┐
│SYNC│   BS1(Prop)BS2(Ph2)  │
├───┼─────┬────┬───┼─────┬────┬───┤
│ 1 │ TQ1│... │TQn│ TQ1│... │TQm│
└───┴─────┴────┴───┴─────┴────┴───┘
  • SYNC_SEG:固定1个时间量子(TQ)
  • BS1:传播时间段(1-16 TQ)
  • BS2:相位缓冲段2(1-8 TQ)

4. STM32CubeMX配置步骤

4.1 基础配置流程

  1. 在Pinout视图启用CAN
  2. 配置参数:
    • Mode:Normal/Loopback
    • Bit Timings:设置Prescaler/BS1/BS2
  3. 过滤器配置:
    • Filter Activate:Enable
    • Scale:32-bit/16-bit
    • Mode:Mask/List
  4. NVIC设置:启用接收中断

4.2 推荐配置参数(500kbps)

参数 说明
Prescaler 6 分频系数
Time Quanta 12 总时间量子数
BS1 8 TQ 传播时间段
BS2 3 TQ 相位缓冲段2
SJW 1 TQ 同步跳转宽度
Sample Point 75% (1+BS1)/(1+BS1+BS2)

5. HAL库编程实战

5.1 CAN初始化代码

CAN_HandleTypeDef hcan;
CAN_FilterTypeDef filter;

void 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_8TQ;
  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;
  
  if (HAL_CAN_Init(&hcan) != HAL_OK) {
    Error_Handler();
  }

  // 配置过滤器(接收所有消息)
  filter.FilterBank = 0;
  filter.FilterMode = CAN_FILTERMODE_IDMASK;
  filter.FilterScale = CAN_FILTERSCALE_32BIT;
  filter.FilterIdHigh = 0x0000;
  filter.FilterIdLow = 0x0000;
  filter.FilterMaskIdHigh = 0x0000;
  filter.FilterMaskIdLow = 0x0000;
  filter.FilterFIFOAssignment = CAN_FILTER_FIFO0;
  filter.FilterActivation = ENABLE;
  
  HAL_CAN_ConfigFilter(&hcan, &filter);
  HAL_CAN_Start(&hcan);
  HAL_CAN_ActivateNotification(&hcan, CAN_IT_RX_FIFO0_MSG_PENDING);
}

5.2 数据发送函数

uint8_t CAN_Send(uint32_t id, uint8_t* data, uint8_t len)
{
  CAN_TxHeaderTypeDef txHeader;
  uint32_t txMailbox;
  
  txHeader.StdId = id;          // 标准ID
  txHeader.ExtId = 0;            // 扩展ID(标准帧设为0)
  txHeader.IDE = CAN_ID_STD;     // 使用标准帧
  txHeader.RTR = CAN_RTR_DATA;   // 数据帧
  txHeader.DLC = len;            // 数据长度
  txHeader.TransmitGlobalTime = DISABLE;
  
  if(HAL_CAN_AddTxMessage(&hcan, &txHeader, data, &txMailbox) != HAL_OK) {
    return 0; // 发送失败
  }
  
  // 等待发送完成
  while(HAL_CAN_GetTxMailboxesFreeLevel(&hcan) != 3);
  return 1;
}

5.3 中断接收处理

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) 
  {
    uint32_t id = rxHeader.StdId;  // 获取标准ID
    uint8_t len = rxHeader.DLC;    // 数据长度
    
    // 处理接收数据 (示例: 串口转发)
    printf("ID:0x%X Data:", id);
    for(int i=0; i<len; i++) {
      printf("%02X ", rxData[i]);
    }
    printf("\n");
  }
}

6. 调试技巧与工具

6.1 常见调试工具

工具类型 推荐型号 特点
CAN分析仪 PCAN-USB, ZLG USBCAN 专业级报文分析
逻辑分析仪 Saleae, DSLogic 物理层信号观测
终端电阻 120Ω精密电阻 消除信号反射

6.2 典型问题排查

  1. 无法通信
    • 检查终端电阻(总线两端各120Ω)
    • 验证波特率配置一致性
    • 测量CAN_H-CAN_L差分电压(2V左右)
  2. 数据丢失
    • 增加接收FIFO深度
    • 优化过滤器设置减少无关报文
    • 提升中断优先级
  3. 总线错误
    • 使用HAL_CAN_GetError()获取错误码
    • 检查物理线路是否受干扰
    • 降低波特率测试稳定性

7. 应用案例

7.1 汽车电子网络

┌──────────────┐       ┌──────────────┐
│ 发动机控制器 │◄─────►│ 车身控制模块 │
├──────────────┤       ├──────────────┤
│    CAN总线   │◄──┐ ┌─►│  仪表盘显示  │
└──────▲───────┘  │ │  └──────────────┘
       │          ▼ ▼
┌──────┴───────┐  ┌──────────────┐
│  制动系统    │  │  网关控制器  │
└──────────────┘  └──────────────┘

7.2 工业控制系统

CAN
CAN
CAN
STM32-PLC
电机驱动器
IO模块
传感器集线器
伺服电机
限位开关
温度传感器

最佳实践提示:在工业环境中,建议使用带隔离的CAN收发器(如ISO1050)并增加TVS管保护电路,可显著提升系统抗干扰能力。

附录:CAN资源速查表

寄存器 功能描述 关键位域
CAN_MCR 主控制寄存器 INRQ, SLEEP, TTCM
CAN_MSR 主状态寄存器 INAK, SLAK, RX, TX
CAN_TSR 发送状态寄存器 TME0/1/2, TXOK0/1/2
CAN_RF0R/RF1R 接收FIFO寄存器 FMP0/1, FULL0/1
CAN_FMR 过滤器主寄存器 FINIT, CAN2SB
CAN_FA1R 过滤器激活寄存器 FACT0-27