你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

嵌入式CAN总线

[复制链接]
gaosmile 发布时间:2020-10-29 19:23
嵌入式的工程师一般都知道CAN总线广泛应用到汽车中,其实船舰电子设备通信也广泛使用CAN,随着国家对海防的越来越重视,对CAN的需求也会越来越大。这个暑假,通过参加苏州社会实践,去某船舶电气公司实习几周,也借此机会,学习了一下CAN总线。

  ~: J4 u0 U% K7 J+ D0 g9 y
▍概述# k, R6 f5 r: ^) s. L6 a: D
CAN(Controller Area Network)即控制器局域网,是一种能够实现分布式实时控制的串行通信网络。  ], I% ?4 A4 X2 \: @7 V
想到CAN就要想到德国的Bosch公司,因为CAN就是这个公司开发的(和Intel)CAN有很多优秀的特点,使得它能够被广泛的应用。比如:传输速度最高到1Mbps,通信距离最远到10km,无损位仲裁机制,多主结构。1 T# T6 H/ s6 I0 ~5 K! c
近些年来,CAN控制器价格越来越低,很多MCU也集成了CAN控制器。现在每一辆汽车上都装有CAN总线。3 S+ i$ E3 n/ w9 s/ ?5 g
一个典型的CAN应用场景:
+ {: {7 G$ ]7 k
微信图片_20201029191520.png + R7 |3 ]( H6 B' Y8 ?7 I* i: D
▍CAN总线标准
1 `. ^( Z- I1 c( \& Z+ B
CAN总线标准只规定了物理层和数据链路层,需要用户自定义应用层。不同的CAN标准仅物理层不同。 微信图片_20201029191523.png 3 i( y- C5 ~6 B8 |! ^% r
CAN收发器负责逻辑电平和物理信号之间的转换。
2 [; \0 J8 D$ I  O$ Z' E
微信图片_20201029191526.png
: H" x0 K* Y- m' F; L: ]
将逻辑信号转换成物理信号(差分电平),或者将物理信号转换成逻辑电平。CAN标准有两个,即IOS11898和IOS11519,两者差分电平特性不同。" C4 f0 U$ g* n3 \; Z: ~: [
微信图片_20201029191530.png 高低电平幅度低,对应的传输速度快;
1 n9 \& \- ?6 ?2 m0 c$ L
微信图片_20201029191533.png 微信图片_20201029191537.png , z2 ]& I" S  p7 m' e: J# K! `- p
*双绞线共模消除干扰,是因为电平同时变化,电压差不变。
! C5 T# d" _/ h- z
物理层
" O- i# G! F- p7 ?; G' ~4 ?5 {3 U
CAN有三种接口器件$ U! L4 @2 a! d% ?* }
微信图片_20201029191540.png 微信图片_20201029191543.png
) e( X! w) K% r! {" V( L
多个节点连接,只要有一个为低电平,总线就为低电平,只有所有节点输出高电平时,才为高电平。所谓"线与"。
# L$ B/ ]! L; v$ C1 A
CAN总线有5个连续相同位后,就插入一个相反位,产生跳变沿,用于同步。从而消除累积误差。
& E* z. O! q! N% {& l1 z
和485、232一样,CAN的传输速度与距离成反比。
# T0 s; i3 G8 @" d
微信图片_20201029191546.png $ j. K8 D% F( j, R  Y! v
CAN总线,终端电阻的接法:
! r9 S3 r, v! w
微信图片_20201029191550.png 0 g+ p  i$ Y3 d. [
为什么是120Ω,因为电缆的特性阻抗为120Ω,为了模拟无限远的传输线$ Z  B' @# }: o% @- o
数据链路层
9 }; _/ t+ T; m2 E2 \; P
CAN总线传输的是CAN帧,CAN的通信帧分成五种,分别为数据帧、远程帧、错误帧、过载帧和帧间隔。
! r$ E0 ?% u% ]+ ^8 t& x
数据帧用来节点之间收发数据,是使用最多的帧类型;远程帧用来接收节点向发送节点接收数据;错误帧是某节点发现帧错误时用来向其他节点通知的帧;过载帧是接收节点用来向发送节点告知自身接收能力的帧;用于将数据帧、远程帧与前面帧隔离的帧。
5 _/ b. \" [1 E8 x3 v& ]& c; a
数据帧根据仲裁段长度不同分为标准帧(2.0A)和扩展帧(2.0B)
; [# j' y8 ~/ X, n1 H: z7 B; W
帧起始

3 q7 D! V& d2 U" v) Z1 u2 [7 B
微信图片_20201029191553.png
+ D# u; h! T$ k( z( b& ^! T+ ?) k
帧起始由一个显性位(低电平)组成,发送节点发送帧起始,其他节点同步于帧起始;/ @% ]0 E, w2 K! g
帧结束由7个隐形位(高电平)组成。6 S6 D7 W2 h  Q3 a  S; Y  |
仲裁段
! o8 ?: u5 Q( A- Q  p. `8 `  p
CAN总线是如何解决多点竞争的问题?2 s+ g, ]8 R- f+ T/ s* E
由仲裁段给出答案。
+ f' K5 T! u. ~& J% e& o+ {
CAN总线控制器在发送数据的同时监控总线电平,如果电平不同,则停止发送并做其他处理。如果该位位于仲裁段,则退出总线竞争;如果位于其他段,则产生错误事件。
% F& N+ B8 [8 E" H) _+ o
微信图片_20201029191557.png
* f1 K$ [+ z8 y& h! T0 ?$ T6 I
帧ID越小,优先级越高。由于数据帧的RTR位为显性电平,远程帧为隐性电平,所以帧格式和帧ID相同的情况下,数据帧优先于远程帧;由于标准帧的IDE位为显性电平,扩展帧的IDE位为隐形电平,对于前11位ID相同的标准帧和扩展帧,标准帧优先级比扩展帧高。
" G! i2 z8 }# g8 E+ k3 @! T$ b8 P
控制段. l3 h3 n) b% N( [$ s) y% C" `& G
共6位,标准帧的控制段由扩展帧标志位IDE、保留位r0和数据长度代码DLC组成;扩展帧控制段则由IDE、r1、r0和DLC组成。 微信图片_20201029191600.png 数据段为0-8字节,短帧结构,实时性好,适合汽车和工控领域; 微信图片_20201029191603.png ! R) E- ^) {/ E, D
CRC段
8 }' B) \; O! Q: N4 q& x
CRC校验段由15位CRC值和CRC界定符组成。 微信图片_20201029191606.png
  ?- a4 `$ h/ _
ACK段: U. r! s- A2 j8 P3 p$ ^3 C
当接收节点接收到的帧起始到CRC段都没错误时,它将在ACK段发送一个显性电平,发送节点发送隐性电平,线与结果为显性电平。  H& G1 ^* Z3 h) v2 {4 {! i# u
远程帧
) ~7 `, l, t7 k) c& g) l1 R) G
远程帧分为6个段,也分为标准帧和扩展帧,且RTR位为1(隐性电平)
- d9 y. @8 U2 k9 e
微信图片_20201029191610.png
9 U7 ~" B9 }3 K& k6 _- M
CAN是可靠性很高的总线,但是它也有五种错误。! A( D' c0 @* U& [' n
CRC错误:发送与接收的CRC值不同发生该错误;格式错误:帧格式不合法发生该错误;应答错误:发送节点在ACK阶段没有收到应答信息发生该错误;位发送错误:发送节点在发送信息时发现总线电平与发送电平不符发生该错误;位填充错误:通信线缆上违反通信规则时发生该错误。
+ P, v; Y* k/ T% v
当发生这五种错误之一时,发送节点或接受节点将发送错误帧
7 }$ }  f# y  @6 U( w$ Z
为防止某些节点自身出错而一直发送错误帧,干扰其他节点通信,CAN协议规定了节点的3种状态及行为
1 `: S  z6 ^. h7 q7 n8 b: c1 L" Z$ }
微信图片_20201029191613.png
0 ]6 V: @/ I4 V3 ^8 j
过载帧( a# j. f. P" U9 V" I2 W
当某节点没有做好接收的"准备"时,将发送过载帧,以通知发送节点。9 f/ o1 B1 b  _" o3 B
微信图片_20201029191617.png
) }5 i6 A6 ^' |' |
帧间隔
/ l1 C5 d+ Z+ K/ k
用来隔离数据帧、远程帧与他们前面的帧,错误帧和过载帧前面不加帧间隔。, }+ s3 _, D7 l& f
微信图片_20201029191620.png 1 ?2 J% B. S  U/ i! n5 u; a' o7 l( ^
构建CAN节点
3 v/ i. [5 k% Y7 S/ O+ e
构建节点,实现相应控制,由底向上分为四个部分:CAN节点电路、CAN控制器驱动、CAN应用层协议、CAN节点应用程序。
$ V8 u6 b* Y4 v1 V" w2 B) V
虽然不同节点完成的功能不同,但是都有相同的硬件和软件结构。  h. Q: N- r$ T( F9 C
微信图片_20201029191623.png CAN收发器和控制器分别对应CAN的物理层和数据链路层,完成CAN报文的收发;功能电路,完成特定的功能,如信号采集或控制外设等;主控制器与应用软件按照CAN报文格式解析报文,完成相应控制。
# x/ Q4 G% P+ A8 T) g
CAN硬件驱动是运行在主控制器(如P89V51)上的程序,它主要完成以下工作:基于寄存器的操作,初始化CAN控制器、发送CAN报文、接收CAN报文;
+ |9 N7 e4 p9 F  ~9 ^! |. T5 `
如果直接使用CAN硬件驱动,当更换控制器时,需要修改上层应用程序,移植性差。在应用层和硬件驱动层加入虚拟驱动层,能够屏蔽不同CAN控制器的差异。7 b- z4 P% K/ ^  z; `" h' f
一个CAN节点除了完成通信的功能,还包括一些特定的硬件功能电路,功能电路驱动向下直接控制功能电路,向上为应用层提供控制功能电路函数接口。特定功能包括信号采集、人机显示等。
& y" x* m4 ^' @+ [7 f% m; p
微信图片_20201029191627.png
8 t" m5 e( X5 B
CAN收发器是实现CAN控制器逻辑电平与CAN总线上差分电平的互换。实现CAN收发器的方案有两种,一是使用CAN收发IC(需要加电源隔离和电气隔离),另一种是使用CAN隔离收发模块。推荐使用第二种。& N0 X4 @9 e/ S2 z0 a7 U
CAN控制器是CAN的核心元件,它实现了CAN协议中数据链路层的全部功能,能够自动完成CAN协议的解析。CAN控制器一般有两种,一种是控制器IC(SJA1000),另一种是集成CAN控制器的MCU(LPC11C00)。
6 t0 H0 _$ I* ~, s) A! {
MCU负责实现对功能电路和CAN控制器的控制:在节点启动时,初始化CAN控制器参数;通过CAN控制器读取和发送CAN帧;在CAN控制器发生中断时,处理CAN控制器的中断异常;根据接收到的数据输出控制信号;" l2 I6 B; e: ?
微信图片_20201029191630.png
; d* d( c# m7 O5 {/ j( ]
接口管理逻辑:解释MCU指令,寻址CAN控制器中的各功能模块的寄存器单元,向主控制器提供中断信息和状态信息。% b- }# {! c  {6 o
发送缓冲区和接收缓冲区能够存储CAN总线网络上的完整信息。
$ Z0 B9 b  q6 F+ h9 ^2 |, l& ^
验收滤波是将存储的验证码与CAN报文识别码进行比较,跟验证码匹配的CAN帧才会存储到接收缓冲区。
0 ]  G- ]# E3 Q. f2 t
CAN内核实现了数据链路的全部协议。
2 |& ~' b' e  n+ m. I6 n
▍CAN协议应用层概述& B+ v3 D  X5 O) e8 q# s
CAN总线只提供可靠的传输服务,所以节点接收报文时,要通过应用层协议来判断是谁发来的数据、数据代表了什么含义。常见的CAN应用层协议有:CANOpen、DeviceNet、J1939、iCAN等。6 h( ^, V8 K1 ^1 C
CAN应用层协议驱动是运行在主控制器(如P89V51)上的程序,它按照应用层协议来对CAN报文进行定义、完成CAN报文的解析与拼装。例如,我们将帧ID用来表示节点地址,当接收到的帧ID与自身节点ID不通过时,就直接丢弃,否则交给上层处理;发送时,将帧ID设置为接收节点的地址。
1 [1 \# G( V) l$ l4 B
CAN收发器
6 G6 ~; V2 R+ \+ _' a1 p1 [& e
SJA1000的输出模式有很多,使用最多的是正常输出模式,输入模式通常不选择比较器模式,可以增大通信距离,并且减少休眠下的电流。
" T6 K; a% X8 R& _+ w* D
微信图片_20201029191633.png
) P$ h8 L. e# N; C, H  t! N# @, f
收发器按照通信速度分为高速CAN收发器和容错CAN收发器。
9 D# b( G* l8 n3 t6 ]
同一网络中要使用相同的CAN收发器。0 i# x) ]6 K1 w* {* o; P+ Z5 o. C
CAN连接线上会有很多干扰信号,需要在硬件上添加滤波器和抗干扰电路 微信图片_20201029191637.png
) g0 j) }4 p& h! _8 \3 w
也可以使用CAN隔离收发器(集成滤波器和抗干扰电路)。$ ~9 X+ j( e  x6 ~7 u, f
微信图片_20201029191640.png 微信图片_20201029191643.png ; Z4 b; i- a: k/ l  z
CAN控制器与MCU的连接方式/ M- a9 L# N- P- [0 `
微信图片_20201029191646.png
9 \4 q$ R" P/ s2 ~
SJA1000可被视为外扩RAM,地址宽度8位,最多支持256个寄存器
# c1 ?9 r8 Q$ ]
微信图片_20201029191650.png 微信图片_20201029191652.png
  • 3 X3 {9 H9 E6 Y: [* O
#define REG_BASE_ADDR 0xA000 // 寄存器基址  B: d9 P0 u" r( U! H/ q3 L
unsigned char *SJA_CS_Point = (unsigned char *) REG_BASE_ADDR ;- [7 w  K) y" v
// 写SJA1000寄存器! \/ r4 ?. W8 u" W# N: x. _  r% [# f
void WriteSJAReg(unsigned char RegAddr, unsigned char Value) {
1 e$ c: X" d( l7 [
*(SJA_CS_Point + RegAddr) = Value;4 I. Z  K$ H$ E1 n8 {
return;8 t" J  `$ i) q( o% j3 d
}
! l" l, A) u$ g3 v. i7 C- I3 I( }3 F
// 读SJA1000寄存器: S8 i& e& I2 W5 _1 ^
unsigned char ReadSJAReg(unsigned char RegAddr) {
9 O6 @  a, c/ W( U+ H$ o9 @3 x
return (*(SJA_CS_Point + RegAddr)); }
7 z) ]8 N' P" S5 n9 Y9 H$ X- N( e
微信图片_20201029191710.png 微信图片_20201029191714.png 将缓存区的数据连续写入寄存器8 K4 h5 k8 t: q* `% w
  • $ `- z5 _  W5 [4 }9 ~, o
…… for (i=0;i<len;i++) { WriteSJAReg(RegAdr+i,ValueBuf);  }……1 Y4 c, j6 q! e! y3 i
将连续多个寄存器连续读入缓存区' k5 g( w" ^. Z1 C

  • 0 a/ F* O. p$ c3 n
…… for (i=0;i<len;i++) {  ReadSJAReg(RegAdr+i,ValueBuf);   }……
+ Q) D) n/ W) d; y
微信图片_20201029191717.png 头文件包含方案:
  • 每个程序包含用到的头文件
  • 每个程序包含一个公用头文件,公用头文件包含所有其他头文件7 o7 V3 d7 k9 h" `

, W* I% H3 l8 s
  • ! J2 q8 q8 {  ^# U" s: z7 @0 r
#ifndef __CONFIG_H__ // 防止头文件被重复包含* ^: d& x6 r$ V
#define __CONFIG_H__
0 `5 {- F1 _! y- r' z: ?5 w/ m
#include <8051.h>         // 包含80C51寄存器定义头文件2 [! U! r- ^' N* F6 s
#include "SJA1000REG.h"         // 包含SJA1000寄存器定义头文件
% ~8 O9 q. I& [* ]& q
// 定义取字节运算2 Z% ?9 m# O2 d/ h8 @) n
#define LOW_BYTE(x)  (unsigned char)(x)* n6 J( r0 P" _* q1 q
#define HIGH_BYTE(x)  (unsigned char)((unsigned int)(x) >> 8)' ]3 w; s* S1 t
// 定义振荡器时钟和处理器时钟频率(用户可以根据实际情况作出调整); d* }/ T" p) \# x$ W9 e
#define OSCCLK 11059200UL+ E# T" H; J8 r  H3 b5 {
// 宏定义MCU的时钟频率; t0 `7 {# K% ]! n2 F
#define CPUCLK (OSCCLK / 12)
' ~* r8 D& ]# y( a: o; ]$ U
#endif // __CONFIG_H__SJA1000上电后处于复位状态,必须初始化后才能工作。(1)置位模式寄存器Bit0位进入复位模式;(2)设置时钟分频寄存器选择时钟频率、CAN模式;(3)设置验收滤波,设定验证码和屏蔽码;(4)设置总线定时器寄存器0、1设定CAN波特率;(5)设置输出模式;(6)清零模式寄存器Bit0位退出复位模式;8 b' a/ n8 @: ~
模式寄存器
, v' p: ]8 U! y. S
微信图片_20201029191719.png 只检测模式:SJA1000发送CAN帧时不检查应答位;
% n; I+ ~6 ?  p& _) J
只听模式:此模式下SJA1000不会发送错误帧,用于自动检测波特率;SJA1000以不同的波特率接收CAN帧,当收到CAN帧时,表明当前波特率与总线波特率相同。
/ C( O" ~  i, V, r
波特率设置6 ^* e5 x" u- Y1 W
CAN总线无时钟,使用异步串行传输;波特率是1秒发送的数据位;' Q' Z2 U5 v3 i( O2 ^
微信图片_20201029191725.png CAN帧发送:
8 P5 s# j7 l& h% @
发送CAN帧的步骤:
3 Y9 a4 t* F! [2 N6 t% [/ v1.检测状态寄存器,等待发送缓冲区可用;
2.填充报文到发送缓冲区;3.启动发送。 微信图片_20201029191728.png SJA1000具有一个12字节的缓冲区,要发送的报文可以通过寄存器16-28写入,也可通过寄存器96-108写入或读出 微信图片_20201029191731.png 微信图片_20201029191734.png 设置发送模式! {  j4 ^. t  U4 B0 v: ~9 i
  • " @7 Z  M- @( \3 v* ]* K
char SetSJASendCmd(unsigned char cmd) {
, d$ h& U* X( j: g5 Z* Y& i. g5 R8 W1 \
    unsigned char ret;+ a7 `( [2 `( Z- W9 _. |/ S
    switch (cmd) {8 o, L. q) U! n7 h2 R
    default:( n" p4 l9 j  N4 q; e/ H9 |  F: E2 P
    case 0:- t! Z& b) P$ ]) h3 |
        ret = SetBitMask(REG_CAN_CMR, TR_BIT); //正常发送
; P0 P$ L4 m5 E3 D4 T8 ~+ \9 P- X
    break;
2 \5 y4 n1 |: A- V6 F; T
    case 1:
2 g! J" |% g1 I7 S1 p
        ret = SetBitMask(REG_CAN_CMR, TR_BIT|AT_BIT); //单次发送# P+ Q$ r; ]. J; S+ B) r
    break;0 z- L9 F! I$ l& p
    case 2:
# F3 a! i4 U4 _
        ret = SetBitMask(REG_CAN_CMR, TR_BIT|SRR_BIT);//自收自发
' Q) J: ^; a4 \; ^
    break;  m- N/ l  a0 p! P& y! v9 P
    case 0xff:; B! ~. N* Z0 b: f1 R
        ret = SetBitMask(REG_CAN_CMR, AT_BIT);//终止发送( w( H' x1 A4 m: l
    break;- S" _& o& r4 ^; D7 |7 l
    }" s% g( v1 c* g# c6 ]9 f
    return ret;6 T5 P- i2 o; O# x
}2 a$ K3 g8 Z0 x) R2 R
发送函数" p  f$ _2 V/ \; c
  • 3 a, U/ h/ K- D3 Z
unsigned char SJA_CAN_Filter[8] = {    // 定义验收滤波器的参数,接收所有帧       8 y+ Q: \. F% `! K9 ]
0x00, 0x00, 0x00, 0x00,                                                0 g+ ^0 z! E% N1 ]0 m: M
// ACR0~ACR3      
1 P2 p2 o& E. t7 B  x/ a
0xff, 0xff, 0xff, 0xff                                                         2 f1 o" K3 D# r+ g2 {
// AMR0~AMR3: I8 \7 x' L% o6 H- l; W3 P2 `1 a, ?
};) R! o1 ?; _$ G. c5 w
unsigned char STD_SEND_BUFFER[11] = {   // CAN 发送报文缓冲区      
7 [; _. S% M; K* y* e
0x08,   // 帧信息,标准数据帧,数据长度 = 8       ) s' ?1 M  @- N2 q% f. y
0xEA, 0x60, // 帧ID = 0x753/ g( y0 D" Y% c6 X9 p
0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa  // 帧数据( q; {, j6 B9 n1 ]2 h  r& }" J
};6 }, c0 @' e! ?  {" K
void main(void) // 主函数,程序入口{      
) ?1 U* L6 G) ^8 t: t6 [* q
    timerInit();// 初始化
* M) R3 ?; t+ e6 A; {
    D1 = 0;       ' a: c& ^- o' }2 x7 G* H
    SJA1000_RST = 1; // 硬件复位SJA1000       9 I+ s1 V6 E, h! Y7 S5 @
    timerDelay(50); // 延时500ms      
/ d7 f. @* E# K0 u, ~
    SJA1000_RST = 0;       7 R1 D. A" L% j
    SJA1000_Init(0x00, 0x14, SJA_CAN_Filter);   // 初始化SJA1000,设置波特率为1Mbps      
. ~8 W4 g: C) A! @. c& T) [
    // 无限循环,main()函数不允许返回      9 j3 U. ^& S! O. g% |2 K
    for(;;) {           ' ~) g! r8 [' ~9 b) M* n
        SJASendData(STD_SEND_BUFFER, 0x0);           7 ?2 l' H# F  ~' i4 R+ y  C
        timerDelay(100);         // 延时1000ms      1 ?- e/ v- L# M1 o# M& b
    }    & x% n6 `% V6 o4 U7 K! L, r; I
} 为什么帧ID是0x753,这与CAN帧在缓冲区的存储格式有关。 微信图片_20201029191737.png 微信图片_20201029191740.png 终端电阻非常重要,当波特率较高而且没加终端电阻时,信号过冲非常严重。 微信图片_20201029191743.png SJA1000有64个字节的接收缓冲区(FIFO),这可以降低对MCU的要求。MCU可以通过查询或中断的方式确定SJA1000接收到报文后读取报文。2 H" c/ Q* f1 Q2 J/ Y( ]  R
赞 收藏 评论0 发布时间:2020-10-29 19:23

举报

0个回答
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版