最近在搞一个项目,用 STM32 单片机通过 CAN 总线与另一个设备通信,用的是 TJA1050 作为 CAN 收发器。配置好波特率等参数后,发现死活通信不上。排查了半天,发现问题竟然出在 USB 扩展坞的供电上,简直绝了!下面分享下我的排查过程和解决方案,希望能帮到遇到同样问题的你。
问题场景重现
我的开发环境是:
- STM32F103C8T6 最小系统板
- TJA1050 CAN 收发器模块
- USB-TTL 模块 (CH340) 用于串口调试
- USB 扩展坞 (因为电脑 USB 口不够用)
一开始,我直接把 USB-TTL 模块插到扩展坞上,然后用串口助手观察 CAN 总线的数据。结果发现,CAN 总线一直没有数据收发。用示波器测量 CAN_H 和 CAN_L 的电压,发现波形异常,根本不像正常的 CAN 总线信号。
底层原理深度剖析
CAN 总线的通信原理我就不赘述了,重点说说 TJA1050。TJA1050 是一款常用的 CAN 收发器芯片,负责将单片机的 CAN 控制器输出的信号转换成 CAN 总线上的差分信号,并将 CAN 总线上的差分信号转换成单片机 CAN 控制器可以识别的信号。它对电源电压有一定要求,如果供电不足,可能会导致无法正常工作,进而导致 CAN 总线通信失败。
一般的 USB 扩展坞,虽然提供了多个 USB 接口,但其总的供电能力是有限的。如果接的设备过多,或者某个设备需要的电流较大,就可能导致供电不足。而 USB-TTL 模块虽然功耗不大,但它也会消耗一定的电流。如果扩展坞的供电质量不好,或者 STM32 单片机本身也需要从 USB 口取电,就可能导致 TJA1050 的供电电压不稳定,从而影响 CAN 通信。
另外,波特率设置不正确也是一个常见的问题。CAN 总线的波特率需要和通信的另一端保持一致,否则无法正常通信。但是,即使波特率设置正确,如果晶振频率不稳定,也可能导致波特率偏差过大,从而导致通信失败。这种情况比较隐蔽,需要用频率计或者示波器来测量晶振频率,确认晶振是否正常工作。
具体的代码/配置解决方案
检查供电:首先,尝试将 USB-TTL 模块直接插到电脑的 USB 接口上,而不是通过 USB 扩展坞。如果这样可以解决问题,那就说明是扩展坞的供电问题。可以尝试更换一个供电能力更强的 USB 扩展坞,或者直接使用 USB HUB 带独立电源的。

确认波特率:使用专业的 CAN 分析仪(例如周立功 USBCAN-II Pro) 检查 CAN 总线上的波特率是否与 STM32 单片机设置的波特率一致。并且用示波器观察 CAN_H 和 CAN_L 的波形,看看是否存在干扰或者信号畸变。
下面是 STM32 CubeMX 中 CAN 的配置代码片段:
CAN_HandleTypeDef hcan;
void MX_CAN_Init(void)
{
hcan.Instance = CAN;
hcan.Init.Prescaler = 6; // 根据晶振频率和波特率计算得出
hcan.Init.Mode = CAN_MODE_NORMAL; // 设置为正常模式
hcan.Init.SJW = CAN_SJW_1TQ;
hcan.Init.BSeg1 = CAN_BS1_12TQ;
hcan.Init.BSeg2 = CAN_BS2_5TQ;
hcan.Init.TTCM = DISABLE;
hcan.Init.ABOM = DISABLE;
hcan.Init.AWUM = DISABLE;
hcan.Init.NART = DISABLE;
hcan.Init.RFLM = DISABLE;
hcan.Init.TXFP = DISABLE;
if (HAL_CAN_Init(&hcan) != HAL_OK)
{
Error_Handler();
}
}
接地问题:确保 STM32 单片机、TJA1050 模块和 CAN 总线的地线连接良好,避免出现地线环路。可以使用星型接地的方式,将所有的地线都连接到一个公共的地线点。
终端电阻:CAN 总线的两端需要接 120 欧姆的终端电阻,以防止信号反射。检查 CAN 总线的两端是否都接了终端电阻,并且电阻值是否正确。
实战避坑经验总结
- USB 扩展坞的坑:尽量避免使用质量差的 USB 扩展坞,特别是需要大电流的场合。最好选择带独立电源的 USB HUB。
- 供电的重要性:CAN 总线通信对供电质量要求较高,务必确保 TJA1050 的供电电压稳定可靠。可以用示波器测量 TJA1050 的电源引脚,看看是否存在电压波动。
- 波特率的校准:在调试 CAN 总线通信时,一定要仔细核对波特率是否正确。可以使用专业的 CAN 分析仪来辅助调试。
- 注意共模干扰:CAN 总线在复杂的电磁环境下容易受到共模干扰,导致通信失败。可以尝试使用共模电感来抑制共模干扰。
希望这些经验能帮助你解决 STM32 CAN 通信的问题。如果还有其他问题,欢迎留言讨论!
冠军资讯
深夜敲代码