CAN总线(Controller Area Network Bus),从名字上可以知道,CAN总线构建的是一种局域网网路,每个挂载在CAN总线上的设备都可以利用这个局域网去发送自己的消息,也可以接收局域网的各种消息,每个设备都是平等的,都在共享这个局域网的通信资源,这就是CAN总线的设计理念。
CAN总线特征:
1、两根通信线(CAN_H、CAN_L),线路少,无需共地,因为是差分信号。(比如说I2C通信,它也只有两根通信SCL、SDA,但是I2C是单端信号,必须得共地。所以实际上I2C,至少得3根线)
2、差分信号通信,CAN_H和CAN_L就是一对差分线,差分线的好处就是抗干扰能力强,比单端信号传输的抗干扰能力强。如果线路产生干扰,则一般两根线的电压都会同时出现波动。但是,两根线的电压差值,仍然是不变的,所以用这个电压差值来传递数据,就能极大的避免干扰。
3、目前CAN总线分为两种标准:
高速CAN(在国际标准中叫ISO11898),其传输速率为125k~1Mbps,传输距离<40m
低速CAN(在国际标准中叫ISO11519),其传输速率为10k~125kbps,传输距离<1km
可以看出高速CAN传输快,但是距离较短。低速CAN传输慢,但是距离很远
4、异步,无需始终线,通信速率由设备各自约定。(这一点和串口非常相似)
5、半双工(不可以同时发送和接收),可挂载多设备,多设备同时发送数据时通过仲裁判断先后顺序。(也就是让大家排好队,消息都是可以发出去的)
6、11位/29位报文ID,用于区分消息功能,同时决定优先级(ID号小的优先发送)。11位是标准格式,29位是扩展格式
7、CAN总线的一个数据帧,可配置1~8字节的有效载荷。(这个类比串口,串口一次只能发送1个字节)
8、可实现广播式和请求式两种传输方式:
广播式就是一个设备发送数据,其他所有设备都能收到。然后接收方根据报文ID,来决定用不用这个数据。大概的场景就是,发送方说:管你们要不要,我反正把数据发出去了,你们谁要谁拿走。
请求式就是数据发送方不会主动广播自己的数据,而是只有收到接收方发出的请求,发送方才会发数据。这样一个数据的传输就需要先请求、再接收。一来一回两个过程,这就是请求式。
应答、CRC校验、位填充、位同步、错误处理的实验现象
这个图绿色的是TJA1050(CAN收发模块),GND与STM32共地。VCC需要5V供电,接到STLINK的5V引脚,TXD接PA12,RXD接PA11.三个节点都这么接。最后把每个CAN收发器的CANH接在一起,CANL接在一起。
上图甚至可以在CAN总线上挂更多的设备,每个设备都可以广播发送自己的数据,其他设备都可以收到这个数据。
另外,CAN总线还能配置为请求式传输。我请求你了,你才发数据,这样也行。
同时,每个设备还可以配置过滤器来有选择地进行接收,我只接受我关注的消息,无关消息我可以直接过滤掉。
主流通信协议对比:
SPI的传输速率是最快的
在我看来,CAN总线就是UART和I2C的结合体
CAN硬件电路
每个设备通过CAN收发器挂载在CAN总线网络上
CAN控制器引出的TX和RX与CAN收发器相连,CAN收发器引出的CAN_H和CAN_L分别与总线的
CAN_H和CAN_L相连。(一定要有CAN收发器)
CAN总线里走的都是差分信号,一般会用双绞线作为载体,避免干扰。
高速CAN使用闭环网络,CAN_H和CAN_L两端添加120欧的终端电阻,使CAN总线形成一个闭合的环路,加这两个终端电阻,主要的作用有两个。
第一个是防止回波反射,尤其是高频信号、远距离传输的场景的场景,回波反射是不能忽略的问题。关于回波反射的具体原因,可以学一学“传输线理论”。这里仅解释现象,如果不加终端电阻。
信号波形会在线路终端反射,进而干扰原始信号。当信号跳变时,它会在边沿震荡几下,这会干扰数据的正确传输。如下图所示。如果加了终端电阻且阻抗匹配,则信号的跳变会变得平稳。
第二个作用就是在没有设备操作时,将两根差分线的电压“收紧”,使其电压一致。(这里用了一个比较直白的词“收紧”,它的意思是在没有设备操作总线的情况下,这个电阻就像一根弹簧一样,会将两根线的电压拉到同一水平)。
这一点其实和I2C的上拉电阻一样,默认拉高至高电平,当有设备想发送0时,就把线路强制拉低至低电平;当有设备发送1时,不是把线路强制拉高至高电平,而是不去碰这个线路。线路由上拉电阻,默认拉高至高电平。这样的好处是,可以防止电平冲突。同时这还能实现“线与”的特性,对总线仲裁,十分重要。所以这个上拉电阻也类似一个弹簧
低速CAN使用开环网络,CAN_H和CAN_L其中一端添加2.2k欧的终端电阻。
CAN电平标准
CAN总线采用差分信号,即两线电压差传输数据位
高速CAN规定:
电压差为0V时表示逻辑1(隐形电平)
电压差为2V时表示逻辑0(显性电平)
低速CAN规定:
电压差为-1.5V时表示逻辑1(隐形电平)
电压差为3V时表示逻辑0(显性电平)
CAN总线帧格式
CAN协议规定了以下5种类型的帧:
数据帧
它的用途是,发送设备主动发送数据,属于广播式的通信方式。比如按下某个设备的按键,这个设备就会向CAN总线广播式地发出一个消息,这个消息,也可以叫做报文(Message),它的承载格式,就是数据帧。
看一下这个图,它定义了数据帧的格式,数据帧有标准格式和扩展格式两种。扩展格式增加了ID位数,能承载更多种类的ID。
数据帧各部分用途简介
遥控帧
遥控帧无数据段,RTR为隐性电平1,其他部分与数据帧相同
帧相隔
将数据帧和远程帧与前面的帧分离开
错误帧
总线上所有设备都会监督总线的数据,一旦发现“位错误”或“填充错误”或“CRC错误”或“格式错误”或“应答错误”,这些设备便会发出错误帧来破坏数据,同时终止当前的发送设备。
过载帧
当接收方收到大量数据而无法处理时,其可以发出过载帧,延缓发送方的数据发送,以平衡总线负载,避免数据丢失。
位填充
位填充规则:发送方每发送5个相同电平后,自动追加一个相反电平的填充位,接收方检测到填充位时,会自动移除填充位,恢复原始数据。
位填充作用:
1、增加波形的定时信息,利于接收方执行“再同步”,防止波形长时间无变化,导致接收方不能精准掌握数据采样时机。
2、将正常数据流与“错误帧”和“过载帧”区分开,标志“错误帧”和“过载帧”的特异性
3、保持CAN总线在发送正常数据流时的活跃状态,防止被误认为总线空闲
波形实例
看一下用示波器捕捉到的CAN波形
使用方法是,用示波器的两个探头,夹子一端,都与其中一个STM32共地;探头一端分别接在CAN_H线和CAN_L线,这样测得的就是CAN_H和CAN_L的对地电压,显示出来的,就是差分电平表示。
然后按下按键,STM32发出一个指定的帧。这是,CAN_H和CAN_L就会产生这样一段波形
发送数据之前CAN总线一直处于两线收紧的空闲状态。
开始发数据帧时,要把两线张开,发送显性0,表示SOF,打破空闲。
一个帧开始,总线也进入占用状态。
SOF之后,根据标准数据帧的定义,首先发送报文ID,因为ID是0x555,转化为2进制就是0000 0101 0101 0101,
因为ID只有11位,所以这里就呈现101 0101 0101这样的波形
然后下一位是RTR,RTR的波形是张开状态,显性0,所以表示当前是数据帧
然后IDE是显性0,表示标准数据帧
R0保留位,必须是0。这是因为在仲裁时,0的优先级更高。之后如果用到了这个保留位,可以保证,当前定义的优先级高于以后拓展定义的优先级。就像IDE一样,因为之前保留位r1默认是0,所以现在就有标准帧高于拓展帧优先级这个特性
之后是4位DLC。同时我们也发现,产生了一个填充位,因为前面已经连续出现5个0了,所以强行插入了一个1。
这个填充位在实际波形中会体现,但是在解析数据帧时要移除填充位,实际上只需要分析4位,即0001,表示DLC的值是0x1
DLC之后就是数据段了。因为DLC是1,所以数据段只有一个字节。
依次判定数据位是1010 1010,表示数据内容是0xAA。同时也可以发现,CAN总线是高位先行的。
数据段结束,是15位的CRC段。发送时,CRC可以由CAN控制器自动生成。
接收时,也可以由CAN控制器自动校验
之后是CRC界定符,它的作用是在ACK槽之前,发送方释放总线。
如果没有CRC界定符,我们看到CRC的最后一位是显性0,如果直接跟ACK槽,那发送方还拽着总线,接收方没法发送应答位
之后,总线控制权短暂交接给接收方,发送方在ACK槽期间不会碰总线。
如果有接收方,接收方会在ACK槽拉开总线,接收方会在ACK槽拉开总线,只要有一个设备拉开了总线,总线必定呈现显性0状态
这里看一看到有接收方应答了
之后应答结束,是ACK界定符,接收方会在这一位期间释放总线,交出总线控制权,当然发送方也是释放状态。
最后7位EOF都是隐性1,默认