树莓派4与Arduino CAN总线通信故障求助
树莓派4与Arduino CAN总线通信故障排查方案
问题背景
已实现多树莓派间CAN总线通信,但树莓派与Arduino(Uno/Mega2560)的CAN通信始终失败:Arduino Uno运行CAN示例代码时提示Starting CAN failed!;Mega2560无报错,但树莓派通过Python代码或candump can0命令均无法接收数据。
已完成配置与代码
树莓派配置
/boot/config.txt添加内容:
dtoverlay=mcp2515-can0,oscillator=8000000,interupt=12 dtoverlay=spi-bcm2835-overlay
- 启动CAN总线命令:
sudo ip link set can0 up type can bitrate 500000
Python收发代码
发送代码:
import time import can bustype = 'socketcan' channel = 'can0' bus = can.interface.Bus(channel=channel, bustype=bustype,bitrate=500000) while True: msg = can.Message(arbitration_id=2, data=[0, 0, 0, 0, 0, 0], is_extended_id=False) bus.send(msg) time.sleep(0.1)
接收代码:
import time import can bustype = 'socketcan' channel = 'can0' bus = can.interface.Bus(channel=channel, bustype=bustype,bitrate=500000) while True: print(bus.recv()) time.sleep(0.1)
Arduino接线(Uno/Mega通用)
- VCC → 5V
- GND → GND
- CS → 引脚10
- SO → 引脚12
- SI → 引脚11
- SCK → 引脚13
- INT → 引脚2
故障排查与解决方案
1. 硬件与接线核心修正
- Mega2560 SPI引脚错误:Mega的SPI引脚为51(MOSI/SI)、50(MISO/SO)、52(SCK),当前接的11/12/13是普通IO,并非SPI引脚,需更换为对应SPI引脚,CS可保留10。
- 终端电阻:CAN总线两端必须接120Ω终端电阻,否则信号反射会导致通信中断,可在树莓派或Arduino的MCP2515模块上焊接终端电阻。
- 引脚拼写错误:树莓派
config.txt中interupt拼写错误,修正为interrupt,否则中断引脚无法正常工作:
dtoverlay=mcp2515-can0,oscillator=8000000,interrupt=12 dtoverlay=spi-bcm2835-overlay
修改后重启树莓派生效。
2. Arduino库与代码调整
针对Uno启动失败问题
- 匹配晶振频率:树莓派配置的是8MHz晶振,Arduino代码中必须同步指定,避免波特率不匹配。示例代码(使用mcp2515库):
#include <mcp2515.h> MCP2515 mcp2515(10); // CS引脚10 struct can_frame canMsg; void setup() { Serial.begin(9600); while (!Serial); // 初始化时指定8MHz晶振+500Kbps波特率 if (mcp2515.begin(MCP_ANY, CAN_500KBPS, MCP_8MHZ) == MCP_FAIL) { Serial.println("Starting CAN failed!"); while (1); } mcp2515.setMode(MCP_NORMAL); } void loop() { canMsg.can_id = 0x02; canMsg.can_dlc = 6; memset(canMsg.data, 0, 6); mcp2515.sendMessage(&canMsg); delay(100); }
针对Mega无数据问题
- 按修正后的SPI引脚重新接线,代码中同样指定8MHz晶振+500Kbps波特率,增加串口调试确认发送状态:
#include <mcp2515.h> MCP2515 mcp2515(10); struct can_frame canMsg; void setup() { Serial.begin(9600); while (!Serial); if (mcp2515.begin(MCP_ANY, CAN_500KBPS, MCP_8MHZ) == MCP_FAIL) { Serial.println("Starting CAN failed!"); while (1); } mcp2515.setMode(MCP_NORMAL); } void loop() { canMsg.can_id = 0x02; canMsg.can_dlc = 6; memset(canMsg.data, 0, 6); if(mcp2515.sendMessage(&canMsg)){ Serial.println("Message sent"); } delay(100); }
3. 分步验证通信
- 先测试Arduino到Arduino的CAN通信,排除模块本身故障。
- 树莓派端执行
candump can0监听,Arduino发送数据,查看终端是否有输出。 - 树莓派端执行
cansend can0 002#000000000000发送数据,Arduino端接收并打印,确认双向通路。
内容的提问来源于stack exchange,提问作者Михаил Димитров
相关产品推荐
相关产品推荐

