RPi 2B: 使用基于MCP2515+TJA1050的模块进行CAN通信

淘宝上卖得最多的CAN模块就是基于MCP2515的CAN总线模块了,该模块通过SPI接口与MCU进行通信。RPi 2B/3B扩展口中包含SPI总线信号,可以很方便地对这个模块进行操作。这使得我们可以很方便地通过can-util工具获取CAN总线中的通信数据,当然也可以对CAN总线中的设备进行读写操作。

  • MCP2515 CAN模块

1. 美图

2016_09_23_mcp2515_can_module

(原图片来自: https://hacktronics.co.in/rs232485-usb-ttl-converters/mcp2515-can-bus-module-tja1050-receivers-spi-protocol)

2. 模块特点

- 支持CAN V2.0B规范,最大通讯速度可达到1Mb/S

- 一次可发送0 〜 8个字节数据,CAN总线每帧最多可发送8个字节

- 支持标准帧、扩展帧及远程帧

- 5V电源供电,使用SPI接口进行控制

- 120欧姆终端电阻

- 模块尺寸:4.4cm x 2.8cm

- 工作电流5mA

3. MCP2515

官网链接:http://www.microchip.com/wwwproducts/en/en010406

数据册:http://ww1.microchip.com/downloads/en/DeviceDoc/21801G.pdf

  • RPi 2B与MCP2515 CAN模块

1. 连线

RPi 2B 40pin扩展口的定义请看这里:

Brillo开发: 在RPi 2B(树莓派)上点亮LED

引脚关系如下:

RPi 2B                MCP2515_CAN
--------------------------------------------------
P1-02 5V           -> VCC 5V电源
P1-06 GND          -> GND
P1-24 GPIO8(CE0)   -> CS
P1-19 GPIO10(MOSI) -> MOSI
P1-21 GPIO9 (MISO) <- MISO
P1-23 GPIO11(SCLK) -> SCK
P1-22 GPIO25       -> INT
  • Raspbian系统操作方法

1. 修改开机脚本config.txt

dtparam=spi=on
dtoverlay=mcp2515-can0,oscillator=8000000,interrupt=25,spimaxfrequency=1000000

NOTE:

- kernel dt的配置与硬件紧密相连,要跟据硬件的实际情况进行设置

- 由MCP2515 datasheet可知,spimaxfrequency可设为10MHz

- 相关的说明文档详见/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

由于原Raspbian系统运行时,在kernel log中与CAN、SPI相关的信息太少,可能在kernel log中只显示:

[    1.422448] CAN device driver interface

再由于第一次在RPi 2B上使用该模块,并不清楚出现这个信息的时候,模块是否正常工作,加之将该模块的CAN接口接入总线的时候,得不到所需的信息。于是重新配置了kernel,打开了SPI与CAN 的debug信息,使得在kernel log中能够出现更多的调试信息,之后查看相关模块是否正常运行会在kernel log中出现如下信息:

pi@raspberrypi:~ $ dmesg | grep -i '\(can\|spi\)'
[    1.411356] spi-bcm2835 3f204000.spi: no tx-dma configuration found - not using dma mode
[    1.420102] spi-bcm2835 3f204000.spi: registered master spi0
[    1.420318] spi spi0.0: setup mode 0, 8 bits/w, 1000000 Hz max --> 0
[    1.420755] spi-bcm2835 3f204000.spi: registered child spi0.0
[    1.420805] spi spi0.1: setup mode 0, 8 bits/w, 500000 Hz max --> 0
[    1.421593] spi-bcm2835 3f204000.spi: registered child spi0.1
[    1.422448] CAN device driver interface
[    1.422710] mcp251x spi0.0: setup mode 0, 8 bits/w, 1000000 Hz max --> 0
[    1.432873] mcp251x spi0.0: CANCTRL 0x87
[    2.026679] can: controller area network core (rev 20120528 abi 9)
[    2.026848] can: raw protocol (rev 20120528)
[    2.026873] can: broadcast manager protocol (rev 20120528 t)
[    2.026907] can: netlink gateway (rev 20130117) max_hops=1
[  285.204945] mcp251x spi0.0 can0: bitrate error 33.3% too high
[  288.362092] mcp251x spi0.0 can0: bitrate error 0.7%
[  315.512812] mcp251x spi0.0: CNF: 0x00 0x88 0x01
[  477.586754] mcp251x spi0.0 can0: bitrate error 33.3% too high
[  481.065628] mcp251x spi0.0 can0: bitrate error 66.6% too high
[  483.985830] mcp251x spi0.0 can0: bitrate error 77.7% too high
[  500.851264] mcp251x spi0.0: CNF: 0x01 0xb5 0x01
[  640.260866] mcp251x spi0.0: CNF: 0x13 0xb5 0x01
[  819.771295] mcp251x spi0.0 can0: bitrate error 33.3% too high
[  829.422866] mcp251x spi0.0 can0: bitrate error 33.3% too high
[  845.065217] mcp251x spi0.0: CNF: 0x00 0x91 0x01

当然,重新使用自己重新配置的kernel的另一个好处就是可以随时去修改mcp2515 driver的代码,以满足自己的需求。

2. 通过ip命令创建CAN网络设备,设置波特率为500kbps:

pi@raspberrypi:~/can-utils $ sudo ip link set can0 type can bitrate 500000
pi@raspberrypi:~/can-utils $ sudo ifconfig can0 up

这时我们可以使用ip命令查看CAN网络信息:

pi@raspberrypi:~/can-utils $ sudo ip -s -d link show can0
2: can0: <NOARP,UP,LOWER_UP,ECHO> mtu 16 qdisc pfifo_fast state UNKNOWN mode DEFAULT group default qlen 10
    link/can  promiscuity 0 
    can state ERROR-ACTIVE restart-ms 0 
	  bitrate 500000 sample-point 0.750 
	  tq 250 prop-seg 2 phase-seg1 3 phase-seg2 2 sjw 1
	  mcp251x: tseg1 3..16 tseg2 2..8 sjw 1..4 brp 1..64 brp-inc 1
	  clock 4000000
	  re-started bus-errors arbit-lost error-warn error-pass bus-off
	  0          0          0          3          3          0         
    RX: bytes  packets  errors  dropped overrun mcast   
    224238     34273    12      0       12      0      
    TX: bytes  packets  errors  dropped carrier collsns 
    0          0        0       0       0       0

3. 下载并安装can-utils:

$ git clone https://github.com/linux-can/can-utils.git
$ cd can-utils
$ make

4. 使用candump命令获取总线上的数据:

pi@raspberrypi:~/can-utils $ sudo ./candump -cae -t z can0,0:0,#FFFFFFFF
 (000.000000)  can0  19D   [8]  40 00 3F FF 10 00 00 FF   '@.?.....'
 (000.000280)  can0  1AF   [3]  00 00 09                  '...'
 (000.000546)  can0  1F5   [8]  0F 0D 00 00 00 00 03 00   '........'
 (000.006001)  can0  0C7   [4]  04 00 00 00               '....'
 (000.006259)  can0  0F9   [8]  80 00 D0 00 00 00 00 00   '........'
 (000.006518)  can0  199   [8]  CF FF 47 2C B8 D1 00 FF   '..G,....'
 (000.018526)  can0  0C7   [4]  04 00 00 00               '....'
 (000.018782)  can0  0F9   [8]  80 00 D0 00 00 00 00 00   '........'
 (000.019059)  can0  199   [8]  0F FF 47 2C B8 D4 00 FF   '..G,....'
 (000.024955)  can0  19D   [8]  80 00 3F FE 10 00 00 FF   '..?.....'
 (000.025206)  can0  1AF   [3]  00 00 09                  '...'
 (000.025536)  can0  1F5   [8]  0F 0D 00 00 00 00 03 00   '........'
 (000.030997)  can0  0C7   [4]  04 00 00 00               '....'
 (000.031290)  can0  0F9   [8]  80 00 D0 00 00 00 00 00   '........'
 (000.031577)  can0  199   [8]  4F FF 47 2C B8 D3 00 FF   'O.G,....'
 (000.043556)  can0  0C7   [4]  04 00 00 00               '....'
 (000.043848)  can0  0F9   [8]  80 00 D0 00 00 00 00 00   '........'
 (000.044140)  can0  199   [8]  8F FF 47 2C B8 D2 00 FF   '..G,....'
 (000.050000)  can0  19D   [8]  C0 00 3F FD 10 00 00 FF   '..?.....'
 (000.050306)  can0  1AF   [3]  00 00 09                  '...'
 (000.050593)  can0  1F5   [8]  0F 0D 00 00 00 00 03 00   '........'

5. 发送与接收

RPi 2B: CAN总线通信 - 通过OBD-II接口获取车辆信息

6. 路由及转发

待续

  • 显示kernel模块mcp251x相关信息及参数的值

我们知道MCP2515对应的linux kernel module的名字为mcp251x,我们可以通过modinfo来查看这个模块的相关信息以及支持的参数列表,如:

pi@raspberrypi:/home $ modinfo mcp251x
filename:       /lib/modules/4.4.11+/kernel/drivers/net/can/spi/mcp251x.ko
license:        GPL v2
description:    Microchip 251x CAN driver
author:         Chris Elston <celston@katalix.com>, Christian Pellegrin <chripell@evolware.org>
srcversion:     B646E18E95C132179C02575
alias:          of:N*T*Cmicrochip,mcp2515*
alias:          of:N*T*Cmicrochip,mcp2510*
alias:          spi:mcp2515
alias:          spi:mcp2510
depends:        can-dev
intree:         Y
vermagic:       4.4.11+ mod_unload modversions ARMv6 
parm:           mcp251x_enable_dma:Enable SPI DMA. Default: 0 (Off) (int)

从这里可以看到这个模块支持一个参数,这时如果我们想知道这个模块在当然运行的kernel对应的值,可通过systool这个命令查看,在raspbian系统中,这个工具需要安装:

$ sudo apt-get install sysfsutils

安装完后通过如下命令查看:

pi@raspberrypi:~ $ systool -vm mcp251x
Module = "mcp251x"

  Attributes:
    coresize            = "9598"
    initsize            = "0"
    initstate           = "live"
    refcnt              = "0"
    srcversion          = "B646E18E95C132179C02575"
    taint               = ""
    uevent              = <store method only>

  Parameters:
    mcp251x_enable_dma  = "0"

  Sections:
    .ARM.exidx.exit.text= "0xbf1195c4"
    .ARM.exidx.init.text= "0xbf1195b0"
    .ARM.exidx          = "0xbf119504"
    .ARM.extab.exit.text= "0xbf1195b8"
    .ARM.extab          = "0xbf119414"
    .ARM.extab.init.text= "0xbf1195a4"
    .bss                = "0xbf119dc0"
    .data               = "0xbf119b80"
    .exit.text          = "0xbf1193d4"
    .gnu.linkonce.this_module= "0xbf119be0"
    .init.text          = "0xbf11c000"
    .note.gnu.build-id  = "0xbf1193f0"
    .rodata             = "0xbf1195cc"
    .rodata.str1.4      = "0xbf119a18"
    .strtab             = "0xbf11cab4"
    .symtab             = "0xbf11c024"
    .text               = "0xbf118000"
    __mcount_loc        = "0xbf119b30"
    __param             = "0xbf119b1c"
  • 相关的参考文档:
  1. https://hacktronics.co.in/rs232485-usb-ttl-converters/mcp2515-can-bus-module-tja1050-receivers-spi-protocol
  2. http://qiita.com/mt08/items/535ab4690eecbcf5375d
  3. http://qiita.com/suzutsuki0220/items/8642b1c3ea51859a95ad
  4. http://qiita.com/suzutsuki0220/items/7cfdeb334efa4ffe3070

发表评论

电子邮件地址不会被公开。 必填项已用*标注