使用Xilinx FPGA完成CAN总线的收发控制(一)
如需原工程文件,请留言索取.
1-1概况说明
CAN(Controller Area Network,控制器局域网)由德国 Bosch 公司提出,最早出现在上世纪80年代末的汽车工业中.当前广泛应用于汽车电子、工业控制、智能家居等领域,从协议的层面看,CAN总线协议完全定义了协议的各个层面.其中多主机机制,仲裁机制,实时性等特别适合汽车系统,工业自动化等方面的应用.比如多主机机制,允许连接至总线的各个系统都可以主动占用总线发送信息,同时CAN总线为了这种多主机机制定义了总线仲裁协议.从物理层面来看,CAN总线使用差分信号,可靠性高,抗干扰能力强.
1-2实验设计
本实验设计了一个FPGA控制CAN总线收发的模块.首先使用测试电脑上的CAN总线测试软件向总线发送一个远程帧,FPGA收到此远程帧后返回一个数据帧.
1-3技术背景
本章节以本实验使用到的CAN总线的相关背景知识做介绍.
(1) 物理层---显性电平,隐形电平
[1] 先从概念上介绍一下显性电平和隐性电平.显性电平(dominant),隐性电平(recessive)指的是CAN总线差分信号上的电平准位.电平准位一般称为高低电平,为什么在CAN协议中又定义为显性电平和隐形电平?这个含义是由CAN总线多主机机制决定的,通过一个主机发送的数据位是显性还是隐性来仲裁哪个主机的优先级高.,比如两个主机同时向总线发送数据位,一个主机发送显性位(向总线发送显性电平),而另一个主机发送隐性位(向总线发送隐性电平), 那么此时总线的电平实际呈现显性电平准位,可以认为隐性位遇到显性位就被取代消失.这也是字面上显和隐的含义. 发送隐性位的主机同时也在侦测总线,发现此时总线上并不是其发送的隐性电平,而是被显性电平覆盖(取代),此主机马上判定当前有优先级更高的主机需要占用总线,此主机随即退出总线竞争.
[2]再来看下显性电平和隐性电平的电气定义
<1>CAN总线只有一对差分信号,CANH和CANL.
<2>向CAN总线发送数据1时,则CANH和CANL两个信号电平均为中间电平,那么接收端接收到的电平为CANH-CANL=0V.即接收端接收差分信号为0V,则判定收到数据1;
<3>向CAN总线发送数据0时,则CANH为3.5V,CANL为1.5V,那么接收端接收到的电平为CANH-CANL=2V.即接收端接收差分信号为2V,则判定收到数据0;
<4>如果一个主机向CAN总线发送数据1,另一个主机向CAN总线发送数据0.那么CANH依然为3.5V,CANL依然为1.5V.这是由CAN总线收发器的电气设计决定的. 那么接收端接收到的电平仍然为CANH-CANL=2V.即接收端接收差分信号为2V,则判定收到数据0.也就是说数据1遇到数据0就被取代了,显而易见,数据0就是显性位,数据1就是隐性位.
(2)CAN协议帧的类型和定义,CAN协议共定义5种帧.分别为数据帧(Data frame), 遥控帧(Remote frame), 错误帧(Error frame), 过载帧(Overload frame), 帧间空间(Inter-frame space).
在本实验中涉及到数据帧和遥控帧,下面介绍一下这两种帧的定义和含义.
[1]数据帧,发送单元向接收单元发送数据的帧.
SOF:帧起始. 此位为数值0(显性位).
仲裁段:
<1>总线上每个设备都有预先设定的11bits ID.在CAN总线数据传输时,每个设备根据接收到的ID值来判定此数据是否是发给自己.除了身份识别,总线仲裁也在这一阶段完成,所以此阶段称为仲裁段.根据上述关于隐性位和显性位性质的描述,一个ID位为0的主机优先级大于一个ID位为1的主机.这也是定义总线上各设备ID的原则,优先级高的主机使用数据0来定义.
<2>RTR:数据帧此位为0,遥控帧此位为1.
控制段:
<1>IDE:此位为数值0.
<2>R0:预留位.协议约定预留位默认值为数值0.
<3>DLC:4bits数据长度.指明后续数据段的字节长度.如后续字节段需发送1个字节长度的数据,则此处DLC的值为4’d0001.
数据段:
支持1-8字节数据,数据长度需与DLC字段声明的一致.
CRC段:
<1>15bits的CRC校验数据.CRC校验的范围含从SOF至数据段最后一个bit. CAN总线协议中推荐了实现的算法,本实例CRC算法依照协议推荐编写verilog代码.
<2>CRC界定符:此位为数值1.
ACK段:
此段分为两bit.
第一个bit预留给接收机作为反馈信号.发送主机此时发送数据1,也就是隐性位.接收机在此处反馈数据0,也就是显性位.根据前述显性位和隐性位的说明,CAN 总线将呈现显性位电平.发送机此刻识别到总线是显性位,判定接收机接收正常.若识别到隐性位,判定接收机接收不正常.
第二个bit发送机发送数值1.
EOF段:结束段固定位7’b111_1111.
以上,总结如下图.
[2]遥控帧,某主机请求另一个ID的主机发送数据的帧. (遥控帧没有数据段)
SOF:帧起始. 此位为数值0(显性位).
仲裁段:
<1>总线上每个设备都有预先设定的11bits ID.在CAN总线数据传输时,每个设备根据接收到的ID值来判定此数据是否是发给自己.除了身份识别,总线仲裁也在这一阶段完成,所以此阶段称为仲裁段.根据上述关于隐性位和显性位性质的描述,一个ID位为0的主机优先级大于一个ID位为1的主机.这也是定义总线上各设备ID的原则,优先级高的主机使用数据0来定义.
<2>RTR:数据帧此位为0,遥控帧此位为1.
控制段:
<1>IDE:此位为数值0.
<2>R0:预留位.协议约定预留位默认值为数值0.
<3>DLC:4bits数据长度.指明请求目的主机发送的数据段的字节长度.如请求目的主机发送1个字节长度的数据,则此处DLC的值为4’d0001.
CRC段:
<1>15bits的CRC校验数据.CRC校验的范围含从SOF至DLC段最后一个bit.
<2>CRC界定符:此位为数值1.
ACK段:
此段分为两bit.
第一个bit预留给接收机作为反馈信号.发送主机此时发送数据1,也就是隐性位.接收机在此处反馈数据0,也就是显性位.根据前述显性位和隐性位的说明,CAN 总线将呈现显性位电平.发送机此刻识别到总线是显性位,判定接收机接收正常.若识别到隐性位,判定接收机接收不正常.
第二个bit发送机发送数值1.
EOF段:结束段固定位7’b111_1111.
以上,总结如下图.
(3)位同步的概念.
通过上述的介绍,很显然可以看出CAN总线类似于UART总线,都属于异步传输的总线.异步传输的总线总是要考虑前后两个主机系统同步的问题.显然,两个都连接在CAN总线上的主机,除了都连接在总线上,其余没有任何关系,包括数字系统最重要的时钟信息.
如果在这样的总线上传输数据,那么如何收发呢?按照最简单的想法,不考虑位同步的概念,我们会怎么做?答案也很简单,就按照类似UART总线收发的方式.接收端在一旦接收到由高到低的SOF位,那么就启动接收流程.接收端按照传输速率约定(比如100kbps),自行计时并确定每个bit的时长,计时到了就切换到下一个bit接收. 这样的方式在UART端口中常常使用.
但是这样的方式有一个缺点,收主机没有考虑和发主机的之间存在的时钟系统误差.发主机按照自己的时钟系统计时,确定每个bit的位宽等时间参数.而收主机按照自己的时钟系统计时,确定自己的每个bit的位宽等时间参数.那么这两个时间系统一定会有时间参数误差,比如不同的时钟jitter或偏移.随着接收的位数越来越多,那么这种误差可能会累积.可能因为误差累积,接收端取样点已经不再位于数据位的中心位置,而已经移动到数据位前沿或后沿这些数据不稳定的状态,导致数值取样错误.更严重可能会出现接收端的计时计数系统认为当前是第n位,而实际发送端发送的是n-1或n+1位.
CAN总线因为使用环境传输可靠性要求高.为避免出现上述收发系统的位偏移,提出了位同步的概念.
CAN协议中建议动态调整接收端对于数据位宽的时间参数,而非上述固定的数据位宽.接收端识别到发送端时钟的偏移对于其发送的数据位宽的影响,而动态的调整接收端的计时计数,避免两个系统的时钟误差.
具体实现方案如下.
[1]发送端依然依照其时钟系统发送数据.由接收端来完成位同步的操作.
[2]信号的高低变化总是一个数据的开始,接收端利用此时刻进行同步.下一次再遇到接收到信号高低变化时刻,再利用此时刻进行同步.
[3]接收端接收到SOF段信号从高到低的变化沿,作为第一个同步沿.这在协议中称为硬同步.从这个变化沿作为第一个定位点,开始计时和计数,确定每个数据位的位宽.后面的数据如果是连0,那么就没有数据变化沿作为同步参考.直到再次出现数据由高到低的变化.(当然,数据由低到高也能作为同步沿,只是协议中建议使用数据由高到低的变化沿作为同步沿).可以看出,如果长时间数据无变化,那么接收端就始终没有数据变化沿作同步的确认,也就相当于没有接收端位同步的机制.如果这样,就又回到上面提到的两个主机设备独立的时钟系统可能造成的问题.为了避免这种连0或者连1造成同步信息缺少的情况,CAN协议要求发送端在出现五个连0或连1时加入一个数值相反位,有意的增加数值的变化沿.这个加入的数据位称为填充位stuffbit.关于这一部分将在下一小节介绍.
[4]上一小段提到接收端使用EOF段作为第一个同步沿(起始沿),并作为内部时钟计数和计时的开始.那么在下一个数据由高到低的变化沿到来时,接收端的正在进行的位宽计时状态和这个变化沿的关系可能会呈现三种可能:
<1>第一种可能,接收端与发送端的位时序仍然一致.
先介绍几个相关的概念,参看下图.为了完成位同步,调整位时序,在一个数据位的时长里面定义四个段.分别为同步段(Synchronization Segment),传播段(Propagation Segment), 相位缓冲段1(Phase Buffer Segment1), 相位缓冲段2(Phase Buffer Segment2).
每个数据段中的最小区间都是固定的,称为Tq.比如下图中ss段有一个Tq,PTS段有三个Tq等.一个bit时长中,具体拥有几个Tq,在不同的设计中并不完全相同.在每个具体的设计中,需要提前确定好.
同步段:同步成功的数据位变化沿应该落在这个区间.
传播段:指的是数据从发送端发送到总线上,并传输到接收端的时间.显然,数据的取样点应该在这个时间阶段之后.
相位缓冲段1,相位缓冲段2:如果数据变化沿没有落在接收端的位时序中同步段SS,那么就调整相位缓冲段1,相位缓冲段2的时长来使得下一个bit的位同步正确.请参考后续说明.
图中标明了取样点位置,在PBS1阶段结束的时刻.这个位置相对的位于一个bit的中心位置,是数值准位稳定的状态,所以协议规定取样点在此时刻.
显然,在这种情况下,接收端的位时序和发送端是一致的,双方并没有因为独立时钟系统而造成位时序的偏移,在图示取样点位置可以正确取样.
<2>第二种可能,接收端的位时序提前于发送端.
下图中,发送端使用其内部的时钟系统发送数据,接收端使用其内部的时钟系统计时接收数据.但是双方的时钟系统有偏差,接收端的时钟计时稍快于发送端.导致发送端位起始已经处于接收端位时序的PTS(或PBS1)段.这种状态下,取样点已经偏离理想位置.如果不做重新的同步,偏差继续累积,那么取样点会移动到数据不稳定的起始甚至是其他bit.所以在设计中,一旦识别到数据的变化沿落在(PTS+PBS1)段,那么就临时增加PBS1段Tq的数量.目的是使下一位收发的SS段处于同步状态. Tq调整的数量在协议中定义为同步跳转宽带(SJW),通常为1或者2.比如图示中就是2个Tq(一次调整两个Tq的时长).在本实例中,代码中使用的方法是调整1个Tq.如果是图示这种状况,需要做两次同步才能达到SS段对齐的目标.
在这个描述中也可以看出,CAN总线位时序的同步总是需要数据准位的变化沿,这也是为什么CAN协议需要填充位的原因.如果没有数值准位反转的填充位,那么一组数据,有可能出现连0或连1的情况,这种情况下没有同步参考,有可能因为累积时钟误差而导致取样错误.
<3>第三种可能,接收端的位时序落后于发送端.
下图中, 发送端的时钟计时稍快于接收端.导致发送端位起始SS段处于接收端位时序的PBS2段(请留意,是前一位的PBS2段).这种状态下,取样点已经偏离理想位置.在设计中,一旦识别到数据的变化沿落在PBS2段,那么就减少当前位PBS2段Tq的数量.目的是使下一位收发的SS段处于同步状态. Tq调整的数量在协议中定义为同步跳转宽带(SJW),通常为1或者2.比如图示中就是2个Tq(一次调整两个Tq的时长).在本实例中,代码中使用的方法是调整1个Tq.如果是图示这种状况,需要做两次同步才能达到SS段对齐的目标.
图示中,重同步成功之后的位时序采样点位于理想正确位置.
在以上两个小节中,可以看出,PBS1和PBS2中的Tq数量是有可能临时调整的,所以称为相位缓冲段.请留意,PBS1和PBS2 Tq数量的调整,是临时的,是只在当前位时序中起效.在下一位就恢复默认值,如果后续再侦测到不同步的状态,那么就再次临时调整.
(4)填充位的概念.
在上一个小节中已经提到填充位.如果CAN总线的有效数据出现连续0或连续1的情况,那么接收端就没有数据变化沿作为同步的参考.所以协议中要求发送端一但识别到发送的数据出现5个连续0或连续1,就需要在第6位加入一个数值相反的填充位.
<1>加入的填充位本身也作为连续位的计算.比如出现了5个0,那么就在第6位加入数据”1”作为填充位.如果这个”1”填充位之后出现了4个数据”1”,那么包括填充位连续出现了5个”1”,就需要在下一位再加入填充位”0”.
<2>填充位不计入CRC的计算,CRC的计算只包含有效数据,不包括之前出现的任何填充位.
<3>填充位的有效时段不包括ACK段和EOF段.