13. STM32-透过SPI驱动MCP2515实现CAN(上)

STM32内建已经有CANBus了~这篇主要是练习SPI并透过MCP2515去实现CanBus通讯!

先来介绍一下MCP2515模组,他已经将MCP2515与TJA1050整合起来了,可以直接透过SPI去做驱动!
https://ithelp.ithome.com.tw/upload/images/20220318/20146325YJuiWKDGzK.png
接下来我们来先看一下这块模组的DataSheet看看到底要如何使用它来实现CANBus通讯!


传送

https://ithelp.ithome.com.tw/upload/images/20220318/20146325Z8aGufuh50.png
这一段提到在发送之前至少需要将TxBnSIDH、TxBnSIDL、TxBnDLC写入对应位元,假设有资料要发送则需要将TxBnDm填入要发送的资料,同时将TXBnSIDL.EXIDE设为1。

下方的Note则提到发送之前需要将TXBnCTRL.TXREQ设为0(代表目前没有正在等待发送的资料)

接下来看看有关於传送到底有那些暂存器吧~

  1. TXBnCTRL :发送缓冲器n控制暂存器,MCP2515具有3个发送缓冲器(TxB0-TxB2),主要设置优先权与触发传送。可以看到当中bit3为TXREQ再传送时须将此位设1,并在发送後会自动清0。
    https://ithelp.ithome.com.tw/upload/images/20220318/20146325Ky4kTww7sg.png
  2. TXBnSIDH/TXBnSIDL/TXBnEID8/TXBnEID0 : 这边则是设置ID的部分拉,也就是上一篇所提到仲裁码设置,SIDH与SIDL是标准格式(CAN2.0A)的ID设置,假设要使用扩展格式(CAN2.0B)则将SIDL当中EXIDE位设置为1,并将後续EID8与EID0填入资料就可以拉~
    https://ithelp.ithome.com.tw/upload/images/20220318/20146325Ee7w4khbBR.png
    https://ithelp.ithome.com.tw/upload/images/20220318/20146325cp3lNBuwCM.png
    https://ithelp.ithome.com.tw/upload/images/20220318/20146325AGOSTZyVl2.png
    https://ithelp.ithome.com.tw/upload/images/20220318/20146325Cn8OvEMkPG.png
  3. TXBnDLC : 资料长度暂存器用来写入资料长度or是否为远端框架。依据後续data资料选择填入对应的资料长度,若为远端框架则将RTR位设置为1。
    https://ithelp.ithome.com.tw/upload/images/20220318/20146325z5gQ3sX4Sl.png
  4. TXBnDm0-TXBnDm7 : 传送资料暂存器,如果传送讯息中带有资料,则将所要传送的资料写入此暂存器,并将对应资料量填入上方DLC当中。
    https://ithelp.ithome.com.tw/upload/images/20220318/20146325fwbwSsOnh2.png

接收

再MCP2515当中有两个接收Buffer,分别是RXB0跟RXB1会优先使用RXB0来做接收。
https://ithelp.ithome.com.tw/upload/images/20220318/20146325ZbGUNz1ZOm.png
上方图片为手册当中说明如何接收,当接收到资料时会将CANINTF.RXnIF位设置为1,代表着接收到讯息并触发中断,这部分必须要由MCU再次将它设置为0才可以接收下一笔讯息。

接着同样来看看与接收相关的暂存器有哪些吧!

  1. RXB0CTRL : 接收缓冲控制暂存器,用来设定接收讯息的条件与是否可接受滚存。(滚存为当RXB0已存在讯息时,下一条讯息不管条件为何皆由RXB1先接收)
    https://ithelp.ithome.com.tw/upload/images/20220318/20146325vUWqIQ83oC.png
  2. RXBnSIDH/RXBnSIDL/RXBnEID8/RXBnEID0 : 接收仲裁码暂存器,当接收讯息时会将该讯息的ID写入,依照标准与扩展格式分别填入。要注意这四个Register只提供读而已!
    https://ithelp.ithome.com.tw/upload/images/20220318/20146325XuddwRQeQj.png
    https://ithelp.ithome.com.tw/upload/images/20220318/20146325gee2yqPXNb.png
    https://ithelp.ithome.com.tw/upload/images/20220318/20146325qzTr7Eb1uH.png
    https://ithelp.ithome.com.tw/upload/images/20220318/20146325E71sqMvLPG.png
  3. RXBnDLC :接收资料长度暂存器,同样只能做读取,在接收到资料时可以依照此暂存器查看是否会RTR以及该笔讯息所带资料长度。
    https://ithelp.ithome.com.tw/upload/images/20220318/20146325tCnPPw5pGz.png
  4. RXBnDm: 接收资料暂存器,当有资料接收时依照上方DLC长度来将资料陆续写入此暂存器,同样仅提供读取而已。
    https://ithelp.ithome.com.tw/upload/images/20220318/20146325gajWjTqCDM.png

Mask 与 Filter设置

前一篇文有提到CANBus在接收讯息时会需要验证ID、Mask与Filter来确定资料是否接收。

在MCP2515当中同样需要去做设定~建议在做测试时将Mask通通设定为0即可!

Mask Bit n Filter Bit n Message Identifier Bit Accept or Reject Bit n
0 x (任意值) x (任意值) Accept
1 0 0 Accept
1 0 1 Reject
1 1 0 Reject
1 1 1 Accept

Filter相关暂存器

  1. RXFnSIDH/RXFnSIDL/RXFnEID8/RXFnEID0 : 同样依照是选择标准格式还是扩展格式来选填,标准格式只需填入RXFnSIDH/RXFnSIDL扩展格式则须写入4个暂存器。
    https://ithelp.ithome.com.tw/upload/images/20220318/20146325h09o6haevG.png
    https://ithelp.ithome.com.tw/upload/images/20220318/20146325YBB8tBuaTx.png
    https://ithelp.ithome.com.tw/upload/images/20220318/20146325kVvihz9A1Y.png
    https://ithelp.ithome.com.tw/upload/images/20220318/20146325fZdIEgb0WH.png

Mask相关暂存器

  1. RXMnSIDH/RXMnSIDL/RXMnEID8/RXMnEID0 : 与上方Filter设定方式相同,建议在Mask当中填入0去做测试,方便接收所有ID讯息。
    https://ithelp.ithome.com.tw/upload/images/20220318/20146325ibGboOBWGM.png
    https://ithelp.ithome.com.tw/upload/images/20220318/20146325NQa6AslJJ7.png
    https://ithelp.ithome.com.tw/upload/images/20220318/20146325g9SaDqKXRD.png
    https://ithelp.ithome.com.tw/upload/images/20220318/20146325ANZo35zmRr.png

BIT TIMING

CANBus当中所有节点都必须以相同的Nominal Bit rate进行通讯,但不是所有的节点设备都具有相同的系统时钟频率,所以需要去Prescaler去对单位时间(TQ)做调整已达到相同的Nominal Bit rate。
https://chart.googleapis.com/chart?cht=tx&chl=NBR%20%3D%20fbit%20%3D%201%20%2Ftbit
https://chart.googleapis.com/chart?cht=tx&chl=tbit%20%3D%20tsyncSeg%20%2B%20tPropSeg%20%2B%20tPS1%20%2B%20tPS2
https://ithelp.ithome.com.tw/upload/images/20220318/2014632575xFcOIrSx.png
PropSeg : 补偿节点间的物理传输延迟时间,可设定1-8TQ

PS1与PS2 : 补偿Bus上的边缘相位误差,其中PS1可设定1-8TQ PS2可设置2-8TQ

如何计算TQ

https://chart.googleapis.com/chart?cht=tx&chl=TQ%20%3D%202%20*%20BRP%20*%20TOSC%20%3D%202%20*%20%20(BRP%2B1)%20%2F%20FOSC
BRP : Bit rate 预分频器

同步

  1. 硬同步 : Bus在空闲状态时发生1→0的跳变边沿状况时进行应同步
  2. 再同步 : 可能会导致PS1延长orPS2缩短,由SJW(同步跳转宽度)决定,会有以下三种情况(PS1 = PS1+SJW PS2 = PS2-SJW),SJW可设定1-4TQ
  • 不发生再同步 : 当Input Single 发生跳变(1→0)在同步区段当中(SyncSeg),则无相位误差无须调整。
    https://ithelp.ithome.com.tw/upload/images/20220318/20146325mRZAJ40NWR.png
  • 与较慢的发送设备再同步 : 当Input Single 发生跳变(1→0)大於同步区段(SyncSeg)且误差为正,则PS1加上SJW。
    https://ithelp.ithome.com.tw/upload/images/20220318/20146325fV4vVyoLj5.png
  • 与较快的发送设备再同步 : 当Input Single 发生跳变(1→0)大於同步区段(SyncSeg)且误差为负时,则PS2减去SJW。
    https://ithelp.ithome.com.tw/upload/images/20220318/201463255bCfvwJJIM.png

设置时间段时应注意

  1. PropSeg + PS1 ≥ PS2
  2. PropSeg + PS2 ≥Tdelay
  3. PS2>SJW

相关暂存器设置

  1. CNF1 : bit6-7为同步跳转宽度(SJW),通常设置为1-2TQ bit5-0则为预分频系数设置。
    https://ithelp.ithome.com.tw/upload/images/20220318/20146325rGEBa0mBtW.png
  2. CNF2 : 设置PropSeg 、PS1与采样位置,当SAM设置为0采样一次1则为3次采样点位置应该位於60%-90%
    https://ithelp.ithome.com.tw/upload/images/20220318/20146325HlcTCnze17.png
  3. CNF3 : 设置SOF与PS2
    https://ithelp.ithome.com.tw/upload/images/20220318/20146325aas6n4T3Iv.png
    EX : 假如FOSC = 16M BRP=7 且希望得到BRT为125kbps

1.可以得知tbit = 1/125kpbs = 8us(SyncSeg + PropSeg + PS1 +PS2 = 8TQ)

2.TQ = 2 * (7+1) / 16M = 1us (这时则会在CNF1中填入0x07)

接着CNF2当中的bit 7 (BTLMODE)选择1,也就是由CNF3去决定PS2长度

3.SyncSeg固定为1TQ 而PropSeg也选择 1TQ,这时已有2TQ则代表PS1与PS2共为6TQ,希望采样点落在大约60~90%之间,可以选择PS1为3 or 4TQ。

假设为3则是(1+1+3)/8TQ=62.5% ; 4则为(1+1+4)/8TQ = 75%。

4.若选择PS1 = 3TQ则CNF2应该填入0x90

5.根据上方Sync = 1 Prop = 1 PS1 = 3,所以PS2 = 3。这时CNF3可以填入0x02


中断

  1. CANINTE 中断致能暂存器 : 可以选择开启哪一类型中断,0位禁止1为开启。在测试时我们会使用RXB0去做接收,可以开启RXB0接收中断。
    https://ithelp.ithome.com.tw/upload/images/20220318/20146325yuo7PBFwgX.png
  2. CANINTF 中断旗标暂存器 : 当触发中断後会将该对应中断设为1表示出发中断,当处理完後需要手动设置为0清除中断旗标,以RXB0来说当接收完毕讯息需要在手动清0。
    https://ithelp.ithome.com.tw/upload/images/20220318/20146325oMUZakjrPX.png

工作模式

有五种工作模式分别为设置、正常、休眠、监听、环回

当需要对ID Mask Filter做设置时,一定要进入设置模式才可以做修改,修改完毕後需要退出设置模式。手边有两组设备的话可以透过正常模式去做测试与接收,只有一组可以利用环回模式进行测试。

  1. CANCTRL : CAN控制暂存器用来设置工作模式
    https://ithelp.ithome.com.tw/upload/images/20220318/201463255k1WE0y79j.png
  2. CANSTAT : CAN状态暂存器,可以用来查看目前所属工作模式与中断状况
    https://ithelp.ithome.com.tw/upload/images/20220318/20146325j0EpORLWsj.png

SPI 指令

这边介绍几个较常使用的SPI指令,其余可以参考手册当中说明。
https://ithelp.ithome.com.tw/upload/images/20220318/20146325QvLYHrnTGm.png

  1. Reset : 直接透过SPI发送0xC0即可进入配置模式
  2. Read : 可以看到下图优先将CS拉低後,透过MOSI传送0x03(读指令)接着接上要读取的暂存器地址,即可透过MISO获得该暂存器资料。
    https://ithelp.ithome.com.tw/upload/images/20220318/20146325OKTFV3Fcop.png
  3. BYTE WRITE : 向指定暂存器写入一个byte,指令後方接上写入地址与写入资料
    https://ithelp.ithome.com.tw/upload/images/20220318/20146325H84B5fmluT.png
  4. REQUEST-TO-SEND (RTS) :请求发送指令,当资料装载完毕後透过此指令可以发送讯息,其中T2 T1 T0分别为对应3个TxBuffer。
    https://ithelp.ithome.com.tw/upload/images/20220318/20146325wx32Goh7d0.png

这一篇主要介绍MCP2515 如何去做使用以及详细的设置说明,下一篇会介绍如何撰写MCP2515的程序码~
以上参考资料来源 : MCP2515 DataSheet


<<:  UVA练习

>>:  关於 物件(Object)与类别(class)

第 9 集:RWD 响应式

此篇会着重在 Bootstrap 5 响应式的介绍以及使用方法。 RWD 响应式网页设计 (Res...

Day 27. B2E-密码加密

还记得第2天在做专案规划时,有提到一个目标「加密敏感资料实现资安管理」吗? 目前我们的密码还是一样...

Scala 语言和你 SAY HELLO!!

第十九天 各位点进来的朋友,你们好阿 小的不才只能做这个系列的文章,但还是希望分享给点进来的朋友,知...

Day 10 - React-JSX

今天一样是语法糖的练习,而且我想把日期塞进去 (感谢 sololearn 的 David Carro...

[FHIR 从入门到放弃] Day 01-简介

在开始之前 前言 其实本来是没想到要写这篇的,毕竟平常生活跟工作已经够忙碌QQ 由於目前主要研究的是...