最近由于接近放假,協調不到調板哥,于是兼職下調板的工作。雖然之前也業余玩過樹莓派和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側重易用性的思路不一樣,一堆配置和前置條件比較難用。每天都處于對自己能力的懷疑當中,不確定是否能做好,但所幸大部分問題都找到解決或者規避措施。也算去計算機的硬件底層瞄了幾眼,開了不少眼界,算是給不平凡的鼠年畫上了個特別的句號。希望明年還能繼續保持對學習熱情,有趣的東西那么多,為什么不去學呢?