盒子
盒子
文章目录
  1. can驱动配置
  2. can驱动启动失败
  3. 解决措施

树莓派外挂MCP2515模块爬坑记录

最近由于接近放假,协调不到调板哥,于是兼职下调板的工作。虽然之前也业余玩过树莓派和arduino,但是由于没有stm32的开发经验和硬件知识的匮乏,还是遇到了很多坑。

这个can总线模块就卡了我两三天,由于涉及到树莓派的配置知识,觉得有必要记录一下。

can驱动配置

目前的这个项目涉及到了树莓派和stm32的通信,使用的是can总线。由于树莓派本身不提供can总线功能,需要外挂一个MCP2515芯片。

网上搜索树莓派的can总线配置,可以找到不少的资料,其中感觉最详细的是这一篇。但是里面有个小bug,我等下再说。

首先网上的接线多数都是这样的:

1
2
3
4
5
6
7
8
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驱动:

1
2
3
4
5
6
7
8
# 打开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:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
...
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,所以我们配不配都没有关系,下面几种配置方法都是对的:

  1. dtoverlay=spi0-1cs,cs0_pin=8
  2. dtoverlay=spi0-1cs
  3. dtoverlay=spi0-2cs,cs0_pin=8
  4. dtoverlay=spi0-2cs
  5. # 不配置,留空

之前我说的这一篇博客的小bug就是它配了dtoverlay=spi1-1cs,实际上是配置了spi1的cs脚,对我们的配置在spi0的can控制器没有影响

我们的接法和网上的不一样,INT脚接gpio17,CS脚接gpio22。根据文档修改下配置就好:

1
2
dtoverlay=mcp2515-can0,oscillator=16000000,interrupt=17
dtoverlay=spi0-1cs,cs0_pin=22

can驱动启动失败

事情到这里其实还算一帆风顺,我也没有花多少时间。但是当重启树莓派发现并没有/sys/bus/spi/devices/spi0.0/net/can0这个设备,使用dmesg命令查看开机日志会发现这样的一个错误,mcp2515驱动启动失败了:

1
2
3
[    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配置,让我一度怀疑自己的英语阅读水平以为自己文档看劈叉了(虽然水平的确也不怎样)。

由于我们的接线和网上的不一样,所以试了很多种配置都没有用。然后我们只能不断做尝试

  1. 让硬件帮忙跳线,跳到和网上的一样,然后用网上的配置 — 失败。

  2. 由于网上的例子都是用4.x的树莓派内核,而我们用的是5.x的内核。所以又猜测是系统版本原因,网上找了个旧的树莓派镜像验证 — 失败。

  3. 见到这篇博客说是电压问题,但是我用万用表量电压是5.17V,接近他所说的5.2伏 — 无用

  4. 找来示波器测量,发现cs脚在开机的时候的确有被拉低又拉高 – 排除树莓派gpio引脚的硬件问题

解决措施

就这样卡了两天,没有办法了在某宝上买了个用到mcp2515的模块回来验证(我们的板子是自己做的),发现买回来的是成功的。

那基本定位是硬件问题,于是交给硬件对比差异。经过修改引脚、晶振、最后定位到的确是电压问题,但是我们这边需要将电压改到3.3v才能用…

最后感慨几句。这段时间虽然遇到的大部分问题最终都定位到是硬件的问题。但是由于芯片都是买的,相当于一个黑盒,硬件修改也比较麻烦,所以需要软件先调试分析给出大概的定位。由于嵌入式经验不足,i2c、spi、can、i2s等各种硬件协议都只能现学现卖。嵌入式的api又由于需要考虑性能问题和应用层api侧重易用性的思路不一样,一堆配置和前置条件比较难用。每天都处于对自己能力的怀疑当中,不确定是否能做好,但所幸大部分问题都找到解决或者规避措施。也算去计算机的硬件底层瞄了几眼,开了不少眼界,算是给不平凡的鼠年画上了个特别的句号。希望明年还能继续保持对学习热情,有趣的东西那么多,为什么不去学呢?