基于ARM的车载CAN总线智能终端设计
扫描二维码
随时随地手机看文章
引言
CAN总线在自动控制领域得到广泛应用,也越来越多地出现在嵌入式系统中,在车载数据采集系统及汽车电子控制网络的主控节点设计中,由于车身部位有很多数据采集和控制的电控单元通过CAN总线将采集的数据传给主控节点,所以主控节点获得的数据量大而且处理数据要求实时性高,同时还必须具备多任务的处理能力以及很好的人机交互界面,因此,采用传统的单片机来设计很难满足要求,为此,本文主要描述利用ARM处理器S3C2440所具有的高性能和低耗能等优点,同时通过嵌入式linux的多任务处理能力来设计车载CAN总线的智能节点。
1 系统总体设计
本设计采用三星公司的ARM微处理器S3C2440来作为核心CPU;64MB的NANDFlash(K9F1208)为程序存储器;64MB的SDRAM(K4S281632)为系统运行时的内存;触摸屏用来进行GUI图形界面显示以及与用户的交互;而JTAG接口、串口和以太网接口可以方便的进行开发调试;选用Linux作为嵌入式操作系统;最后采用Qt编写上层的图形用户界面。其系统结构框图如图1所示。
2 CAN总线模块的硬件接口设计
本设计采用的三星S3C2440是一款基于ARM9TDMI内核的RISC处理器,该CPU的主频最高可达500MHz,处理速度快,可满足CAN节点实时性的需求,但由于其片内不带CAN控制器,所以硬件上需要外扩CAN控制器,CAN控制器和收发器采用的是Microchip公司的MCP2510和MCP2551,其中MCP251O完全支持CAN1.2、CAN2.0A、CAN2.OB等版本协议,能够发送和接收标准和扩展报文,它还同时具备验收滤波以及报文管理功能,它与微控制器的通讯是采用SPI口实现的,其SPI口数据传输速率高达5Mb/s;而高速CAN收发器MCP2551则可把CAN控制器生成的数字信号转化成为适合总线传输的差分信号,它也为CAN控制器和CAN总线之间加入了缓冲器,可以有效抑制高压尖峰信号,而且具有很强的抗噪特性。在本设计中,S3C2440被设置为SPI的主设备.MCP251O作为从设备,GPG6引脚控制对从设备的片选操作。为了尽量少占用外部中断口,设计时可将MCP2510的通用中断引脚与S3C2440的外部中断1相连。
同时为了增强CAN总线节点的抗干扰能力,MCP2510的TXCAN和RXCAN并不是与MCP2551的TXD和RXD相连,而是通过高速光耦6N137后与MCP2551相连,这样就能很好地实现总线上各CAN节点间的电气隔离。应该注意的是,光耦部分电路所采用的两个电源Vcc和VcCA必须完全隔离,否则采用光耦就没有意义了,为了增大负载、减少回波反射,可以在CAN总线接口处接上120Q的终端电阻,CAN总线模块的硬件接口电路如图2所示。
3 软件设计
3.1 系统移植和文件系统的构建
由于本设计采用嵌入式Linux作为操作系统,所以需要移植U-boot和Linux内核,同时应移植带有Qt库的文件系统,以及网卡和触摸屏的驱动程序移植,其中最主要的就是开发CAN控制器的驱动程序,最后再将镜像文件烧写到NANDFlash中,系统上电后,由U-boot引导系统启动。
3.2 CAN控制器MCP2510的驱动程序
驱动程序是上层应用程序和CAN控制器硬件之间的一个中间软件层,它屏蔽了CAN控制器的工作细节,并提供给用户程序一系列的标准调用接口函数,这些接口函数可通过SPI接口通信来实现对CAN控制器的操作。用户程序可通过调用Linux系统调用函数来间接访问底层硬件,它们之间的相互关系如图3所示。
(1) SPI接口读写程序
MCP2510芯片内部的所有寄存器都映射在一个地址表上,MCU通过SPI口发送相应的命令和数据来完成对MCP2510的初始化、工作状态的控制以及数据的读写。在实现驱动程序之前,需要完成对MCP2510进行读写或控制的底层函数,而这些函数主要是根据SPI口的通信时序完成MCP2510的读写操作或状态控制。MCP2510的SPI口的写时序如图4所示,故可以按照此时序实现对MCP2510进行写操作的的底层函数。
SPI接口的读写程序如下:
write2510(u8 cmd,u8 addr,u8 data)
{CS_L; //拉低GPG6引脚启动对MCP2510的操作
iowrite8(cmd,SPTDATO); //写指令到SPI口
wait; //等待发送操作完成
iowrite8(addr,SPTDATO); //写地址到SPI口
wait; //等待发送操作完成
iowrite8(data,SPTDATO); //写数据到SPI口
wait; //等待发送操作完成
CS_H; //拉高GPG6引脚结束对MCP2510的操作
}
(2) 驱动程序接口函数的实现
在Linux系统下,每一个硬件设备都对应着一个设备文件,内核一般是通过主设备号将设备驱动程序与设备文件相连,驱动程序的一个重要结构就是file.operations,它包含指向驱动程序内部函数的指针,它的每一个成员对应一个系统调用。所以,在设备驱动程序中,就是通过调用SPI接口的读写程序来实现file_operations结构中的一些接口函数(如open、read、write、ioctl、release等),为了方便用户程序与驱动的交互,可以根据CAN控制器的工作特点定义MCP2510的设备结构体,其定义代码如下:
structMCP2510{
wait_queue_head_t read_wq; //读进程的等待队列
unsigned char en_read; //读进程等待的条件
struct CANR_MSG rec_buf; //接收报文缓冲器
struct CAN_MSG tra_buf; //发送报文缓冲器
struct SET_FILTER set_filter; //MCP2510寄存器配置
structcdevcdev; //字符设备结构体
在上述定义代码中,CANR_MSG结构体作为接收报文的缓冲区,CANR_MSG结构体作为发送报文的缓冲区,en_read是读进程进入等待队列的等待条件,这样就可以把等待队列和事件联系起来,使进程可以转入休眠状态等待某个特定事件,而当事件发生时,这些进程又能够被再次唤醒。这里,事件就是CAN控制器的中断,在中断里可以唤醒等待的进程。
Open函数用于打开设备,设置MCP2510的波特率、验收过滤器、CAN收发数据方式和CAN消息传送模式。read和write函数可以和用户空间交换数据,实现CAN消息的发送和读取,ioctl函数利用其命令参数可以使用户程序重新设置MCP2510的寄存器以改变节点的工作模式和波特率等。
(3) 中断函数的实现
Linux内核会对所有的中断统一编号,使用一个irq_desc结构数组来描述这些中断;每个数组项对应一个中断号,其中记录了中断处理函数入口、底层的硬件访问接口和中断状态等,嵌入式linux内核会维护一个中断信号线注册表,所以,在使用中断前,必须先申请中断号,使用完之后要释放该中断号,这里就是使用函数request_irq(IRQ_EINT1,can_inter_rupt,IRQT_FALLING,DEVICE_NAME,dev_id);来注册一个中断处理程序,其中IRQ_EINT1是所要申请的中断号,can_interrupt是中断处理函数的指针,IRQT_FALLING是中断触发的方式。这里选择的是下降沿触发,其中DEVICE_NAME是产生中断的设备名称,dev_id主要用于共享中断线,中断处理程序需要査询中断标志寄存器来获取中断信息。其中断函数代码片段如下:
上述代码中,icode保存的是从MCP2510的CAN-STA寄存器中读取的中断信息,将icode值左移3位即可得到接收缓冲器0在CAN控制器中的寄存器映射地址,然后将接收到的报文ID和数据拷贝到设备结构体中的CANR_MSG类型缓冲器,然后再唤醒读进程,用户应用程序就可以得到底层硬件接收到的报文数据。其他的中断都可以按这种方法来实现。
3.3 CAN总线智能节点应用层的软件设计
为了使该节点具有多任务的处理能力,所以,本设计的程序采用多线程设计,Qt主线程负责显示窗口,并响应相应的用户触摸操作,比如用户可以点击界面中的设置按钮设置波特率等。创建一个轮询线程就可以不断地发送CAN远程帧以依次请求各个从节点发送数据,然后调用read函数读取接收到的CAN报文,没有接收到消息,该线程就会阻塞,而如果读取到CAN报文,就会刷新数据的显示。其程序流程如图5所示。
4 结语
本文使用ARM和嵌入式Linux作为开发平台,并利用其高性能和多任务的处理能力来开发车载CAN总线智能节点,以便实时接收并处理各车载电控单元的信息,进而使用Qt开发基于触摸屏的图形用户界面。该智能节点具有处理速度快,用户交互界面友好,可维护性强,软件上易于升级等特点。