首页 自动驾驶

STM32 CAN通信疑难杂症:TJA1050波特率玄学与USB扩展坞掉电惊魂

分类:自动驾驶
字数: (1811)
阅读: (6510)
内容摘要:STM32 CAN通信疑难杂症:TJA1050波特率玄学与USB扩展坞掉电惊魂,

最近在搞一个STM32的CAN总线项目,遇到了个让人头大的问题:STM32通过TJA1050芯片进行CAN通信,怎么调都收发不正常。波特率、滤波器、中断都检查了无数遍,确认配置没问题,硬件连接也没松动,实在是让人摸不着头脑。甚至怀疑是不是TJA1050芯片本身有问题,换了好几个新的TJA1050芯片测试依然没效果。期间也各种百度、Google,尝试了很多方法,最终才发现问题所在,这里记录一下排查过程,希望能帮助到遇到类似问题的同学。

问题场景重现:波特率无误,收发静默

我的STM32 CAN分析仪硬件平台是STM32F103C8T6,CAN收发器是TJA1050。软件方面使用标准库开发。现象是:

STM32 CAN通信疑难杂症:TJA1050波特率玄学与USB扩展坞掉电惊魂
  1. CAN总线分析仪(上位机)能正常发送数据,单片机(下位机)接收不到。
  2. 单片机也能发送数据,但总线分析仪同样收不到。
  3. 示波器观察CAN_H和CAN_L的波形,发送时波形正常,但静止时电平不符合CAN总线规范(正常应该是2.5V左右)。
  4. 确认波特率配置正确,和其他设备测试也是OK的。

底层原理深度剖析:TJA1050、波特率与供电的三角关系

首先回顾一下CAN总线的几个关键点:

STM32 CAN通信疑难杂症:TJA1050波特率玄学与USB扩展坞掉电惊魂
  • CAN总线规范:CAN(Controller Area Network)是一种多主总线,常用于汽车电子、工业控制等领域。其物理层使用差分信号,具有抗干扰能力强的特点。
  • TJA1050芯片:TJA1050是NXP(原Philips)推出的一款CAN收发器芯片,负责CAN控制器和物理总线之间的信号转换。
  • 波特率:CAN总线的通信速率,必须保证总线上所有设备的波特率一致,才能正常通信。计算方法涉及时钟频率、分频系数等参数,需要仔细核对。
  • 终端电阻:CAN总线的两端需要接120欧姆的终端电阻,用于匹配阻抗,减少信号反射。
  • 共模电压:CAN_H和CAN_L的电压相对于地线的电压。通常情况下,两者都应该在2.5V左右。

按理说,如果这些都没问题,CAN通信应该正常工作。但实际情况并非如此。经过仔细排查,我发现问题出在两个方面:

STM32 CAN通信疑难杂症:TJA1050波特率玄学与USB扩展坞掉电惊魂
  1. USB扩展坞供电不足:我使用USB扩展坞给STM32开发板供电,这个扩展坞同时也连接了其他设备。当CAN总线上有较大数据流量时,STM32开发板的供电电压会短暂下降,导致TJA1050工作不稳定,无法正常收发数据。这就像高并发场景下,服务器CPU负载过高,导致系统响应缓慢一样。
  2. 波特率的精细调整:虽然我一直认为波特率是正确的,但实际上存在一定的偏差。在使用CAN分析仪时,我对波特率进行了更精确的校准,发现即使是1%的偏差,也可能导致通信失败。这跟Nginx配置不当,导致并发连接数上不去是一个道理,需要精益求精。

代码/配置解决方案:优化波特率,替换电源

针对上述问题,我的解决方案如下:

STM32 CAN通信疑难杂症:TJA1050波特率玄学与USB扩展坞掉电惊魂
  1. 替换电源:不再使用USB扩展坞供电,而是使用独立的5V电源给STM32开发板供电。这样可以保证供电电压的稳定性,避免TJA1050因供电不足而工作异常。
  2. 精细调整波特率:通过调整STM32的CAN初始化代码中的Prescaler和BS1/BS2的值,对波特率进行精确校准。可以使用CAN分析仪实时监测总线上的数据,并根据实际情况进行微调。

以下是STM32的CAN初始化代码片段,重点关注波特率相关的配置:

void CAN_Config(void)
{
  CAN_InitTypeDef        CAN_InitStructure;
  CAN_FilterInitTypeDef  CAN_FilterInitStructure;

  /* CAN register init */
  CAN_DeInit(CAN1);

  /* CAN cell init */
  CAN_InitStructure.CAN_TTCM = DISABLE;  //时间触发通信模式
  CAN_InitStructure.CAN_ABOM = DISABLE;  //自动离线管理
  CAN_InitStructure.CAN_AWUM = DISABLE;  //自动唤醒模式
  CAN_InitStructure.CAN_NART = DISABLE;  //禁止报文自动重传
  CAN_InitStructure.CAN_RFLM = DISABLE;  //接收FIFO锁定模式
  CAN_InitStructure.CAN_TXFP = DISABLE;  //发送FIFO优先级
  CAN_InitStructure.CAN_Mode = CAN_Mode_Normal; //正常工作模式

  // 波特率配置:Prescaler和BS1/BS2的值需要根据实际情况进行调整
  CAN_InitStructure.CAN_SJW  = CAN_SJW_1tq;     //同步跳转宽度1个时间单位
  CAN_InitStructure.CAN_BS1 = CAN_BS1_8tq;      //时间段1为8个时间单位
  CAN_InitStructure.CAN_BS2 = CAN_BS2_7tq;      //时间段2为7个时间单位
  CAN_InitStructure.CAN_Prescaler = 6;    //分频系数。调整此值以微调波特率 (72M/(6*(1+8+7)) = 500k)
  CAN_Init(CAN1, &CAN_InitStructure);

  // CAN filter init
  CAN_FilterInitStructure.CAN_FilterNumber = 0;        //过滤器编号
  CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdMask; //屏蔽位模式
  CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit;   //32位过滤器
  CAN_FilterInitStructure.CAN_FilterIdHigh = 0x0000;         //过滤器高16位ID
  CAN_FilterInitStructure.CAN_FilterIdLow = 0x0000;          //过滤器低16位ID
  CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0x0000;       //屏蔽位高16位
  CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0x0000;        //屏蔽位低16位
  CAN_FilterInitStructure.CAN_FilterFIFOAssignment = CAN_FIFO0;    //过滤器关联到FIFO0
  CAN_FilterInitStructure.CAN_FilterActivation = ENABLE;       //激活过滤器
  CAN_FilterInit(&CAN_FilterInitStructure);
}

实战避坑经验总结:关注细节,排除干扰

总结一下这次STM32 CAN通信问题的排查经验:

  • 电源稳定性至关重要:CAN总线对电源电压的稳定性要求较高,尤其是在高速通信时。使用独立的、稳定的电源是保证CAN通信正常工作的基础。
  • 波特率校准需要精益求精:即使是微小的波特率偏差,也可能导致通信失败。使用CAN分析仪进行精确校准是必不可少的步骤。
  • 检查终端电阻:确保CAN总线的两端都连接了120欧姆的终端电阻,避免信号反射。
  • 排除干扰源:CAN总线容易受到电磁干扰,尽量避免将CAN总线靠近高频设备或强电磁场。
  • 使用示波器观察波形:通过示波器观察CAN_H和CAN_L的波形,可以帮助判断总线状态是否正常。

希望这些经验能帮助大家少走弯路,顺利解决STM32 CAN通信问题。

STM32 CAN通信疑难杂症:TJA1050波特率玄学与USB扩展坞掉电惊魂

转载请注明出处: 夜雨听风

本文的链接地址: http://m.acea1.store/blog/397728.SHTML

本文最后 发布于2026-04-26 03:47:58,已经过了1天没有更新,若内容或图片 失效,请留言反馈

()
您可能对以下文章感兴趣
评论
  • 海王本王 16 小时前
    感谢楼主分享,学习了!以后遇到CAN通信问题,可以从电源和波特率这两个方面入手排查。
  • e人代表 5 天前
    波特率的精细调整确实很重要,之前我也以为波特率设置对了就万事大吉了,结果还是不行,后来用示波器仔细观察波形才发现问题。
  • 风一样的男子 5 天前
    终端电阻也很关键,之前我忘了接终端电阻,结果CAN总线一直收发异常,折腾了好久才发现。
  • 选择困难症 6 天前
    终端电阻也很关键,之前我忘了接终端电阻,结果CAN总线一直收发异常,折腾了好久才发现。
  • 非酋本酋 3 小时前
    波特率的精细调整确实很重要,之前我也以为波特率设置对了就万事大吉了,结果还是不行,后来用示波器仔细观察波形才发现问题。