CAN驱动程序编程

简介: CAN驱动程序编程

学习之路,长路漫漫,写学习笔记的过程就是把知识讲给自己听的过程。这个过程中,我们去记录思考的过程,便于日后复习,梳理自己的思路。学习之乐,独乐乐,不如众乐乐,把知识讲给更多的人听,何乐而不为呢?


项目中解决的问题


CAN与串口操作基本类似,主要就是读写操作。但除此之外,CAN还多了一个报文过滤器的设置。利用7个CAN协议驱动实现VI,编写出几乎所有场合下都能使用的CAN通信程序。


做题思路


(1)CAN初始化

CAN初始化函数CAN Init.vi主要用来设置CAN通信速率、发送模式以及引脚重映射,如图

00a9d9c311d64c5f8bbbf31d82dea56e.png

其中,STM32中的bxCAN属于高速CAN,最大支持1MHz的波特率,为了用户的使用方便,我们提供了5Kbps~1Mbps共23档选择;发送方式有“正常发送”与“环回模式”,当用户只有一块My_ARM学习板或一个CAN节点时,可以使用“环回模式”进行自发自收,来验证程序的功能性是否合理。当然,如果有多个CAN节点相互通信时,选择“正常模式”即可。

其实,CAN的3种映射分别与USB、SDIO(TIM4)、LCD重合,因此,如果用户想要完全独立地使用CAN总线接口,需要舍弃其中一项,比如USB或者SD卡,然后再将CAN映射到与之对应的物理引脚上。

My_ARM学习板上默认使用的是PB8和PB9引脚,虽然与SDIO部分引脚重合,但是我们提供的SD卡驱动采用的是SPI串行通信,并非SDIO并行通信,因此,刚好可以避开。

(2)CAN过滤器设置

一个CAN节点想要接收指定特征的报文,就需要提前设置过滤器,只有满足条件的报文才能顺利通过。CAN过滤器函数CAN Filter Set.vi需要设置的参数有以下6类:接收的是数据帧还是远程帧(回读命令);ID号有多少位,是标准帧还是扩展帧;启用哪个过滤器(范围:Filter0~13);想要接收的报文ID号;ID屏蔽位(U32),就是确定接收到的报文中的ID号、帧类型,哪些位是必须与前面设置的参数完全一致还是可不关心,如果设置成0xFFFFFFFF,表示外部发送过来的报文必须与过滤器中预期设置的参数完全一致,反之,如果设置为0x00000000,则表示前面所有的设置无效,任何报文都可以接收,过滤器呈完全放开状态,可以看出,ID屏蔽位其实就是子网掩码;最后选择开启还是关闭这个过滤器,默认都是开启,如果用户想要取消这组过滤器带来的限制条件,则可以选择关闭该过滤器。所有参数设置如图

3072f3c5733241e48a5f5c5a5b499589.png

由于STM32最多可以设置14个硬件过滤器,也就说最多可以通过硬件筛选出14个指定的ID号,即14个不同类型的报文。如果用户需要获取更多类型的报文,则可以使用ID子网掩码配合软件过滤来实现,但是需要通过软件编程,消耗一点CPU和RAM资源。

(3)发送报文

CAN最重要的功能就是报文的发送,这个功能可以利用CAN Send Frame.vi函数来实现,如图

664651b6e2ba45d3beb1b90d1dcdb285.png

一般情况下,要想发送一帧报文,需要设置以下4项:输入报文ID号,如果是11位的标准帧,那么ID的范围就是0211-1,如果是29位的扩展帧则是0229-1,可见在一个CAN网络中,传递的报文帧数量可以很多,而且,ID号越小优先级越高;ID号的位数决定了该帧属于标准帧还是扩展帧;发送的是携带重要数据的数据帧还是回读命令的远程帧;最后是数据场,一帧数据最多不能超过8个字节。该VI可以返回发送该帧报文的邮箱编号(Mailbox Number)以及是否发送成功。

(4)获取接收缓冲区报文数量

在读取报文之前,我们需要先获取一下当前开辟的接收缓冲区当中,到底有多少帧报文以及缓冲区中的有效字节数,类似于串口缓冲区中的字节数。获取报文数量可以利用CAN Frame Count.vi函数来完成,如图

aec2786f03c64558944ba8d07fa6fd78.png

其中,Frame Counts返回的是接收到的有效报文数量,但是每帧报文中的有效数据字节数(数据场)不一定都相同;总的数据字节数量通过Buffer Counts返回。

(5)读取指定数量的报文

知道了当前接收缓冲区中的报文数量,就可以利用CAN Read Frame.vi函数来读取这些数据,如图

3715cef1d7274798b74751d1c2701254.png

该VI返回的是一个二维数组:数组中的每一行表示一帧数据,每一行中的前4个字节为报文ID号,大端格式,即最低位在索引0;第5个字节表示接收到的是数据帧(0)还是远程帧(1);第6个字节为该帧报文中携带的有效数据字节数量;余下的数组元素就是用户需要得到的数据场数据。


目录
相关文章
|
3月前
|
Java Linux Android开发
嵌入式Android系统耳机驱动基本知识
嵌入式Android系统耳机驱动基本知识
45 0
|
3月前
|
Linux
Linux设备驱动之多个同类设备共用一套驱动
Linux设备驱动之多个同类设备共用一套驱动
115 0
|
3月前
|
Unix Linux 编译器
Linux驱动设计(一):驱动是什么?
Linux驱动设计(一):驱动是什么?
43 0
|
Linux API
Linux驱动之I2C驱动架构
Linux驱动之I2C驱动架构
【驱动详解】如何理解驱动程序
【驱动详解】如何理解驱动程序
326 0
【驱动详解】如何理解驱动程序
|
测试技术 程序员
我的场景驱动设计
我的场景驱动设计
我的场景驱动设计
|
IDE 前端开发 数据可视化
ZenUML与服务驱动设计
ZenUML与服务驱动设计
ZenUML与服务驱动设计
|
Windows
驱动开发:驱动与应用的简单通信
驱动程序与应用程序的通信离不开派遣函数,派遣函数是Windows驱动编程中的重要概念,一般情况下驱动程序负责处理I/O特权请求,而大部分IO的处理请求是在派遣函数中处理的,当用户请求数据时,操作系统会提前处理好请求,并将其派遣到指定的内核函数中执行,接下来将详细说明派遣函数的使用并通过派遣函数读取Shadow SSDT中的内容。
214 0
|
Ubuntu Linux Windows
Linux驱动开发: 编写USB接口光谱仪驱动
Linux驱动开发: 编写USB接口光谱仪驱动
187 0