CAN总线入门教程

如果之前学习过IIC和串口,就已经学会了一半。

想学习IIC请转到IIC协议(以STM32为例,软件iic,第一部分时序讲解,第二部分代码实现)

简介

1.CAN总线(Controller Area Network Bus)控制器局域网总线。

2.CAN总线是由BOSCH公司开发的一种简洁易用、传输速度快、易扩展、可靠性高的串行通信总线,广泛应用于汽车、嵌入式、工业控制等领域

3.CAN总线特征:

        1.两根通信线(CAN_H、CAN_L),线路少,无需共地

        2.差分信号通信,抗干扰能力强

        3.高速CAN(ISO11898):125k~1Mbps, <40m

        4.低速CAN(ISO11519):10k~125kbps, <1km

        5.异步,无需时钟线,通信速率由设备各自约定

        6.半双工,可挂载多设备,多设备同时发送数据时通过仲裁判断先后顺序

        7.11位/29位报文ID,用于区分消息功能,同时决定优先级

        8.可配置1~8字节的有效载荷

        9.可实现广播式和请求式两种传输方式

        10.应答、CRC校验、位填充、位同步、错误处理等特性

CAN硬件电路

        每个设备通过CAN收发器挂载在CAN总线网络上

        CAN控制器引出的TX和RX与CAN收发器相连,CAN收发器引出的CAN_H和CAN_L分别与总线的CAN_H和CAN_L相连

        高速CAN使用闭环网络,CAN_H和CAN_L两端添加120Ω的终端电阻

        低速CAN使用开环网络,CAN_H和CAN_L其中一端添加2.2kΩ的终端电阻

对于ISO11898(高速CAN)两根线中间有个120Ω的电阻,这两个电阻在空闲时间可以将两条线拉到同一电平(类似于IIC总线上的上拉电阻)。

对于ISO11519(低速CAN)接了两个2.2K的 电阻,并未连接到一块,他们空闲时间不是同一电平。

CAN电平标准

        CAN总线采用差分信号,即两线电压差(VCAN_H-VCAN_L)传输数据位

        高速CAN规定:

                电压差为0V时表示逻辑1(隐性电平)        

                电压差为2V时表示逻辑0(显性电平)

        低速CAN规定:

                电压差为-1.5V时表示逻辑1(隐性电平)

                电压差为3V时表示逻辑0(显性电平)

显性电平为0,隐性电平为1,这可能不好理解,但是可以对比IIC理解,上面我们讲到把CAN_H,CAN_L两条线接到一块的120Ω的电阻在空闲时可以把两条线拉到同一电平,相当于IIC外接4.7k的上拉电阻,对于IIC来说,空闲处于高电平,因为外接了上拉电阻,因此,对于can总线,我们可以理解为,因为电阻的拉力起了总用,各个设备间谁也没控制总线,处于空闲时间处于高电平。

 

这里补充一下,CAN收发器。

        对于RXD这条路,当外部设备释放CANH CANL 经电阻的拉力,把两条线的电平拉到同一水平,经过DECEIVER输出0(不要惊讶,后面好友极性反转),再往后,如果低电平上路导通,VCC把RXD拉高输出1,同理,高电平下路导通,GND把RXD拉低输出低电平。

        对于TXD这条路,当输入为1时,经DRIVER的控制,上下两路都断开,CANH有外部VCC拉高,CANL由外部GND拉低,这就形成了电压差。

CAN总线帧格式

CAN协议规定了以下五种类型的帧:

数据帧

数据帧各部分用途简介

        SOF (Start of Frame):帧起始,表示后面一段波形为传输的数据位

        ID(Identify):标识符,区分功能,同时决定优先级

        RTR(Remote Transmission Request ):远程请求位,区分数据帧和遥控帧

        IDE(Identifier Extension):扩展标志位,区分标准格式和扩展格式

        SRR(Substitute Remote Request):替代RTR,协议升级时留下的无意义位

        r0/r1(Reserve):保留位,为后续协议升级留下空间

        DLC(Data Length Code):数据长度,指示数据段有几个字节

        Data:数据段的1~8个字节有效数据

        CRC(Cyclic Redundancy Check):循环冗余校验,校验数据是否正确

        ACK(Acknowledgement):应答位,判断数据有没有被接收方接收

        CRC/ACK界定符:为应答位前后发送方和接收方释放总线留下时间

        EOF(End of Frame ):帧结束,表示数据位已经传输完成

数据帧的发展历史

        CAN 1.2时期,仅存在标准格式,IDE位当时仍为保留位r1

        

             CAN 2.0时期,ID不够用,出现了扩展格式,增加了ID的位数,为了区分标准格式与扩展格式,协议将标准格式中的r1赋予了新功能—IDE

        遥控帧

        遥控帧无数据段,RTR为隐性电平1,其他部分与数据帧相同

错误帧

总线上所有设备都会监督总线的数据,一旦发现“位错误”或“填充错误”或“CRC错误”或“格式错误”或“应答错误” ,这些设备便会发出错误帧来破坏数据,同时终止当前的发送设备

错误帧的错误标志为6位,是为了与位补充区分,后面会详细说到位补充

过载帧

        当接收方收到大量数据而无法处理时,其可以发出过载帧,延缓发送方的数据发送,以平衡总线负载,避免数据丢失

帧间隔

                将数据帧和遥控帧与前面的帧分离开

延迟传送(发送暂时停止)
8 个位的隐性位。
只在处于被动错误状态的单元刚发送一个消息后的帧间隔中包含的段。

 位填充

        位填充规则:发送方每发送5个相同电平后,自动追加一个相反电平的填充位,接收方检测到填充位时,会自动移除填充位,恢复原始数据

例如:

     即将发送:    100000110       10000011110    0111111111110          

     实际发送:    1000001110       1000001111100    011111011111010          

     实际接收:    1000001110       1000001111100    011111011111010          

    移除填充后: 100000110       10000011110    0111111111110

位补充的作用:

增加波形的定时信息,利于接收方执行“再同步”,防止波形长时间无变化,导致接收方不能精确掌握数据采样时机

将正常数据流与“错误帧”和“过载帧”区分开,标志“错误帧”和“过载帧”的特异性

保持CAN总线在发送正常数据流时的活跃状态,防止被误认为总线空闲

位时序

CAN总线没有时钟线,总线上的所有设备通过约定波特率的方式确定每一个数据位的时长

发送方以约定的位时长每隔固定时间输出一个数据位

接收方以约定的位时长每隔固定时间采样总线的电平,输入一个数据位

理想状态下,接收方能依次采样到发送方发出的每个数据位,且采样点位于数据位中心附近

接收方采样遇到的问题

接收方以约定的位时长进行采样,但是采样点没有对齐数据位中心附近

接收方刚开始采样正确,但是时钟有误差,随着误差积累,采样点逐渐偏离

为了灵活调整每个采样点的位置,使采样点对齐数据位中心附近,CAN总线对每一个数据位的时长进行了更细的划分,分为同步段(SS)、传播时间段(PTS)、相位缓冲段1(PBS1)和相位缓冲段2(PBS2),每个段又由若干个最小时间单位(Tq)构成

ss固定为1Tq,其他自己指定

 硬同步

        每个设备都有一个位时序计时周期,当某个设备(发送方)率先发送报文,其他所有设备(接收方)收到SOF的下降沿时,接收方会将自己的位时序计时周期拨到SS段的位置,与发送方的位时序计时周期保持同步

        硬同步只在帧的第一个下降沿(SOF下降沿)有效

        经过硬同步后,若发送方和接收方的时钟没有误差,则后续所有数据位的采样点必然都会对齐数据位中心附近

再同步

        若发送方或接收方的时钟有误差,随着误差积累,数据位边沿逐渐偏离SS段,则此时接收方根据再同步补偿宽度值(SJW)通过加长PBS1段,或缩短PBS2段,以调整同步

        再同步可以发生在第一个下降沿之后的每个数据位跳变边沿(在之前的为填充出现五个相同的数据会跳变,所以说位填充有利于再同步的执行)

swj=1~4Tq

波特率计算

波特率=1/一个数据位的时长 = 1 / (TSS + TPTS + TPBS1 + TPBS2)

例如:  

   SS = 1Tq,PTS = 3Tq,PBS1 = 3Tq,PBS2 = 3Tq   

    Tq = 0.5us

    波特率 = 1 / (0.5us + 1.5us + 1.5us + 1.5us) = 200kbps

仲裁

        CAN总线只有一对差分信号线,同一时间只能有一个设备操作总线发送数据,若多个设备同时有发送需求,该如何分配总线资源?

        解决问题的思路:制定资源分配规则,依次满足多个设备的发送需求,确保同一时间只有一个设备操作总线

 

 资源分配规则1--先占先得

        若当前已经有设备正在操作总线发送数据帧/遥控帧,则其他任何设备不能再同时发送数据帧/遥控帧(可以发送错误帧/过载帧破坏当前数据)

        任何设备检测到连续11(1个ack间隔符,7个结束帧,3个间隔帧)个隐性电平,即认为总线空闲,只有在总线空闲时,设备才能发送数据帧/遥控帧

        一旦有设备正在发送数据帧/遥控帧,总线就会变为活跃状态,必然不会出现连续11个隐性电平,其他设备自然也不会破坏当前发送

        若总线活跃状态其他设备有发送需求,则需要等待总线变为空闲,才能执行发送需求

资源分配规则2--非破坏性仲裁

        若多个设备的发送需求同时到来或因等待而同时到来,则CAN总线协议会根据ID号(仲裁段)进行非破坏性仲裁,ID号小的(优先级高)取到总线控制权,ID号大的(优先级低)仲裁失利后将转入接收状态,等待下一次总线空闲时再尝试发送

        实现非破坏性仲裁需要两个要求:

                线与特性:总线上任何一个设备发送显性电平0时,总线就会呈现显性电平0状态,只有当所有设备都发送隐性电平1时,总线才呈现隐性电平1状态,即:0 & X & X = 0,1 & 1 & 1 = 1

                回读机制:每个设备发出一个数据位后,都会读回总线当前的电平状态,以确认自己发出的电平是否被真实地发送出去了,根据线与特性,发出0读回必然是0,发出1读回不一定是1(若回读不是自己发送的电平,则仲裁失利,则主动退出,当然只有发送1时,两根线在120Ω的作用下处于同一电平(隐形电平1),当其他设备输出0时,这时,这个设备读入电平为0,1>0所以是设备号大的设备后占用总线)

非破坏性仲裁过程

        数据位从前到后依次比较,出现差异且数据位为1的设备仲裁失利

     

        数据帧和遥控帧ID号一样时,数据帧的优先级高于遥控帧(RTR位数据帧位0,遥控帧为1(ID号与RTR一起组成仲裁帧))

 标准格式和扩展格式的优先级

标准格式11位ID号和扩展格式29位ID号的高11位一样时,标准格式的优先级高于扩展格式(SRR必须始终为1,以保证此要求)

此设计非常巧妙,不得不说发明CAN总线的人真是个天才

此时问题又来了  当扩展格式的数据帧与标准格式的遥控帧比较时,此时标准格式的仲裁帧已经过去,是否会出现差错呢?

答案是当然不会,对比他们的格式不难发现,标准格式的下一位IDE为0,而扩展格式为1,因此还是标准格式遥控帧先占据总线,不得不说这个过程实在是太惊险了,此时不得不提,发明CAN        总线的人真是个天才。

错误类型

错误共有5种: 位错误、填充错误、CRC错误、格式错误、应答错误

错误状态

 主动错误状态的设备正常参与通信并在检测到错误时发出主动错误帧

被动错误状态的设备正常参与通信但检测到错误时只能发出被动错误帧

总线关闭状态的设备不能参与通信

每个设备内部管理一个TEC和REC,根据TEC和REC的值确定自己的状态

 

波形示例 

设备处于主动错误状态,发送标准数据帧,正常传输

设备处于主动错误状态,发送标准数据帧,检测到ACK错误

设备处于被动错误状态,发送标准数据帧,检测到ACK错误

(上文也有提到,帧间隔处)
延迟传送(发送暂时停止)
8 个位的隐性位。
只在处于被动错误状态的单元刚发送一个消息后的帧间隔中包含的段。
CAN总线通信中,缓冲区是指用于临时存储待发送或已接收的CAN数据帧的内存区域,缓冲区的大小可以影响CAN数据的发送和接收效率。CAN总线通信中的缓冲区分为发送缓冲区和接收缓冲区。 - 发送缓冲区:用于存储待发送的CAN数据帧。当发送数据时,数据会先被写入发送缓冲区,然后由CAN总线发送出去。如果发送缓冲区已满,则无法发送新的数据。 - 接收缓冲区:用于存储已接收的CAN数据帧。当CAN总线接收到数据时,数据会先被写入接收缓冲区,然后由CAN控制器触发中断,通知主控制器有新的数据到来。如果接收缓冲区已满,则新的数据会被丢弃。 在CAN总线通信中,缓冲区的大小可以影响CAN数据的发送和接收效率。如果缓冲区太小,则会导致发送或接收频率过高,影响系统的稳定性;如果缓冲区太大,则会占用过多的内存空间,影响程序的性能。因此,需要根据实际需求进行调整,一般建议设置适当的缓冲区大小,避免缓冲区溢出或资源浪费。 在使用CAN总线进行通信时,可以通过设置CAN控制器的寄存器来控制发送缓冲区和接收缓冲区的大小。具体的设置方式和寄存器地址等信息,需要根据所使用的CAN控制器型号和芯片手册进行设置。同时,也可以通过使用第三方的CAN通信库,如`python-can`等,在Python程序中设置发送缓冲区和接收缓冲区的大小。例如,在使用`python-can`库进行CAN通信时,可以使用`can.interface.Bus`类的构造函数中的`tx_buffer_size`和`rx_buffer_size`参数来设置发送缓冲区和接收缓冲区的大小。例如: ```python import can # 创建CAN总线对象,设置发送缓冲区和接收缓冲区的大小为50 bus = can.interface.Bus(bustype='socketcan', channel='can0', tx_buffer_size=50, rx_buffer_size=50) # 发送CAN数据 msg = can.Message(arbitration_id=0x123, data=[0x01, 0x02, 0x03]) bus.send(msg) # 接收CAN数据 msg = bus.recv() ``` 以上代码中,`tx_buffer_size`和`rx_buffer_size`参数的默认值都为10,可以根据实际需求进行调整。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值