昨晚很荣幸邀请到李工在RT-Thread微信群进行RT-Thread上的CAN驱动和应用讲座。小编整理了讲座内容,特发出讲义以供享用。
讲师:李起伟,任职于煤炭科学技术研究院有限公司,助理研究员,硕士,现主要从事嵌入式系统与煤矿安全监测监控系统的研究工作
分享主题:RT-Thread上的CAN驱动和应用
大家晚上好,今天跟大家探讨一下RTT上的CAN驱动和应用相关一些内容,主要有三个方面,第一项介绍一下CAN总线的基础知识,主要是一些帧格式的介绍。第二项是RTT上的CAN驱动的一个编写,这部分内容主要介绍一些CAN设备的读和写以及中断处理函数的驱动编写,中断处理函数主要说一下接收部分的处理。最后一项就是介绍一下CAN数据的处理现场的编写,整个内容都写得比较浅,然后在咱们这个探讨内容结束之后,我给大家发一个CAN总线的基础教程,然后另外我写的这部分驱动包括处理现场也是我在实际产品当中应用的,随后我把这部分内容的代码然后整理一下,之后也放出来。
我们就开始第一部分的内容,,说一下CAN的这个特性吧,在这个CAN的介绍当中会有跟这个modbus总线会有一些简单的对比,那么CAN总线它是一个多主站的结构,在总线上挂的这个所有的节点,他们的节点地位都是平等的,就是所有的节点都可以向总线当中主动地发送数据,不需要等待其他的节点的就是跟他发命令说我才可以往上发,这一点是跟modbus的区别,就是说modbus总线,他是一主多从的,在总线上只有一个主节点,其他节点都是从机,从机只能被动地根据主机的命令做出相应的回复或者是动作,当然这些节点再往总线上发送数据的时候会有一个优先级的问题。
在CAN总线当中,它有一个种CAN总线仲裁的机制,它主要是通过报文ID来实现的,那么在CAN总线当中执行的是“线与”操作,0是属于显性电平,1是隐性电平。这样的话进行限于之后报名ID越小,那么他在总线竞争当中优先级也就越高,报文ID或者说是这个标识符与这个节点的ID或者节点序号,这是两个完全不同的概念,就是在这个报名ID当中其实可以包,因为它在扩展的帧当中有29位,可以包含很多有意义的内容,你都可以帮放在这个标识符当中。
在这个标识符当中,我们可以把发送节点的序号类型、接受节点的序号类型甚至安装位置等一系列信息都包含在那里,所以说标识符它在一定程度上就描述数据的含义,这样的话就在某些特定应用当中可以对标识符进行过滤,就是说我需要的我才接受,不需要的我就可以过滤掉,然后这样的话CPU呢不需要进行参与一些操作,完全由CAN控制器就可以完成了。
modbus总线一些协议栈也可以对报文进行过滤,但是这是需要CPU进行参与的,这样的话就会占用CPU,也就是说当modbus总线上有数据的时候,所有节点都是要参与的,这样的话一旦modbus总线上有数据,所有的节点当前正在执行的任务都会被打断,所以这样的话也是CAN总线跟modbus总线的区别,或者是一点优势吧。
因为CAN总线是是一种差分电平,所以它使用那个双绞线作为它的总线传输介质,在1Mbps的情况下,总线长度一般会小于40米,我们看这个U线这张图,从现在传输速率跟它的传输距离在一定程度上是成反比例关系的,而我们在实际应用当中,曾经做到过在5Kbps的情况下达到了7到8公里,而且还是一种多分叉多分枝这种结构。总线结构比较复杂,而不是我们通常见的一条总线或母线,节点都单独的挂在这个总线路线上,在实际运用当中,这种情况其实很少见。 说一下CAN协议的版本,那么目前主要就是2.0B,是可以兼容11位和29位两种ID的报文,就是说标准帧和扩展帧都可以兼容,具体的协议内容大家可以去查阅一下相关的文档,这里就不再多说。 CAN总线当中主要的帧格式主要数据帧和远程侦。数据帧也分两种,就是标准帧和扩展帧,远程侦同样有对应的标准帧和扩展帧。 对这两种帧格式来简单地介绍一下,标准帧和扩展帧主要区别就是在帧ID的位数上,标准帧是11位ID,扩展帧是29位ID。我们看标准帧,它有一个隐性电平帧起始,之后是11位的帧ID,然后是一个RTR位,RTR位的意思是什么呢?远程传送请求位,那这位是0就是数据帧,1的话就代表远程帧,显性电平,也就是说数据帧的优先级要高于远程帧,那么在进行总线仲裁的时候,数据帧获得总线的控制权。用来区别标准帧和扩展帧的这位叫做标识符扩展位。0代表标准帧,1代表扩展帧。这样的话,当标准帧和扩展帧在进行争夺总线的时候,那肯定是标准帧获得总线控制权。
DLC位代表数据长度,一共四位,有效值是0—8,9到15没有效,他代表数据场,指后面的数据场里面一共有多少个字节能够被传送。再然后是15位CRC位,因为这个CRC校验的起始是从帧开始一直到数据场的结束,整个这一串的位数参加这个CRC校验。CRC检验完事之后是一个DR位,这位叫做CRC界定服务,到这里就表示CRC校验完事了,后面就是应答场。对于我们这个用户来说,在实际的编程应用当中,我们用户一般的需要做的其实是仲裁场以及控制场和数据场,上其他的CRC场场、ASK场均结束。一般不需要用户进行参与,这些都是由CAN控制器来自动完成的。
我们再来看扩展帧。扩展帧首先前面的11位帧ID先不,后面看RTR位后面。SR位与RTR位是在同一个位置上,RTR位叫做远程传送请求位,SR位叫做远程请求替代位,后面的部分就跟标准一样,这个就不再多。真正的RRT位被移送到了29位的帧ID的后面,那么SR位或者是RTR位在标准帧或者是在扩展帧当中,它也有高电平还是低电平。那么在标准帧当中同样的位RTR一定是显性电平,而在扩展帧当中这个一定是隐性电平。
再一下,远程帧。远程帧同样分为两种,就是根据这ID的位数不同,分为标准远程帧和扩展远程帧,我们看一下图上的这个RTR位,在这他就是一个隐形电平,就明他是一个远程帧, 远程侦和数据帧的主要区别就是在于除了这个RTR位之外,还有一个区别远程帧没有数据场,是不带数据的。 远程侦在总线的主要作用是什么呢?就是我们知道CAN总线是多主的,就是大家都是平等的,向总线上各自发送数据,这个就像我们在微信群里聊天一样,有人一直往这个群体方式发送一些消息。但是假如其中有人觉得你发送的消息不是我想要的,或者不满足我的要求那么怎么办呢?我就会主动给你请求数据,那么我就向你发送这个远程侦那。至于你向谁请求数据、请求的是什么数据,那我可以都可以包含在帧ID当中,而且也只能包含在帧ID当中,因为这个远程侦当中他没有数据场,你所有的数据的意义只能在帧I当中,也基本上就相当于你的那个数据的个性化定制吧。
在这点与modbus的0X03和0X06呢比较类似,相当于取多个或单个寄存器的数据命令,指主动的索取数据。这条命令,举一个应用的场合吧。比方在火灾预警的场合,一般现实的过程当中鉴定火灾的几个要素:一个是温度,一个是烟雾,另外一个是一氧化碳的浓度。烟雾传感器、一氧化碳传感器还有温度传感器,他们都是同样挂在一条CAN主线当中,假如现在监测到烟雾传感器烟雾浓度变大了,但是我们知道目前的烟雾传感器有一个最大问题对水蒸气特别敏感,即使水蒸气浓度很高,烟雾传感器就会误报警。那么为了确认当前确实是烟雾传感器误报警,还是确实发生了火灾,那么我们就要及时看到当前一氧化碳的浓度以及温度的情况。这时候我可以主动发送一个远程侦来索取一氧化碳传感器的数据以及温度传感器的数据,通过这几个传感器的数据进行综合的比较,或者是按照一定的算法,我们就可以知道现在是否确实发生了火灾,还是烟雾传感器进行了误报警。这样就可以防止一些不必要的误报警,因为误报警会有很多的问题。关于CAN的帧格式的一些介绍就简单介绍到这里。 下面就进入到RT-Thread上的CAN驱动的编写部分,一些刚接触到RTT的一些朋友,可能觉得这个学这个驱动比较困难,或者是不知道无从下手。
其实你看一下就是RTT上面现有的一些设备的驱动,比方串口的、SPI的等等一些现有设备的驱动,仔细揣摩一下,自带这个驱动都写得很规范,大家可以完全可以借鉴和模仿,那么这个驱动其实主要实现在这个图片上列出来这七个函数,我们能把这些函数都实现了,并且把设备注册到这个系统内核当中,这个设备的驱动也就基本完成。我今天讲的这个CAN的驱动是在1.2.3版本的串口驱动上改写的,当时的这个串口驱动跟现在还是有很大区别的,一会大家可以看一下。
未完,后续部分请看完整版PPT,录音文件以及源码。 (关于代码部分说明:由于是查询发送,所以不能充分利用can控制器的邮箱做缓存,发送速度上会有些限制。改成中断发送会非常好,一是可以利用CAN控制器的多个邮箱,另外可以使用用户自己开辟的缓存,有兴趣的朋友自己改吧)
|