




已阅读5页,还剩3页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
基于uC/OS-II的CAN驱动程序设计 成进 施国梁 摘要:实时性是衡量CAN现场总线系统性能的一个重要标准。本文提出了一种采用uC/OS-II并结合I-CAN协议在应用层面上提高CAN总线系统实时性的驱动程序设计方案,并以分层的方式逐层阐述CAN驱动程序的设计过程。关键字:CAN总线,uC/OS-II,实时性,驱动程序CAN-Driver Design Based on uC / OS-II Cheng Jin Shi Guoliang(College of Electronic and Information,Soochow University,Suzhou 215006) Abstract: Real-time is an important standard of measuring the performance of CAN field bus system. This paper presents a can driver design by using uC / OS-II in combination with I-CAN protocol which improve the real-time of CAN bus system at the application level, and describes CAN driver design process layer by layered approach described in hierarchical way.Keywords: can bus; uC/OS-II; real-tine; drivers引 言CAN-BUS是德国Bosch公司于1983年为汽车应用而开发的一种能有效支持分布式控制实时控制的串行通信网络,属于现场总线的范畴。通信距离与波特率有关,最大通信距离可达10Km,最大通信波特率可达1Mbps。CAN总线仲裁用11位(CAN2.0A协议)和29位(CAN2.0B协议)标志和非破坏性仲裁总线结构机制,可以确定数据块的优先级,保证在网络节点冲突时最高优先级节点不需要冲突等待。CAN总线上任何节点可在任意时刻主动向网络上其他节点发送信息而不分主次,因此可实现各节点之间的自由通信。目前,CAN总线协议已被国际标准化组织认证,技术比较成熟,已被大量应用于汽车、工业环境、高速网络和低价位多路连线的应用中。uC/OS-II是Jean J.Labrosse开发的一种小型的嵌入式操作系统,它实质上是基于优先级的可剥夺型内核,系统中的所有任务都有一个唯一的优先级别,它适合应用在实时性要求较强的场合。正是由于uC/OS-II的这些特点,笔者采用它来设计CAN的驱动程序以满足系统的实时要求。1 CAN节点的硬件设计CAN节点是分布在CAN网络进行相互通信的基本单元。它主要有主控制器、CAN控制器和CAN收发器组成。本设计的节点结构如图1所示。 图1 CAN节点基本结构框图 CAN节点采用NXP公司的LPC2368作为主控制器。LPC2368是一款基于ARM7 TDMI-S内核的RISC处理器,它包含两个兼容CAN2.0B规范的CAN控制器。每个CAN控制器拥有双重接收缓冲器和三态发送缓冲器,快速的硬件实现的搜索算法,支持大量的CAN标识符。在电压兼容方面,由于LPC2368是一款3.3V器件,虽然其对应的CAN收发器接口引脚能够承受5V电压,但为了让CAN节点能够更稳定得运行,这里采用TI公司的3.3伏CAN收发器SN65HVD230D与之配合使用。SN65HVD230D的高输入阻抗特性可以在一条总线上支持多达120个CAN节点,并且能够和5V的CAN收发器良好地兼容。由于硬件设计不是本文的重点,所以这里不再详述。下面将详细介绍CAN驱动程序的设计。2 CAN驱动程序设计总体思想 为了使软件可移植性强、易维护,采用分层的方法编写CAN驱动程序。驱动程序分层结构见图2。图2 驱动程序分层结构图双向线表示实时操作系统uC/OS-II与CAN驱动程序之间的数据交换。单向箭头表示上层软件对下层软件的调用。这样的驱动程序结构分明,可读性强且易于维护。下面将从下往上分析各层软件的设计和实现方法。3 CAN设备控制层和接口控制层CAN设备控制层主要任务是:初始化主控制器与CAN控制器之间的连接配置、复位CAN控制器、建立主控制器和CAN控制器之间的通信函数。由于LPC2368内部集成了CAN控制器,CPU通过内部APB总线接口能够对CAN控制器的所有寄存器进行访问,所以不再需要编写设备控制驱动层程序,已经完全由硬件实现了。CAN接口控制层主要任务是实现CAN控制器的各种功能。如设置控制模式、发送数据、释放接收缓冲区、配置验收滤波器等等。这些操作都是通过对CAN控制器的内部相关寄存器的读写来实现。程序清单3.1展示的是应用层中实现CAN控制器初始化操作的程序,内部调用的函数都是在这一层中进行编写。 程序清单3.1 CAN初始化程序void CAN20B_Init() #if CAN1_EN 0while(CAN1MOD & CAN_MOD_RM)!=1) CAN1_MOD_RM (); /进入复位模式CAN1_BTR (); /配置总线定时寄存器 ID_RAM (); /配置验收滤波器 while(CAN2MOD & CAN_MOD_NM)!=1) CAN1_MOD_NM_SET(); /进入正常模式CAN1_INT_EN (); /中断使能寄存器设置 #endif 为了使程序更加简洁,可读性强,一般可以通过宏定义的形式进行编写。例如:#define CAN_MOD_RM () CAN1MOD |= 1,CAN1MOD是CAN控制器的模式寄存器,对它的最低位置1使CAN控制器进入复位模式,这种模式下可以对控制器的所有寄存器进行写操作。其他的对于CAN控制器内部寄存器的操作可以参照LPC2368的技术手册,这里不再详述。4 CAN协议层 从OSI网络模型的角度来看,现场总线网络一般实现了第1层(物理层)、第2层(数据链路层)、第7层(应用层)。而CAN现场总线仅仅定义了第1层、第2层,这两层分别由CAN收发器和CAN控制器实现。CAN没有规定应用层,本身并不完整,需要一个高层协议来定义CAN报文中的11/29位标识符、8字节的使用。目前已经存在一些国际上标准的CAN-BUS高层协议,例如DeviceNet协议和CANopen协议。但是这个协议规范比较复杂,理解和开发难度都比较大,对于一些并不复杂的基于CAN总线的控制网络不太适合。本设计采用国内周立功CAN开发组织根据实际应用制定的一简单的CAN应用层协议I-CAN协议作为软件设计的CAN协议层。I-CAN协议中的29位帧标识符定义如表4.1所示。位 符号功能描述28:21SrcMACID(源节点编号)发送节点的编号20:13DestMACID(目标节点编号)接收节点的编号12:5FUNC ID(功能码)指示报文的功能4:0SourceID(资源节点编号)指示操作设备内部单元 表4.1 I-CAN协议中的标识符定义CAN总线仲裁是从标识符的最高位(28位)开始逐位进行。每一个发送器都对发送位的电平与被监控的总线电平进行比较。如果电平相同,则这个单元可以继续发送。如果发送的是“隐性”(逻辑1)电平而监控到为“显性”(逻辑0)电平时,那么该单元就失去了仲裁,必须退出发送状态。再根据I-CAN源节点编号部分可以看出,节点的地址编号越小优先级也就越高,在仲裁时能够优先获得总线使用权。在CAN网络系统中越重要的节点应该分配优先级越高的地址编号,譬如车载网络中的发动机电控单元就应该比定向大灯电控单元的优先级高,这样才能保证重要的报文及时传送出去。在节点接受到报文之后,应用程序依据I-CAN协议解析报文标识符并实现其指定的功能。 5 应用层应用层实现CAN控制器的所有功能。CAN设备控制驱动层、CAN接口驱动层和CAN协议层都在应用层的控制之中。应用层主要实现的任务包括:(1)初始化CAN控制器以及初始化应用层相关的全局变量。(2)编写CAN控制器的中断服务程序。(3)报文处理任务。该任务基于I-CAN协议来解析报文,并实现报文指示的功能。(3)报文发送任务。该任务存储未能发送的报文,并在发送缓冲区可用的情况下自动发送报文。初始化CAN控制器的程序可以参照程序清单3.1,这里不再详述。但是由于初始化CAN控制器直接和CAN物理层及链路层的性能挂钩,必须要依据具体应用环境正确地配置CAN控制器才能使系统稳定地运行。5.1 中断服务程序中断服务程序判断CAN控制器的中断类型,作出相应的响应。其函数见程序清单5.1。程序清单5.1 中断服务程序void CAN1_ISR() INT32U can1_i_st; VICVectAddr =0x0; /更新VIC优先级硬件OSIntEnter(); can1_i_st = CAN1ICR; /读中断和捕获寄存器if (can1_i_st!=0)if(can1_i_st&CAN_RI) /接受中断 CAN1_RI_HANDLE(); if(can1_i_st&CAN_TI1) /发送中断1 if(TX_CNT0)OSSemPost(CAN_TX_OVER);if(can1_i_st&CAN_TI2) /发送中断2 if(TX_CNT0) OSSemPost(CAN_TX_OVER;if(can1_i_st&CAN_TI3) /发送中断3if(TX_CNT0) OSSemPost(CAN_TX_OVER);if(can1_i_st&CAN_BEI) /总线错误中断 CAN1_BEI_HANDLE(); OSIntExit(); /中断级任务切换这里只对接受中断发送中断以及总线错误中断进行阐述,其他类型的CAN中断处理应根据具体系统进行针对性设计,不具有通用性。CAN1_RI_HANDLE()负责接收报文,并将报文发送到任务的消息队列中。其代码如程序清单5.2所示。程序清单5.2 接受中断处理函数void CAN1_RI_HANDLE() RI_DATA.FRAME = CAN1RFS;RI_DATA.ID = CAN1RID;RI_DATA.DataA = CAN1RDA;RI_DATA.DataB = CAN1RDB;OSQPost(CAN1_Q_RX,&RI_DATA); /向消息队列发送消息CAN1_COMMAND_RRB(); /释放接收缓冲区 其中RI_DATA为定义的结构体CAN_MSG变量,CAN_MSG结构如程序清单5.3所示。CAN1RFS、CAN1RID、CAN1RDA和CAN1RDB分别为CAN控制器存储接收报文帧信息、标识符、数据字节的寄存器。程序清单5.3 CAN_MSG结构体struct CAN_MSGINT32U FRAME; /存放报文帧信息INT32U ID; /存放报文标识符INT32U DataA; /存放报文前4个字节数据INT32U DataB; /存放报文后4个字节数据; 当发送中断处理函数通过TX_CNT判断出报文发送函数(程序清单5.4所示)的消息队列中有待发送报文时,通过函数OSSemPost(CAN_TX_OVER)向其发送信号量,通知其可以发送报文了。若TX_CNT为0,说明消息队列中没有待发送的报文,则不发送信号量。CAN1_BEI_HANDLE()通过查询中断和捕获寄存器判断是何种错误类型,并将它记录下来便于系统诊断。由于CAN1_RI_HANDLE()和OSSemPost()都可能就绪等待中的任务,所以为了保证系统能够严格按照优先级来执行任务,程序采用OSIntExit()函数进行中断级任务切换,在执行完中断服务程序后运行一个具有最高级别的任务而不是返回被中断的任务。关于接受中断处理函数和发送中断处理函数将在下面内容中进一步进行阐述。5.2 应用层面临的问题及解决方法下面将结合应用层面临的实际问题对报文处理和报文发送函数进行详细阐述。(1)CAN节点将CAN中断设为FIQ中断,而其他中断设为不同优先级的IRQ中断,由于FIQ中断能够打断IRQ中断,所以节点在任何情况下都能尽快地响应CAN中断,以提高系统的实时性。但是编写的CAN中断服务程序应该越短越好,在不影响系统性能的情况下尽量将中断服务任务放到中断服务程序外执行,从而尽早得退出FIQ中断模式,以使节点能够响应新的中断,减少系统中的中断延时。其中的接收中断处理是最占用节点资源的,它不仅需要根据I-CAN协议对报文进行解析,还需要执行报文指定的功能,所以必须放到中断服务程序外执行。解决的办法通过uC/OS-II中的OSTaskCreate()函数建立一个报文处理任务,这个任务由一个请求消息队列函数OSQPend()和一个报文解析处理函数组成。其示意代码如下所示:程序示意代码5.1 报文处理函数void CAN_RMSG_HANDLE(void* ptmr)ptmr = ptmr;for( ; ; )OSQPend(CAN1_Q_RX,0,&CAN_Q_ERROR);根据I-CAN协议解析报文完成报文制定功能。若需要发送CAN报文,先查询是否有可用的发送缓冲区,若都被锁定,则调用OSQPost()将报文发送到程序清单5.4所示函数的消息队列MESSAGE_TX中并且执行TX_CNT+操作,若有可用的发送缓冲区则直接发送;这里需要注意的是有任务需要发送报文时应该先查询发送缓冲区状态,若有发送缓冲区可用就直接发送,无须通过消息队列作为中介发送,这样可以提高程序运行效率。变量TX_CNT记录MESSAGE_TX中的报文数目,任务向MESSAGE_TX发送一个报文,TX_CNT就加1,报文发送函数(见程序清单5.4)成功发送一个报文,TX_CNT就减1。这样的话中断服务程序(程序清单5.1)就可以根据TX_CNT来判断是否有向 CAN_TX_OVER发送信号量的必要。这样的细节处理可以减少程序不必要的冗余操作。(2)在繁忙的CAN网络中,节点由于仲裁丢失不能及时将数据传输,必须要对代发送的数据进行进行存储,等待节点获得总线使用权的时候再发送出去。LPC2368的CAN控制器有一个三态发送缓冲区,最多能够存储三个报文。但是若三个缓冲区都处于锁定状态(报文正在等待发送或正处于发送过程),又有一个报文需要发送时,则需要额外的缓冲区先将它进行存储,以待节点获得总线使用权时再发送。这里通过定义一指针数组,然后把建立的消息数据缓冲区的首地址存入这个数组中,然后再调用OSQCreate()函数来创建一个用于存储发送报文的消息队列MESSAGE_TX,最后通过OSTaskCreate()函数建立一个负责发送报文的任务。这个任务由一个请求消息队列函数OSQPend()和一个请求信号量函数OSSemPend()组成。该任务函数如程序清单5.4所示。程序清单5.4 报文发送函数void CAN_MESSAGE_SEND(void* ptmr )ptmr = ptmr;for( ; ; )S = OSQPend(MESSAGE_TX , 0 , & Q_ERROR);OSSemPend(CAN_TX_OVER , 0 , &SEM_ERROR);OS_ENTER_CRITICAL( ); /进入临界代码区SEND_TX_BUFFER( S );TX_CNT-; OS_EXIT_CRITICAL( );除非在CAN节点任务中有比将处理好的CAN报文发送出去更重要的任务要做, 一般来讲,报文发送任务在节点任务中应该具有最高的优先级,这样才能保证CAN系统的实时性。 (3)LPC2368的最高运行速率可达72MHz,而CAN最高传输速率最高传输速率为1Mbit/s,一般情况下,即使连续接收到两个报文,CPU也完全有能力在接受完第二个报文前将第一个报文处理完毕。所以这种情况下只需要建立一个报文处理任务就足够了。但是对于要完成较复杂任务的节点,譬如车载网络中的中央控制部件(BSI)来讲, 在全CAN车载网络中,它连接了内部网、车身网和舒适网三个网络。作为汽车车载网络系统中枢,BSI任务繁重,对CAN报文的处理经常会被各种中断和内部任务打断,所以不能保证可以及时处理上一次接收的CAN报文。并且由于消息队列是采取先进先出(FIFO)或者后进先出(LIFO)的方式来组织报文的,当积消息队列中积攒多个还没处理的报文时无法先取出优先级最高的报文进行处理。为了能够优先处理重要设备发送过来的报文,必须针对系统中每个与本节点有进行CAN通信关系的节点建立一个独立的报文处理任务,这个任务包含一个独立的消息队列,并且发送报文的节点优先级越高,这个任务设置的优先级也应该越高。为此程序清单5.2所示的CAN1_RI_HANDLE()函数也应该做出相应的修改,修改之后的程序示意代码如下所
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 社会工作者-社会工作综合能力(初级)真题库-3
- 计算机一级Msoffice基础试题及答案
- 简单店面租赁合同协议书
- 协议书合同样板范本
- 针对软件测试技术的难点试题及答案解析
- 跆拳道加盟合同协议书
- 工程合同增加协议书
- 高考英语语法填空口诀记忆与变式精练专题01 连词判断(上篇)原卷版
- 精彩探讨2025年文学概论试题及答案
- 起草合同协议书去哪里
- 2024年四川西华师范大学招聘辅导员笔试真题
- 2025年市政工程地下管网试题及答案
- 2025年武汉铁路局集团招聘(180人)笔试参考题库附带答案详解
- 2025届云南省曲靖市高三第二次教学质量检测生物试卷(有答案)
- 农产品供应链应急保障措施
- 2024年中国农业银行安徽蚌埠支行春季校招笔试题带答案
- 2025年2月21日四川省公务员面试真题及答案解析(行政执法岗)
- 国家开放大学汉语言文学本科《中国现代文学专题》期末纸质考试第一大题选择题库2025春期版
- 山东大学《军事理论》考试试卷及答案解析
- 面向非结构化文本的事件关系抽取关键技术剖析与实践
- 《国别和区域研究专题》教学大纲
评论
0/150
提交评论