最近由于接近放假,协调不到调板哥,于是兼职下调板的工作。虽然之前也业余玩过树莓派和arduino,但是由于没有stm32的开发经验和硬件知识的匮乏,还是遇到了很多坑。
这个can总线模块就卡了我两三天,由于涉及到树莓派的配置知识,觉得有必要记录一下。
can驱动配置
目前的这个项目涉及到了树莓派和stm32的通信,使用的是can总线。由于树莓派本身不提供can总线功能,需要外挂一个MCP2515芯片。
网上搜索树莓派的can总线配置,可以找到不少的资料,其中感觉最详细的是这一篇。但是里面有个小bug,我等下再说。
首先网上的接线多数都是这样的:
RPi Pin RPi Label CAN Module
02---------5V------------VCC
06---------GND-----------GND
19---------GPIO10--------MOSI (SI)
21---------GPIO9---------MISO (SO)
22---------GPIO25--------INT
23---------GPIO11--------SCK
24---------GPIO8---------CS
然后修改文件/boot/config.txt激活MCP2515驱动:
# 打开spi总线,树莓派与MCP2515之前通过spi通信,然后再转成can协议
dtparam=spi=on
# 在spi0.0上配置MCP2515 CAN控制器,CAN控制器的晶振频率是16MHz,INT脚接到了gpio25
dtoverlay=mcp2515-can0,oscillator=16000000,interrupt=25
# SPI0只使用一个CS引脚,把spi0.0的cs脚配置到gpio8。实际上不配置这个也没有影响
dtoverlay=spi0-1cs,cs0_pin=8
这些dtoverlay配置项的说明可以查看/boot/overlays/README:
...
Name: mcp2515-can0
Info: Configures the MCP2515 CAN controller on spi0.0
Load: dtoverlay=mcp2515-can0,<param>=<val>
Params: oscillator Clock frequency for the CAN controller (Hz)
spimaxfrequency Maximum SPI frequence (Hz)
interrupt GPIO for interrupt signal
Name: mcp2515-can1
Info: Configures the MCP2515 CAN controller on spi0.1
Load: dtoverlay=mcp2515-can1,<param>=<val>
Params: oscillator Clock frequency for the CAN controller (Hz)
spimaxfrequency Maximum SPI frequence (Hz)
interrupt GPIO for interrupt signal
...
Name: spi0-1cs
Info: Only use one CS pin for SPI0
Load: dtoverlay=spi0-1cs,<param>=<val>
Params: cs0_pin GPIO pin for CS0 (default 8)
no_miso Don't claim and use the MISO pin (9), freeing
it for other uses.
Name: spi0-2cs
Info: Change the CS pins for SPI0
Load: dtoverlay=spi0-2cs,<param>=<val>
Params: cs0_pin GPIO pin for CS0 (default 8)
cs1_pin GPIO pin for CS1 (default 7)
no_miso Don't claim and use the MISO pin (9), freeing
it for other uses.
...
所以以后需要打开什么功能,都可以到这文档里面查看配置方法。
首先由于我们把MCP2515 CAN控制器配到了spi0.0,所以我们需要配置spi0.0的cs脚(当然如果你也可以配置mcp2515-can1将它配置到spi0.1,这样的话就需要改spi0.1的cs脚)。
这个cs脚使是用来选择设备的,当有多个设备挂到spi总线上的时候可以用这个脚去选择指定设备。由于我们只有一个设备,所以可以使用spi0-1cs指定spi0只有一个cs脚,当然你也可以配置两个cs脚(spi0-2cs)留空一个不用。然后无论是spi0-1cs还是spi0-2cs,cs0默认都是gpio8,所以我们配不配都没有关系,下面几种配置方法都是对的:
- dtoverlay=spi0-1cs,cs0_pin=8
- dtoverlay=spi0-1cs
- dtoverlay=spi0-2cs,cs0_pin=8
- dtoverlay=spi0-2cs
- # 不配置,留空
之前我说的这一篇博客的小bug就是它配了dtoverlay=spi1-1cs,实际上是配置了spi1的cs脚,对我们的配置在spi0的can控制器没有影响
我们的接法和网上的不一样,INT脚接gpio17,CS脚接gpio22。根据文档修改下配置就好:
dtoverlay=mcp2515-can0,oscillator=16000000,interrupt=17
dtoverlay=spi0-1cs,cs0_pin=22
can驱动启动失败
事情到这里其实还算一帆风顺,我也没有花多少时间。但是当重启树莓派发现并没有/sys/bus/spi/devices/spi0.0/net/can0这个设备,使用dmesg命令查看开机日志会发现这样的一个错误,mcp2515驱动启动失败了:
[ 7.653601] mcp251x spi0.0: MCP251x didn't enter in conf mode after reset
[ 7.653654] mcp251x spi0.0: Probe failed, err=16
[ 7.653738] mcp251x: probe of spi0.0 failed with error -16
然后我就懵逼了,网上搜索这个错误找到了很多遇到这种情况的人,但是他们的回答都是加上dtoverlay=spi0-1cs配置,让我一度怀疑自己的英语阅读水平以为自己文档看劈叉了(虽然水平的确也不怎样)。
由于我们的接线和网上的不一样,所以试了很多种配置都没有用。然后我们只能不断做尝试
让硬件帮忙跳线,跳到和网上的一样,然后用网上的配置 --- 失败。
由于网上的例子都是用4.x的树莓派内核,而我们用的是5.x的内核。所以又猜测是系统版本原因,网上找了个旧的树莓派镜像验证 --- 失败。
见到这篇博客说是电压问题,但是我用万用表量电压是5.17V,接近他所说的5.2伏 --- 无用
找来示波器测量,发现cs脚在开机的时候的确有被拉低又拉高 -- 排除树莓派gpio引脚的硬件问题
解决措施
就这样卡了两天,没有办法了在某宝上买了个用到mcp2515的模块回来验证(我们的板子是自己做的),发现买回来的是成功的。
那基本定位是硬件问题,于是交给硬件对比差异。经过修改引脚、晶振、最后定位到的确是电压问题,但是我们这边需要将电压改到3.3v才能用...
最后感慨几句。这段时间虽然遇到的大部分问题最终都定位到是硬件的问题。但是由于芯片都是买的,相当于一个黑盒,硬件修改也比较麻烦,所以需要软件先调试分析给出大概的定位。由于嵌入式经验不足,i2c、spi、can、i2s等各种硬件协议都只能现学现卖。嵌入式的api又由于需要考虑性能问题和应用层api侧重易用性的思路不一样,一堆配置和前置条件比较难用。每天都处于对自己能力的怀疑当中,不确定是否能做好,但所幸大部分问题都找到解决或者规避措施。也算去计算机的硬件底层瞄了几眼,开了不少眼界,算是给不平凡的鼠年画上了个特别的句号。希望明年还能继续保持对学习热情,有趣的东西那么多,为什么不去学呢?