0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

手把手教你玩转CAN总线 从原理到STM32实战

李旭昂 来源:李旭昂 作者:李旭昂 2025-04-10 11:10 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

一、物理层深度剖析

1.1 差分信号的本质

CAN总线采用****双线差分传输 ,核心原理图解:

markdown

CAN_H ──────       /───────── 
                 /  
             ___/  
CAN_L ──────/     ─────────
  • 显性状态(Dominant) :CAN_H电压 ≥ 2.5V,CAN_L ≤ 1.5V → 差值≥1V
  • 隐性状态(Recessive) :CAN_H/CAN_L均为2.5V → 差值≈0V

物理层参数对照表

参数标准值测试方法
终端电阻120Ω ±1%万用表直接测量
最大传输距离10km @ ≤5Kbps示波器+时延测试仪
波特率容差±1%专用CAN分析仪
共模电压抑制±2V隔离示波器测量

1.2 波特率计算公式

markdown

位时间 = 同步段 + 传播时间段 + 相位缓冲段1 + 相位缓冲段2 
总位数 = 同步段(SJW) + 时间段1(TS1) + 时间段2(TS2)

STM32配置示例 (500Kbps):

hcan1.Init.SyncJumpWidth = CAN_SJW_1TQ;    // 同步跳转宽度=1TQ
hcan1.Init.TimeSeg1 = CAN_BS1_9TQ;         // 时间段1=9TQ
hcan1.Init.TimeSeg2 = CAN_BS2_4TQ;         // 时间段2=4TQ
// 总位时间=1+9+4=14TQ → 时钟频率=8MHz → TQ=0.125μs → 波特率=1/(14 * 0.125μs)=500Kbps

1.3 终端电阻调试技巧

  • 错误现象 :总线波形畸变、通信不稳定
  • 检测方法:
    1. 断电测量总线两端电阻(应为120Ω±5%)
    2. 上电后用示波器观察终端反射波形
  • 解决方案:
# 终端电阻计算公式(单位Ω)
def calc_termination_resistance(length):
    # 每米电缆约60Ω特性阻抗
    return 120 - (length * 60) / 1000  
# 示例:总线长度40m → 120 - 24 = 96Ω → 需补48Ω电阻

二、数据链路层全解析(帧结构+仲裁机制)

2.1 CAN帧类型对比表

帧类型标识符长度用途DLC最大值
标准帧11位普通数据传输8字节
扩展帧29位复杂设备通信8字节
远程帧11/29位请求数据-
错误帧-错误通知-

2.2 经典仲裁过程演示

场景 :三个节点同时发送数据

markdown

节点A: ID=0x100 (0b000100000000)
节点B: ID=0x200 (0b001000000000)
节点C: ID=0x080 (0b000010000000)

仲裁过程

  1. 第一位:全显性 → 继续比较
  2. **第二位:A=0, B=0, C=1 → C失去仲裁权**
  3. 后续位比较后,A胜出总线使用权

STM32仲裁配置要点

// 使能自动重传功能(默认开启)
hcan1.Init.AutoRetransmission = ENABLE;
// 设置重试次数(最大16次)
hcan1.Init.RetryCount = 3;

2.3 错误检测机制详解

五级错误防护体系

  1. CRC校验 :15位循环冗余校验
  2. 位填充 :每5个相同电平插入相反电平
  3. ACK校验 :接收节点必须发送显性确认
  4. 帧格式校验 :7个保留位必须为隐性
  5. 总线监控 :持续检测总线逻辑电平

错误计数器动态调整算法

markdown

当检测到错误时:
TEC += 8(发送错误)或 REC += 1(接收错误)
当TEC > 127时:进入总线关闭状态

2.4 位时间同步技术

同步机制

  • 硬同步 :在帧起始位强制对齐
  • 重新同步 :通过调整时间段2补偿时钟偏差

STM32时间参数配置示例

// 配置同步跳转宽度为1个时间量子
hcan1.Init.SyncJumpWidth = CAN_SJW_1TQ;
​
// 时间段分配(假设系统时钟16MHz)
CAN_BtrTypeDef sCanBtr;
sCanBtr.SyncJumpWidth = CAN_SJW_1TQ;
sCanBtr.TimeSeg1 = CAN_BS1_9TQ;  // 传播延迟补偿
sCanBtr.TimeSeg2 = CAN_BS2_4TQ;  // 相位缓冲

三、数据链路层核心机制

3.1 CAN协议栈全景图

应用层(CANopen/J1939)
   
网络层(路由/错误处理)
   
数据链路层(帧结构/仲裁)
   
物理层(差分信号/终端电阻)

3.2 帧结构深度拆解

标准帧格式(11位ID)

| 仲裁场(11b) | 控制场(6b) | 数据场(0-8B) | CRC场(15b) | ACK场(1b) | 帧结束(7b) |
  • 仲裁场 :包含节点ID和帧类型标识
  • 控制场 :DLC(数据长度码) + IDE(扩展标识符)
  • CRC场 :15位循环冗余校验(生成多项式:x¹⁵+x¹⁴+...+1)

STM32 CRC配置示例

// CAN1 CRC初始化
hcan1.Instance- >CRCD = 0xFFFF;    // 初始值
hcan1.Instance- >CRCSA = 0x0000;   // 起始地址

3.3 仲裁机制详解

29位扩展帧仲裁过程

优先级位 → 源地址 → 参数组号(PGN)
  • 优先级计算 :ID31-ID26位决定(数值越小优先级越高)
  • 源地址冲突检测 :同一网络内节点地址必须唯一

仲裁时序仿真

def can_arbitration(id_list):
    sorted_ids = sorted(id_list, key=lambda x: bin(x).count('1'))
    return sorted_ids[0]
​
# 示例:三个节点同时发送
nodes = [0x18FEF100, 0x18FEF200, 0x18FEF300]
winner = can_arbitration(nodes)  # 输出0x18FEF100

四、CANopen协议深度实战

4.1 对象字典(Object Dictionary)

OD结构示例

索引        类型        描述
0x2000     ARRAY       电机控制参数
0x2000[0]  UINT16      目标转速(rpm)
0x2000[1]  FLOAT       加速度(m/s²)
0x2001     RECORD      故障代码
0x2001[0]  BITFIELD    故障标志位

STM32 SDO传输实现

// SDO客户端上传数据
void SDO_Upload(uint16_t index, uint8_t subindex) {
    CO_SDO_Req req;
    CO_SDO_ReqInit(&req);
    req.Cmd = CO_SDO_CMD_UPLOAD_REQ;
    req.Index = index;
    req.SubIndex = subindex;
    
    if (CO_SDO_Transmit(&req) == CO_SDO_OK) {
        Process_SDO_Response(req.Data);
    }
}

4.2 NMT网络管理

状态迁移图

INIT → PRE-OPERATIONAL → OPERATIONAL → STOPPED
   ↑        ↑                    ↓
   └──RESET←───────────────────┘

心跳报文配置

// 心跳生产者配置
CO_NMT_HeartbeatConfig(0x01, 0x00, 500);  // 节点ID=1,周期500ms

五、J1939协议核心要点

5.1 参数组号(PGN)编码规则

PGN = PF(8b) < < 8 | PS(8b)
PF: 参数组功能(0-255)
PS: 参数组子功能(0-255)

典型PGN解析

PGNPFPS描述
0xFEFC0xFE0xFC发动机转速请求
0xFEF00xFE0xF0冷却液温度
0xFECA0xFE0xCA车辆位置报告

5.2 多包数据传输

传输流程

请求 → 确认 → 数据包1 → 数据包2 → ... → 结束符

STM32多包发送实现

// 多包数据发送(最大12字节/包)
void CAN_Send_MultiPacket(uint8_t *data, uint16_t length) {
    uint8_t packets[6][8] = {0};
    uint8_t packet_count = (length + 7) / 8;
    
    for (int i=0; i< packet_count; i++) {
        packets[i][0] = 0x00;  // 流控制字段
        memcpy(&packets[i][1], &data[i*8], 8);
        CAN_TransmitPacket(packets[i]);
    }
}

六、STM32HAL库实战进阶

6.1 完整初始化流程

// 1. GPIO配置(CubeMX生成)
void MX_GPIO_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};
  __HAL_RCC_GPIOB_CLK_ENABLE();
  
  // CAN_RX/TX引脚配置
  GPIO_InitStruct.Pin = GPIO_PIN_8 | GPIO_PIN_9;
  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
  GPIO_InitStruct.Alternate = GPIO_AF9_CAN1;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}
​
// 2. CAN初始化(含过滤器配置)
void MX_CAN1_Init(void)
{
  CAN_HandleTypeDef hcan1;
  
  hcan1.Instance = CAN1;
  hcan1.Init.Prescaler = 5;         // 500Kbps
  hcan1.Init.SyncJumpWidth = CAN_SJW_1TQ;
  hcan1.Init.TimeSeg1 = CAN_BS1_9TQ;
  hcan1.Init.TimeSeg2 = CAN_BS2_4TQ;
  hcan1.Init.Mode = CAN_MODE_NORMAL;
  
  if (HAL_CAN_Init(&hcan1) != HAL_OK) {
    Error_Handler();
  }
  
  // 滤波器配置(接收ID=0x100-0x1FF)
  CAN_FilterTypeDef sFilterConfig = {0};
  sFilterConfig.FilterBank = 0;
  sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
  sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;
  sFilterConfig.FilterIdHigh = 0x100 < < 13;
  sFilterConfig.FilterIdLow = 0x1FF < < 13 | 0xFFFF;
  HAL_CAN_ConfigFilter(&hcan1, &sFilterConfig);
}

6.2 数据收发实战

// 数据发送(PDO模拟
void CAN_Send_PDO(uint8_t node_id, uint16_t position) {
  CAN_TxHeaderTypeDef TxHeader = {0};
  uint8_t TxData[8] = {0};
  
  TxHeader.StdId = 0x200 + node_id;  // PDO ID
  TxHeader.IDE = CAN_ID_STD;
  TxHeader.DLC = 2;
  
  TxData[0] = (position > > 8) & 0xFF;
  TxData[1] = position & 0xFF;
  
  HAL_CAN_AddTxMessage(&hcan1, &TxHeader, TxData, &TxMailbox);
}
​
// 接收回调(带错误检测)
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan) {
  CAN_RxHeaderTypeDef RxHeader;
  uint8_t RxData[8] = {0};
  
  if (HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &RxHeader, RxData) == HAL_OK) {
    if (RxHeader.DLC != 2) {
      // 数据长度异常处理
      return;
    }
    uint16_t value = (RxData[0] < < 8) | RxData[1];
    Process_Sensor_Data(value);
  }
}

七、工业级应用案例解析

7.1 电动汽车三电系统

  • BMS电池管理 :通过CAN总线监控单体电压/温度
  • 电机控制器 :接收扭矩指令并反馈转速
  • OBC车载充电机 :与BMS通信实现充电保护

通信拓扑

BMS  CAN  MCU  CAN  电机控制器
           ↑↓
         充电桩

7.2 智能仓储机器人

  • 多机协同 :50+台AGV通过CAN总线同步路径规划
  • 实时监控 :电量/故障状态实时上报
  • 抗干扰方案:
    • 双绞线屏蔽层接地
    • 隔离收发器(如ADuM1201)
    • 冗余帧重传机制

八、调试与优化技巧

  1. 示波器观察
    • 检查CAN_H/CAN_L差分波形(正常应为方波)
    • 波特率验证(500Kbps对应周期2μs)
  2. 错误分析
    • 错误帧计数:HAL_CAN_GetError(&hcan1)
    • 总线负载率:CAN总线分析仪检测
  3. 性能优化
    • 使用CAN FD(Flexible Data Rate)提升带宽
    • 优化过滤器配置减少CPU开销
    • 采用环形缓冲区处理高频率数据

九、扩展学习资源

  • 经典CAN vs CAN FD :带宽从1Mbps提升至5Mbps
  • AUTOSAR架构 :标准化汽车软件架构
  • TSN时间敏感网络 :工业4.0通信新标准
    更多嵌入式知识,关注“逸云客嵌入式”公众号!

审核编辑 黄宇

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • CAN总线
    +关注

    关注

    145

    文章

    2020

    浏览量

    134693
  • STM32
    +关注

    关注

    2305

    文章

    11121

    浏览量

    371183
收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    0到1,10+年资深LabVIEW专家,手把手教你攻克机器视觉+深度学习(5000分钟实战课)

    “告别检测系统能力缺陷!10+年LabVIEW视觉资深专家手把手教你:5000+分钟高清教程(含工具、算法原理、实战操作、项目优化全流程讲解)”——传统视觉算法→深度学习建模→工业级
    的头像 发表于 12-02 08:07 106次阅读
    <b class='flag-5'>从</b>0到1,10+年资深LabVIEW专家,<b class='flag-5'>手把手</b><b class='flag-5'>教你</b>攻克机器视觉+深度学习(5000分钟<b class='flag-5'>实战</b>课)

    迅为Hi3403开发板极速启航 | 手把手带你玩转核心例程,轻松上手AI视觉!

    迅为Hi3403开发板极速启航 | 手把手带你玩转核心例程,轻松上手AI视觉!
    的头像 发表于 11-19 13:56 1312次阅读
    迅为Hi3403开发板极速启航 | <b class='flag-5'>手把手</b>带你<b class='flag-5'>玩转</b>核心例程,轻松上手AI视觉!

    【迅为RK3568开发板NPU实战】别再闲置你的NPU!手把手教你玩转RKNN-Toolkit2 的使用

    【迅为RK3568开发板NPU实战】别再闲置你的NPU!手把手教你玩转RKNN-Toolkit2 的使用
    的头像 发表于 11-11 14:21 548次阅读
    【迅为RK3568开发板NPU<b class='flag-5'>实战</b>】别再闲置你的NPU!<b class='flag-5'>手把手</b><b class='flag-5'>教你</b><b class='flag-5'>玩转</b>RKNN-Toolkit2 的使用

    【RK3568 NPU实战】别再闲置你的NPU!手把手带你用迅为资料跑通Android AI检测Demo,附完整流程与效果

    【RK3568 NPU实战】别再闲置你的NPU!手把手带你用迅为资料跑通Android AI检测Demo,附完整流程与效果
    的头像 发表于 11-10 15:58 870次阅读
    【RK3568 NPU<b class='flag-5'>实战</b>】别再闲置你的NPU!<b class='flag-5'>手把手</b>带你用迅为资料跑通Android AI检测Demo,附完整流程与效果

    理到实操:BLE蓝牙配网(STA+SoftAP双模式)一文通关!

    BLE蓝牙配网如何兼顾便捷性与稳定性?STA+SoftAP双模式给出最优解。下面技术原理到实战案例,手把手教你搭建双模式配网系统,无需复杂
    的头像 发表于 09-20 15:20 1124次阅读
    <b class='flag-5'>从</b>原<b class='flag-5'>理到</b>实操:BLE蓝牙配网(STA+SoftAP双模式)一文通关!

    手把手教你如何调优Linux网络参数

    在高并发网络服务场景中,Linux内核的默认网络参数往往无法满足需求,导致性能瓶颈、连接超时甚至服务崩溃。本文基于真实案例分析,参数解读、问题诊断到优化实践,手把手教你如何调优Linux网络参数,支撑百万级并发连接。
    的头像 发表于 05-29 09:21 650次阅读

    正点原子Linux系列全新视频教程来啦!手把手教你MP257开发板,让您轻松入门!

    正点原子Linux系列全新视频教程来啦!手把手教你MP257开发板,让您轻松入门! 一、视频观看 正点原子手把手教你STM32MP257
    发表于 05-16 10:42

    手把手教你玩转CAN总线理到STM32实战

    一、物理层深度剖析 1.1 差分信号的本质 CAN总线采用****双线差分传输,核心原理图解: markdown CAN
    发表于 04-10 11:08

    《零基础开发AI Agent——手把手教你用扣子做智能体》

    《零基础开发AI Agent——手把手教你用扣子做智能体》是一本为普通人量身打造的AI开发指南。它不仅深入浅出地讲解了Agent的概念和发展,还通过详细的工具介绍和实战案例,帮助读者快速掌握
    发表于 03-18 12:03

    手把手教你做星闪无人机—KaihongOS星闪无人机开发实战》系列课程课件汇总

    —KaihongOS星闪无人机开发实战》系列课程,该课程与《手把手教你做PC—KaihongOS笔记本电脑开发实战》同步并行,两个系列课隔周交替播出。 《
    发表于 03-18 10:33

    手把手教你做PC-KaihongOS笔记本电脑开发实战》课件汇总

    ”携手“电子发烧友”联合推出了 《KaihongOS手把手系列直播课程》,该系列课程以实际产品为案例,详细讲解每个产品的开发全流程。 此次首发内容是《手把手教你做PC-KaihongOS笔记本电脑开发
    发表于 03-18 10:25

    【第四章 定时任务】手把手教你玩转新版正点原子云

    【第四章 定时任务】手把手教你玩转新版正点原子云 承接上篇,除了报警联动这个功能,原子云还有一个特色功能也是各开发者喜欢用的,定时任务功能。 【正点原子】云平台:原子云(点击登录原子云) 前言
    发表于 03-13 10:19

    开发者集结!《手把手教你做星闪无人机》第二课开讲啦!

    开发者集结!《手把手教你做星闪无人机》第二课开讲啦!
    的头像 发表于 02-17 19:40 656次阅读
    开发者集结!《<b class='flag-5'>手把手</b><b class='flag-5'>教你</b>做星闪无人机》第二课开讲啦!

    手把手教你做星闪无人机》即将开播,锁定15日晚七点!

    ”再次联合推出《手把手教你做星闪无人机—KaihongOS星闪无人机开发实战》系列课程,该课程与《手把手教你做PC—KaihongOS笔记本
    的头像 发表于 01-13 19:42 879次阅读
    《<b class='flag-5'>手把手</b><b class='flag-5'>教你</b>做星闪无人机》即将开播,锁定15日晚七点!

    手把手教你做PC》课程即将启动!深开鸿引领探索KaihongOS笔记本电脑开发实战

    ”携手“电子发烧友”联合推出了《KaihongOS手把手系列直播课程》,该系列课程以实际产品为案例,详细讲解每个产品的开发全流程。此次首发内容是《手把手教你做PC-
    的头像 发表于 01-06 20:46 864次阅读
    《<b class='flag-5'>手把手</b><b class='flag-5'>教你</b>做PC》课程即将启动!深开鸿引领探索KaihongOS笔记本电脑开发<b class='flag-5'>实战</b>