目录

一、 CAN的应用

1.为什么车载用CAN?

USART的问题:
  ① 一对一通信,不能多设备共用总线
     一个USART只能接一个设备
     车上几十个ECU,不可能每个都拉一对TX/RX
  
  ② 没有错误检测机制
     数据被干扰了,收发双方都不知道
     车上电磁干扰大,数据出错率比桌面上高得多

  ③ 没有优先级机制
     紧急数据(刹车信号)和普通数据(车窗位置)
     在同一个总线上没有优先级区分

SPI的问题:
  ① 线太多(4根+每设备一根CS)
     车门里面没有空间拉这么多线
  
  ② 距离短(一般不超过30cm)
     车上ECU分布在车头到车尾,距离几米到十几米
  
  ③ 没有多主机能力
     不能两个ECU同时往总线上发数据

所以引入CAN:

车上需要这种通信系统:
  ① 所有ECU共用两根线(CANH/CANL)
     —— 代替USART的一对一和SPI的多CS

  ② 任何ECU都可以随时发消息
     —— 多主机,不需要主机轮询

  ③ 紧急消息优先发送
     —— 刹车信号必须比车窗信号先发

  ④ 有完整的错误检测和重发机制
     —— 数据错了能发现、能重发

  ⑤ 距离远(最长40m@1Mbps)
     —— 满足车身长度需求

CAN全部做到了。
  • CAN 与 USART SPI对比
对比项        USART           SPI              CAN
──────────────────────────────────────────────────────────
线数          2(TX/RX)      4+CS             2(CANH/CANL)
距离          几米            几十厘米         最长40米
速度          115200~921600  几MHz~几十MHz    最高1Mbps
                                                (低速CAN到125kbps)
多设备        不支持           支持(需CS线)    支持(无CS线)
多主机        不支持           困难             原生支持
优先级        无              无               有(ID仲裁)
错误检测       无(只有奇偶校验) 无              有(CRC+ACK+位填充)
数据量        任意             任意              一帧最多8字节
                                             (CAN FD最多64字节)
每帧固定格式   起始+数据+停止    无固定格式       SOF+ID+控制+数据+CRC+ACK+EOF

2. CAN连接示意

  • 车载网络中:

    发动机ECU   ──┐
                 │
    变速箱ECU   ──┤
                 │
    ABS/ESP   ───┼──── CANH ────┐
                 │              │          ┌───── 车窗ECU
    车身BCM    ───┤              ├─────────┤
                 │              │          └───── 车门ECU
    气囊ECU    ───┤     CANL ────┘
                 │
    仪表盘     ───┘
    
    所有ECU都挂在同一对CANH/CANL上
    任何ECU都能发消息
    任何ECU都能收到所有消息(但不一定处理)
    
  • STM32连接到CAN总线:

    STM32不能直接连CAN总线——需要CAN收发器。
    
               CAN收发器
      STM32   ┌──────────┐
      CAN_TX ─┤ TX      CANH├─── CANH
              │          │
      CAN_RX ─┤ RX      CANL├─── CANL
              │          │
              └──────────┘
               VCC=3.3V   GND
    
      常用CAN收发器芯片:
        TJA1050(5V供电,推荐)
        SN65HVD230(3.3V供电)
        TJA1040(带待机模式)
        
      STM32F103C8T6的CAN引脚:
        CAN1_RX = PA11
        CAN1_TX = PA12
    

3. CAN物理层特性:

3.1 抗干扰
  • USART用一根TX线传输,SPI用一根MOSI线传输。CAN为什么用两根?因为抗干扰。

    车上环境:
      发动机点火线圈产生的高压脉冲
      电机驱动产生的大电流突变
      继电器吸合产生的电弧
      这些都会在导线上感应出噪声电压
    
    单端传输(USART/SPI):
      TX对GND的电压:0V或3.3V
      如果干扰在线上感应了+2V噪声
      你发3.3V,对方收到5.3V
      你发0V,对方收到2V(可能被误判为1)
      数据就错了
    
    差分传输(CAN):
      CANH和CANL两根线一起传
      CANH - CANL 的差值代表数据
      如果两根线同时被感应了+2V噪声
      (CANH+2) - (CANL+2) = CANH - CANL
      差值不变,数据不受影响
    
3.2 CAN总线电平逻辑
CAN总线的两种状态:

  显性(Dominant):
    CANH = 3.5V
    CANL = 1.5V
    差分电压 = 3.5 - 1.5 = 2.0V
    逻辑值 = 0
    为什么叫"显性"?
      只要有一个ECU输出显性,总线就是显性
      多个ECU同时输出时,显性覆盖隐性

  隐性(Recessive):
    CANH = 2.5V
    CANL = 2.5V
    差分电压 = 2.5 - 2.5 = 0V
    逻辑值 = 1
    为什么叫"隐性"?
      所有ECU都输出隐性时,总线才是隐性
      有一个ECU输出显性,总线就被拉成显性
  • 显性–差分电压有值–逻辑为0;
  • 隐性–差分电压为0–逻辑为1;
  • "线与"特性——和I2C的开漏类似:

    多个ECU同时发送:
      如果ECU_A发显性(0),ECU_B发隐性(1)
      总线结果是显性(0)
      因为显性驱动能力强(推挽),隐性靠电阻(类似上拉)
      这就是CAN仲裁的物理基础
    
  • CAN控制器通过显性隐性机制实现无损仲裁:显性压倒隐性

    例如:

    ​ 发动机ECU : ID = 0X100 发送

    ​ ABS ECU : ID = 0X080 发送

    两个同时发送,CAN 不会冲突,会自动仲裁:

    规则: ID越小优先级越高;

    所以ABS先发,发动机停止发送等待下一次(是等待,不是重发)

3.3 终端电阻
CAN总线两端必须各接一个120Ω电阻:

  ┌──────┐              ┌──────┐
  │ ECU1 │──── CANH ────│ ECU2 │
  │      │   120Ω  120Ω │      │
  │      │──── CANL ────│      │
  └──────┘              └──────┘

为什么需要终端电阻?
  防止信号反射
  CAN总线上的信号频率高(最高1Mbps)
  如果总线末端不匹配阻抗
  信号会反射回来,和原始信号叠加
  导致数据错误

  为什么是120Ω?
  CAN总线设计时定义的特性阻抗就是120Ω
  汽车维修中经常遇到的故障就是"终端电阻丢失"
  表现为CAN通信时好时坏
  • CAN总线:

    120Ω
     │
    CAN_H
     │
     │
     ECU1
     │
     ECU2
     │
     ECU3
     │
    CAN_L
     │
    120Ω
    

4. CAN内部结构

  • STM32F103内部CAN框图:

               ┌───────────┐
               │   CPU     │
               └─────┬─────┘
                     │
            ┌────────▼────────┐
            │     bxCAN       │
            └───────┬─────────┘
                    │
         ┌──────────┼──────────┐
         │          │          │
         ▼          ▼          ▼
    
    TX邮箱(x3)   Filter(14)   RX FIFO(x2)
    
         │                      │
         └──────────┬───────────┘
                    ▼
               CAN收发器
                    ▼
               CAN总线
    

    操作CAN实际是在操作这3部分:

    发送邮箱
    接收FIFO
    过滤器
    
4.1 发送邮箱(X Mailbox)
  1. 在前面时候,类似USRAT发送:

    USART_SendData();
    直接发进寄存器;
    

    CAN不同,因为数据量大:

    ​ 可能很多帧等待发送

    ​ 所以CAN内部有缓存

  2. STM32中提供3个发送邮箱:

    Mailbox0
    Mailbox1
    Mailbox2
        
    每个邮箱都能存1帧数据
    
    • 假设CPU发送:

      Frame1
      Frame2
      Frame3
      

      则:

      Mailbox0 -> Frame1
      Mailbox1 -> Frame2
      Mailbox2 -> Frame3
      

      然后CAN控制器自己决定:

      谁先发
      谁后发
      
4.2 接收FIF0
  1. 接收与发送不同

总线:

ECU1发送
ECU2发送
ECU3发送
    
都可能收到

如果CPU来不及处理–数据会丢失
所以CAN内部提供:

FIFO0
FIFO1

两个接收队列;

  1. FIFO:

    First In First Out–先进先出

例如:收到3帧:

Frame1
Frame2
Frame3

存储:

FIFO

┌───────┐
│Frame1 │
├───────┤
│Frame2 │
├───────┤
│Frame3 │
└───────┘

CPU读取:

先读Frame1
再读Frame2
再读Frame3
  1. 两个FIFO的作用:方便管理
    可以对接收到的数据进行分类

例如:

发动机数据:
    0x100
	0x101
	0x102
放:
    FIFO0
    
诊断数据:
    0x700
	0x701
放:
    FIFO1
4.3 过滤器(Filter)
  1. 不需要的数据直接丢弃:

CAN是广播
总线上:

发动机转速
车速
ABS状态
空调状态
电池电压
电池温度
GPS数据
...

可能上千条消息;
而对应ECU只关心:

电池电压

如果全部接收,过于消耗CPU;

所以CAN提供–过滤器:

不需要的数据直接丢弃;
需要的数据进进入--FIFO
  1. 过滤器工作位置 – 硬件执行

    总线
     ↓
    Filter
     ↓
    FIFO
     ↓
    CPU
    
  2. 过滤器模式:

    掩码模式--Mask Mode--全部接收
    列表模式--List Mode--直接指定ID
    
    • 掩码模式–Mask Mode–全部接收

      例如:
          ID=0X100~0X1FF
          全部接收;
          
          通过: ID + MASK 实现
          
      if((ID & MASK)==TARGET)
      {
          接收
      }
      
    • 列表模式–List Mode–直接指定ID

      例如:
          0x100
      	0x123
      	0x555
      	0x777
      接收
          其他全部拒绝
      
  3. 14组过滤器,每一组都有

    FR1
    FR2
        
    两个32位寄存器
    
4.4 回环模式(LoopBack)

回环模式 即:

通过CAN发送Frame
    直接返回自己的接收模块:
        TX
 		↓
	  CAN内部
 		↓
		RX
4.5 CAN波特率:

常用:

125K
250K
500K
1M

汽车中常见:

500kbps

新能源:

500kbps
1Mbps

CAN传输中所有节点波特率必须一致

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐