导言
近年来,依据各种总线规范的网络化操控体系现已在工业操控范畴内得到广泛运用。网络化操控体系选用了彻底分散化的操控节点结构,将操控的权利很大部分交给了处于操控现场的智能节点,体系内各种交互信息经过现场总线传送。
当时已有用化的总线规范有许多种,如WorldFIP, Profibus, LONWORKS, CAN等。其间,CAN(Controller Area Network)是Bosch公司在现代轿车运用技能中抢先推出的一种串行通讯网络。CAN主线选用多主站作业方法,依据优先权进行总线拜访裁定,能够检测出通讯进程产生的任何过错。CAN总线还具有杰出的信号传输功用,当信号传输间隔到达l0km时,它仍可供给高达SOKbit/s的数据传输速率。别的,CAN协议废除了站地址编码,而选用对通讯数据块编码的方法,这样使得网络内的节点个数在理论上不受约束。现在,CAN总线现已在许多职业得到了广泛的运用,尤其是工业操控范畴,并常被认为是最有出路的现场总线之一。
常用的CAN总线节点一般选用的是“单片机+CAN操控器”的结构,这样我们运算才干的约束,这类节点的智能化程度较低,常是作为工控机节点的从节点。而近年来,以ARM为代表的嵌入式32位微处理器技能得到了飞速发展,无论是在功耗、便携性仍是在硬件本钱上,许多高功用的ARM芯片现已与单片机相差无几,因而在CAN节点规划中,运用ARM芯片替代传统的8/16位单片机现已是一个十分有用的挑选。这样规划的CAN节点,不只保留了低功耗、低本钱和小体积的长处,而且功用得到了大幅进步,若辅以大容量的存储器,一起运转功用强大的嵌入式操作体系,它简直已能够替代原先的工控机节点。本文则从软硬件两方面详细介绍了上述规划方案的详细完结进程。
1 节点的接口电路规划
本文规划的CAN总线节点是某工业操控体系的一个子模块,一起归纳考虑其它相关需求和功用扩展,因而选用了AT91 RM9200处理器作为体系的中心处理单元。AT91 RM9200,是ATMEL公司出产的一款高功用的ARM9处理器,它是一款通用工业级ARM芯片,主频为180MHz/200MIPS,现已在工业操控、智能仪器仪表等范畴内得到了很多的成功运用。
CAN操控器选用的是SJA 1000芯片,它是Philips公司出产的一款独立CAN总线操控器芯片,专用于移动方针和一般工业环境中操控器局域网络((CAN)。SJA 1000本质上是前期的PCA82C200的晋级产品,与后者在管脚、电气特性上彻底兼容,而且除具有根本CAN作业形式((BasicCAN)外,还增加了一种新的增强作业形式(PeIiCAN),这种新形式支撑具有许多新特性的CAN2.OB协议。
SJAlooo的总线接口选用的是地址总线和数据总线复用的方法,这种方法与s1相似,也选用总线复用架构的处理器,接口很便利,并在读写时序上也很好合作,但当与数据总线和地址总线别离的微处理器接口时,则需求专门的读写逻辑与之合作,而且还相对比较复杂,依据这个原因,现在许多规划都选用比如SPI等专用接口的CAN总线操控器,但这种方法使运用遭到了许多约束,如要求微处理器有必要有SPI接口,一起当体系需求多路CAN总线接口时,会遭到SPI端口数的约束等。
ARM架构的数据总线和地址总线是别离的,因而,有必要引进专门的操控逻辑,才干完结对SJA1000的操作。
图1和图2别离为SJA 1000读/写操作时序。剖析其读/写时序,能够看出,无论是读操作仍是写操作,首要有必要送出操作寄存器的地址,然后读/写数据。在写地址的进程中,片选信号(/CS )和读(/RD )、写(/WR)均无效(高电平),仅ALE信号有用(高电平),而在读/写数据的进程中,读/写信号有用(低电平),ALE信号无效(低电平),一起,在操作的进程中,还有必要分量信号电平的持续时刻。
因而,能够选用如图3所示的操控逻辑完结。
图1 SJA1000的读操作时序(Intel形式)
图2 SJA1000的写操作时序(Intel形式)
图3 SJA1000操作时序的完结
在图3所示的SJA1000操作时序的完结中,左端的信号如/CS, /RD, /WR, A7别离为ARM微处理器的片选、读、写操控信号,A7为地址信号(也能够是其它的地址),右端产生的ALE CAN,/CS CAN, /WR_CAN, /RD_ CAN别离与SJA1000对应的信号相连接,当微处理器对SJA100()对应的地址进行读写操作时,即可产生正确的操控逻辑。
2 节点的驱动程序开发
在工业操控运用中,运用嵌入式操作体系已逐步成为一个盛行的挑选。现在,市场上的嵌入式操作体系超越100种,其间嵌入式Linux是一种十分抱负、经济的挑选,由于它不只具有功用强大、高功用、稳定性好等长处,仍是免费并开放源代码的。一起Linux内核选用了模块化规划,具有十分杰出的移植性和可定制性。现在,许多ARM出产厂商都现已将Linux体系移植到其出产的ARM芯片上,并发布了相关源代码供用户免费运用。本体系中选用的操作体系便是ATMEL公司发布的支撑其AT912RM9200处理器的ARM-Linux体系的版别,版别号为2.4.27。
CAN操控器SJA1000明显归于Linux体系中的字符设备类型,其驱动程序的完结架构相似于体系中字符设备的通用完结结构,关于Linux设备驱动开发的详细剖析可参阅文献。本末节则以SJA1000的增强作业形式(PeIiCAN)为例,对Linux体系下CAN设备驱动程序的首要完结部分进行了详细阐明,包含首要数据结构的界说、操作函数和中止函数的完结三个部分。
2.1 CAN设备驱动的首要数据结构
为便利驱动程序的规划和编写,驱动中界说了两个数据结构体,即协议帧数据结构和缓冲区结构体,下面给出每个结构体的界说及成员变量的解说。
其间,协议帧结构体是用来对CAN网络的报文数据帧进行笼统,驱动中运用该结构体来进行用户与内核空间的数据帧传递及发送/接纳数据缓冲区的办理。
从缓冲区结构体的界说能够看出,CAN设备的数据缓冲区由两个独立缓冲区构成,一个用于设备读操作,另一个用于写操作。读缓冲区和写缓冲区都是一个先入先出的环形缓冲区,缓冲区的巨细设为协议帧结构体的整数倍,如64倍。驱动经过缓冲区的读指针和写指针来进行缓冲区办理。如关于接纳缓冲区(读缓冲区),它的读指针指向了当驱动程序从内核空间向用户空间劳动报文数据帧时,缓冲区中第一个有用数据帧的方位;而缓冲区的写指针则代表了在操控器芯片碑文接纳数据时,行将数据帧从SJA1000的寄存器读到缓冲区,缓冲区的当时可写方位;这样经过读指针和写指针的相对方位及缓冲区的全体长度就能够得到读缓冲区中当时的数据帧个数。写缓冲区的办理与读缓冲区根本相同,其详细机制可参阅后边给出的相关伪代码。一起缓冲区中还界说了volatile int型变量tx_in_progress来表征当时是否有实践的数据发送操作已被发动,“1”标识已发动,不然为“0”。别的,结构体界说中运用到了Linux体系的等候行列结构,关于它的详细机制可参阅文献。
2.2 CAN设备的操作函数
字符设备驱动的中心便是完结设备的操作函数结构,所谓的操作函数结构,本质上是界说了运用程序在设备上的一切或许操作。但关于某一详细设备,驱动中只需求完结设备作业一切必要的操作。如关于CAN设备,本例中共完结了5种体系调用函数,即open, close, read, write和ioctl函数。
其间,open函数是在运用程序翻开CAN设备时被调用,函数首要完结两部分功用,首要对驱动中的变量和数据结构进行初始化,并分配缓冲区空间。另一部分便是对CAN操控器SJA 1000初始化,即在复位时为芯片的各个寄存器设置正确的初始值。关于SJA1000芯片,需求设置的寄存器包含:1)形式和时钟寄存器;2)输出操控寄存器;3)检验代码寄存器和检验屏蔽寄存器;4)总线守时寄存器;5)过错计数寄存器;6)中止使能寄存器。需求留意的是,SJA1000的装备寄存器只能在复位形式下可写,所以在设置寄存器之前,有必要先进入复位形式,一切设置完结后有必要回来正常作业形式,关于SJA 1000芯片寄存器设置的更多内容可拜见文献。CAN设备的close调用的完结功用十分简略,即等候缓冲区中已有的数据帧被处理完,然后开释缓冲区,最终封闭设备中止。
驱动程序的write便是对应于用户写CAN设备时的体系调用。它的功用便是完结运用程序在用户空间中的报文发送,即报文数据从用户空间向内核空间的传递。下面给出了完结write函数的伪代码:
ssize t can-write(……)
{
…..
判别指定的数据长度是否分量数据帧格局,若不分量,则提示并回来;
经过写指针和读指针的相对方位及缓冲区的全体长度核算输出缓冲区中闲暇空间的巨细,
while闲暇空间长度<一个数据帧巨细运用interruptible_sleep_on_timeout()函数将写进程放入写操作等候行列睡觉,该函数既阐明晰睡觉可被信号中止,还能够指定进程的最长睡觉时刻;
睡觉完毕后,再次核算闲暇空间的巨细。若闲暇空间长度已大于或等于一个数据帧巨细,则可跳出循环,不然持续while循环;
从用户空间劳动N字节数据到输出缓冲区,其间:N = min(核算的闲暇空间巨细,数据长度参数),然后更新输出缓冲区的写指针方位;
if当时无实践的发送操作已被发动,即tx_in_progress等于0
置位tx in_progress为1,一起调用发送初始化函数,行将输出缓冲区中第一个有用数据帧写入到操控器芯片相应的发送寄存器中,一起使能发送操作,完结后,完毕c} write()函数并回来数值N;
else
函数直接完毕,回来N
}
需求阐明的是,上述伪码中在对临界区变量进行操作和判别时,即核算闲暇区长度和判别饮_in_progress变量时,有必要要在封闭设备中止条件下进行,操作完结后当即从头翻开中止,下面描绘的读函数中与临界区变量相关的操作也有必要选用相同的机制。
读函数read的功用便是响运用户对CAN设备的读操作,假如接纳缓冲区中已有了数据帧,则直接从缓冲区劳动M字节的数据回来给用户,其间M为用户要求字节数与缓冲区已有数据字节数之间的较小值,更新读指针方位然后函数回来数值M,而假如当时缓冲区中无有用数据,则需求判别设备文件的读取形式,若为非堵塞形式,则直接回来,不然将读进程放入读操作等候行列睡觉,指定进程的最大睡觉时刻并设置为睡觉可被信号中止形式,当使命被唤醒后,再对唤醒方法进行判别,若因睡觉时刻完毕而唤醒,则函数直接回来相应标识,不然阐明缓冲区中已有数据,则碑文上述的劳动动作,并更新缓冲区的读指针方位,函数完毕并回来实践读取字节数,详细完结略。
设备的iOCtl函数是用于设备操控的公共接口,能够依据设备的详细需求来完结相应的操控代码,在本文中共完结了三种功用,即铲除读/写缓冲区、设置总线波特率、设置检验代码寄存器和检验屏蔽寄存器。
2.3 CAN设备的中止函数
如上所述,设备的读函数和写函数仅仅完结用户空间与设备的接纳/发送缓冲区之间的数据帧传递,而真实的数据接纳和发送作业,即芯片的寄存器与数据缓冲区之间的数据读取和写入,是由设备中止函数来完结。因而,完结中止函数既是驱动程序开发的中心,也是难点。下面是本例中运用的中止函数的伪代码:
ssize_tcan_isr_handle(……)
{
……
读Call芯片的中止状况寄存器,用来判别中止源类型;
if CAN接纳中止
读芯片的RX帧信息寄存器,然后依据接纳的数据帧类型,即规范帧或扩展帧,读取相应的ID寄存器和RX数据寄存器,并将各数值写入一个数据帧结构体中,再把读取的该数据帧劳动到接纳缓冲区中,缓冲区的写指针便是缓冲区的当时可写方位,劳动完结后,更新写指针方位;
读操控器的状况寄存器,判别RXFIFO是否还有可用信息,若还有信息,则重复碑文上述的数据读取操作,不然就判别读操作等候行列上是否有睡觉使命,有则唤醒它,中止函数完毕;
else if CAN发送中止
判别设备的发送缓冲区是否已为空,若为空,则置tx_in_progress变量为0,并判别写操作等候行列上是否有睡觉进程,有则唤醒它,然后中止函数完毕,
不然持续发送缓冲区中的数据帧,而缓冲区的读指针代表了缓冲区中当时需求发送的数据帧方位,发送完结后,更新读指针方位,并判别写操作等候行列上是否有睡觉进程,有则唤醒它,中止函数退出;
else即为其他中止
判别过错类型,并置位相应过错标识,然后别离判别写操作等候行列和读操作等候行列上是否有睡觉进程,有则唤醒它,中止函数退出;
}
当CAN操控器产生除接纳中止和发送中止外的其它类型中止时,一般是依据详细的运用需求采纳相应的处理办法。本例中选用了置位相应标识,由用户程序进行处理的方法。别的,驱动程序除完结上述的操作函数和中止函数,还应在模块初始化函数中完结设备注册、请求中止并注册中止函数及其他初始化作业;在模块铲除函数中需求卸载设备并开释中止资源。
3 完毕语
本文从软硬件两方面临依据ARM9芯片的CAN节点的详细规划进程进行了介绍,对硬件规划中的要害性问题和驱动模块完结结构都作了详细剖析。现在,该CAN总线节点作为一个子体系已在某高速的网络化数据并重体系中得到运用,运转结果表明设备在CAN总线2.0B协议规范(兼容2.0A)下,数据发送、接纳彻底正常,分量了体系作业要求。本文给出的示例具有必定的普适性,对依据其他嵌入式设备上的CAN模块开发也有必定的参阅价值。