当前位置:首页 > 汽车电子 > 汽车电子
[导读]1 前言标定是指根据整车的各种性能要求(如动力性、经济性、排放及辅助功能等),来调整、优化和确定整车上各ECU(如发动机、AT等各子系统 ECU)控制参数的控制算法。标定系统主要是由上位机和底层ECU这二部分组成,因此

1  前言

标定是指根据整车的各种性能要求(如动力性、经济性、排放及辅助功能等),来调整、优化和确定整车上各ECU(如发动机、AT等各子系统 ECU)控制参数的控制算法。标定系统主要是由上位机和底层ECU这二部分组成,因此,上位机和底层ECU的通信方式对整个标定系统的性能起到了至关重要的作用。目前,一般的标定系统都是采用基于串行口的点对点的通信方式,这种通信方式容易实现,但存在着通信速度较慢、可靠性较低等缺陷。这里我们采用的是CAN总线的通信方式,相对串口通信,基于CAN总线的通信方式具有通信可靠[1]、传输速度快、可实现在线编程等优点。

2  总体设计

CAN通信可视为系统的一个I/O字符流设备[3],它在完成普通收发功能的同时,还要能实现驱动程序必备的设备无关性。即驱动程序应将系统所有的硬件特性封装起来,为使用该设备的应用程序提供与硬件无关的、通用的编程接口,应用层程序编写人员无需了解设备的原理,即可顺利实现对设备的控制,通过该设备实现可靠的数据交换。另外,针对CAN通信和嵌入式系统的实时性要求,该驱动程序要求收发数据代码可靠,延迟短,占用系统时间短,中断执行时间短,关闭中断时间短,并在收发错误和发生异常情况时,向应用程序汇报。另外,该驱动程序需要监控CAN控制器的工作状态,在出现致命错误和脱离总线时,为CAN模块复位,并向系统汇报。

图1 驱动程序总体结构图

基于以上需求分析,结合其他OS中实现I/O串行设备的驱动方案及CAN的总线要求特点,设计总体驱动程序结构如图1。   

3  CAN驱动模块的实现

基于以上总体设计框架,首先定义一个CAN类来封装CAN通信中的数据结构和函数,最下面一层为中断级程序,中断处理程序在每次CAN控制器完成收发时,唤醒驱动程序,进行下一步工作。在中断处理程序中,根据不同的中断向量来确定当前发生的是发送完成中断还是接受完成中断,并完成相应工作。中间一层为底层驱动程序,底层驱动程序主要是通过对CAN控制器寄存器的读写,完成对CAN端口的配置和状态检测等工作,同时为设备无关软件和用户程序提供接口。在这一层中,必须要建立一个环状缓冲结构,该缓冲由一个接收环状缓冲区和一个发送环状缓冲区组成,其数据结构如下代码所示,对于每个环状缓冲区,设计了一个存入指针指向下一个待存入CANMsg的存入地址,一个读出指针指向缓冲区下一个待取出的(最旧的)CANMsg的地址,一个计数器记录目前缓冲区中有多少个CANMsg待取出,一个信号量,用于与应用程序交换消息。接收环状缓冲区用于缓冲接收到的总线消息,等待应用程序处理,发送环状缓冲区用于缓冲应用程序发送出的消息,等待发送中断程序来处理。

typedef struct{   //环形缓冲区的数据结构

INT16U   RingBufRxCtr;       //接收计数器

OS_EVENT *RingBufRxSem;    //信号量

CAN_msg  *RingBufRxInPtr;    //接收缓冲区的存入指针

CAN_msg  *RingBufRxOutPtr;  //接收缓冲区的读出指针

CAN_msg  RingBufRx[CAN_RX_BUF_SIZE];  //接收缓冲区的消息存储

INT16U   RingBufTxCtr;  //发送计数器

OS_EVENT *RingBufTxSem;

CAN_msg  *RingBufTxInPtr;    //发送缓冲区的存入指针

CAN_msg  *RingBufTxOutPtr;  //发送缓冲区的读出指针

CAN_msg  RingBufTx[CAN_TX_BUF_SIZE];  //发送缓冲区的消息存储

}CAN_RING_BUF;

 3.1 底层驱动

底层驱动模块为我们应用程序提供了接收和发送消息的接口函数。

图2  CAN接收消息

当接收消息时[3],如图2所示,应用程序在信号量处等待;收到一个消息后,ISR从串行端口读入消息,将其存入环型缓冲区。然后ISR发出信号量,通知在等待串口数据的任务已收到一个消息。等待任务收到信号量后,进入就绪状态,准备被OS调度器激活。当内核调度该任务运行时,该任务从环状缓冲区中取出消息,完成接收消息的过程。

void CAN_GetMsg(CAN_msg *msg){

INT8U   oserr;

OS_CPU_SR cpu_sr;

CAN_RING_BUF *pbuf;

pbuf = &ringbuf;

OSSemPend(pbuf->RingBufRxSem,0,&oserr);   //等待信号量

OS_ENTER_CRITICAL();//关中断

pbuf->RingBufRxCtr--;//接收计数器减1

CopyMsg(pbuf->RingBufRxOutPtr++,msg); //从环形缓冲区中取出信号量         

if(pbuf->RingBufRxOutPtr==&pbuf->RingBufRx[CAN_RX_BUF_SIZE]) {pbuf->RingBufRxOutPtr= &pbuf->RingBufRx[0];

//如果环形缓冲区的读出指针达到缓冲区的最末端,将其改为指向缓冲区的首地址  }

OS_EXIT_CRITICAL();  //开中断,允许CPU响应中断   }

发送CAN消息与接受消息类似。后台进程将欲发送的消息帧存储于发送环状缓冲区中。当CAN端口准备发送一帧消息时,产生一个中断,CAN消息从缓冲区中取出,并由ISR输出[4]。但其中出现了一个问题:CAN端口只能在发送上一个数据结束的时候才会产生一个中断,这个产生中断的时刻与我们需要执行中断任务的时间是不一致的。解决这个问题的方法就是,禁止发送端中断使能直到需要再发送消息为止。在系统启动时,禁止发送中断,发送一个启动消息帧,这时发送完成中断标志位已经被置位,但由于发送中断使能位为低,所以无法发生中断,系统继续执行。当需发送第一个消息时,将该消息放入发送环状缓冲区,然后运行发送中断,这时,上一次发送消息完成中断产生,发送该消息。在发送消息结束时,若发送环状缓冲区中有其他数据需要发送,则清中断源,等待该消息发送完成中断产生,来发送下一个消息,若没有其他数据需要被发送,则直接禁止发送中断,将该消息发送完成时产生的中断保留到下一次有消息需要发送时发生。

图3  CAN发送消息

发送消息的方法如图3。当发送环状缓冲区已满时,信号量作为指示,暂停发送任务。发送消息时,任务等待信号量。如果环状缓冲区未满,则任务继续向环状缓冲区存储欲发送的消息。如果存储的消息是缓冲区第一个字节,则发送中断允许,中断程序准备启动。CAN发送ISR从环行缓冲区中取出最旧的消息,同时发送信号量,通知发送任务,表明环状缓冲区有空间接收另外的消息,接着ISR将消息从发送到总线上。其实现代码如下所示:

void CAN_PutMsg(CAN_msg *msg) {

INT8U oserr;

OS_CPU_SR cpu_sr;

CAN_RING_BUF *pbuf;

pbuf = &ringbuf;

OSSemPend(pbuf->RingBufTxSem, 0, &oserr);   //等待信号量

OS_ENTER_CRITICAL();//关中断

pbuf->RingBufTxCtr++;   //发送计数器加1

CopyMsg(msg, pbuf->RingBufTxInPtr++);  //将消息放入环形缓冲区

if(pbuf->RingBufTxInPtr==&pbuf->RingBufTx[CAN_TX_BUF_SIZE]) {pbuf->RingBufTxInPtr=&pbuf->RingBufTx[0];

     }

if (pbuf->RingBufTxCtr==1) {

     CAN_TxIntEn();//为环形缓冲区的第一则消息,开发送中断

     }

     OS_EXIT_CRITICAL();

}

3.2 中断服务程序

根据前面谈到发送和接收消息的软件结构,在CAN初始化时就要求CAN的接收中断处入开启状态,而发送中断仅仅是在发送缓冲区里面有了第一则消息后再开启的,因此在这里设计两个接口函数,CAN.TxIntEn()和CAN.TxIntDis(),分别将发送屏蔽位置1(允许发送完成中断)和置0(禁止发送完成中断)。

图4  发送接收中断程序流程图

中断级程序的核心就是CANRX_ISR()和CANTX_ISR(),它们由初始化时对该模块的中断设置寄存器设置的中断级别。如图4所示,若为接收完成中断,则清除中断源,将接收到的消息放入接收缓冲区;将该消息存入接收缓冲区存入指针所指向的地址,将该指针向下移动,接收缓冲区计数器加1,并发出信号量通知应用程序有新的消息已经接收到,若有任务正在等待CAN上的新消息,则该任务进入就绪状态等待OS的调度。若为发送完成中断,则将发送缓冲区的待发送消息读出;将有待发送消息且优先级最高的一个中读取最旧的消息(缓冲区取出指针所指向的消息),发送缓冲区计数器减1,发出信号量通知应用程序有一个消息被发出,并汇报当前发送缓冲区的状态;还应判断是否为最后一个待发送的消息,若不是,则清除中断源并将消息发送到总线上,若是最后一个,则禁止发送完成中断后发送该消息,将这个发送完成中断保留到应用程序下一次发送消息的时候允许并产生。

3.3 应用

该驱动程序的应用,如下代码所示,这里使用的是uCOS-II,首先定义一个CAN消息对象(msg)和一个环状缓冲区数据结构(CANRingBuf),在主程序中,初始化OS以后调用Ringbuf_Init()函数初始化环形缓存区,然后调用CAN_Init()函数初始化CAN端口。在启动OS后,用户就可用在任何任务中调用CAN_PutMsg(CAN_msg *msg)和CAN_GetMsg(CAN_msg *msg)发送和接收总线消息了。

CAN_msg msg;

CAN_RING_BUF CANRingBuf;

void main(void) { 

OSInit();

Ringbuf_Init();

CAN_Init();

/* Creat task1 */

       OSStart();    }

void task1 (void * data)

{     CAN_PutMsg(&msg);

CAN_GettMsg(&msg);

}

4  结束语

通过改变芯片总线频率、CAN通信速率这样多次反复不断的调试,此CAN驱动在实时操作系统上运行稳定可靠,未出现数据丢失,较好的实现了上位机与ECU的通信,因此,具有很强的实用价值。

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

9月2日消息,不造车的华为或将催生出更大的独角兽公司,随着阿维塔和赛力斯的入局,华为引望愈发显得引人瞩目。

关键字: 阿维塔 塞力斯 华为

加利福尼亚州圣克拉拉县2024年8月30日 /美通社/ -- 数字化转型技术解决方案公司Trianz今天宣布,该公司与Amazon Web Services (AWS)签订了...

关键字: AWS AN BSP 数字化

伦敦2024年8月29日 /美通社/ -- 英国汽车技术公司SODA.Auto推出其旗舰产品SODA V,这是全球首款涵盖汽车工程师从创意到认证的所有需求的工具,可用于创建软件定义汽车。 SODA V工具的开发耗时1.5...

关键字: 汽车 人工智能 智能驱动 BSP

北京2024年8月28日 /美通社/ -- 越来越多用户希望企业业务能7×24不间断运行,同时企业却面临越来越多业务中断的风险,如企业系统复杂性的增加,频繁的功能更新和发布等。如何确保业务连续性,提升韧性,成...

关键字: 亚马逊 解密 控制平面 BSP

8月30日消息,据媒体报道,腾讯和网易近期正在缩减他们对日本游戏市场的投资。

关键字: 腾讯 编码器 CPU

8月28日消息,今天上午,2024中国国际大数据产业博览会开幕式在贵阳举行,华为董事、质量流程IT总裁陶景文发表了演讲。

关键字: 华为 12nm EDA 半导体

8月28日消息,在2024中国国际大数据产业博览会上,华为常务董事、华为云CEO张平安发表演讲称,数字世界的话语权最终是由生态的繁荣决定的。

关键字: 华为 12nm 手机 卫星通信

要点: 有效应对环境变化,经营业绩稳中有升 落实提质增效举措,毛利润率延续升势 战略布局成效显著,战新业务引领增长 以科技创新为引领,提升企业核心竞争力 坚持高质量发展策略,塑强核心竞争优势...

关键字: 通信 BSP 电信运营商 数字经济

北京2024年8月27日 /美通社/ -- 8月21日,由中央广播电视总台与中国电影电视技术学会联合牵头组建的NVI技术创新联盟在BIRTV2024超高清全产业链发展研讨会上宣布正式成立。 活动现场 NVI技术创新联...

关键字: VI 传输协议 音频 BSP

北京2024年8月27日 /美通社/ -- 在8月23日举办的2024年长三角生态绿色一体化发展示范区联合招商会上,软通动力信息技术(集团)股份有限公司(以下简称"软通动力")与长三角投资(上海)有限...

关键字: BSP 信息技术
关闭
关闭