汽车ECU 标定系统CCP 软件的实现
时间:11-30
来源:互联网
点击:
4.1 CAN Driver
在这里我们采用的是μC/OS-II 这种实时操作系统,但在标定过程中,我们处理的数据量很大,通信速度也很快,CAN 接收到一条消息就产生一次中断,中断服务子程序,每次中断都要引起一次任务调度。CPU 大量的时间花在任务切换上,若CPU 还需处理其他事件,则可能出现接收缓冲寄存器接收溢出的错误,造成数据丢失。因此,在这里采用一种基于环形缓冲区的方式来实现CAN Driver。整个CAN Driver 由中断处理程序和底层驱动模块组成。中断处理程序在每次CAN 控制器完成收发时,唤醒驱动程序,进行下一步工作,设备相关程序通过对CAN 控制器寄存器的读写,完成对CAN 端口的配置和状态检测等工作,同时为设备无关软件和用户程序提供接口。而底层驱动模块则主要任务是结合收发消息缓冲区,为应用程序提供了接收和发送消息的接口函数。
(1)中断处理程序
中断级程序的程序流程图如图 2 所示。首先根据不同的中断类别进入不同的中断级程序。若为接收完成中断,则清除中断源,将接收到的消息放入接收缓冲区;将该消息存入接收缓冲区存入指针所指向的地址,将该指针向下移动,接收缓冲区计数器加1,并发出信号量通知应用程序有新的消息已经接收到,若有任务正在等待CAN 上的新消息,则该任务进入就绪状态等待OS 的调度。
图2 中断级程序的程序流程图
若为发送完成中断,则将发送缓冲区的待发送消息读出;将有待发送消息且优先级最高的一个中读取最旧的消息,发送缓冲区计数器减1,发出信号量通知应用程序有一个消息被发出,并汇报当前发送缓冲区的状态;还应判断是否为最后一个待发送的消息,若不是,则清除中断源并将消息发送到总线上,若是最后一个,则禁止发送完成中断后发送该消息,将这个发送完成中断保留到应用程序下一次发送消息的时候允许并产生。
(2)底层驱动模块
底层驱动模块主要是为应用程序提供了接收和发送消息的接口函数。当接收消息时,如图3 实线所示,应用程序在信号量处等待;收到一个消息后,ISR从串行端口读入消息,将其存入环状缓冲区。然后ISR 发出信号量,通知在等待串口数据的任务已收到一个消息。等待任务收到信号量后,进入就绪状态,准备被OS 调度器激活。当内核调度该任务运行时,该任务从环状缓冲区中取出消息,完成接收消息的过程。
图3 缓冲区接收发送消息
发送消息的方法如图3 虚线所示。当发送环状缓冲区已满时,信号量作为指示,暂停发送任务。为发送消息,任务等待信号量。如果环状缓冲区未满,则任务继续向环状缓冲区存储欲发送的消息。如果存储的消息是缓冲区的第一个字节,则发送中断允许,中断程序准备启动。CAN 发送ISR 从环行缓冲区中取出最旧的消息,同时发送信号量,通知发送任务,表明环状缓冲区有空间接收另外的消息。接着ISR 将消息从CAN 端口发送到总线上。
4.2 CCP Driver
基于实时操作系统的CCP Driver,标定系统在这里是通过Command 处理机和DAQ 处理机两部分来实现的。
Command 处理机由一个系统任务来完成。该任务在OS 初始化后就启动运行,识别CAN 网络上的CCP 主设备发送给该从设备的会话命令。根据命令做相应动作,并回送命令应答,完成会话。DAQ 处理机由1~n 个系统任务来完成。本项目支持对不同时间要求的监视参数设定不同的DAQ 周期,不同时间要求的监视参数填入不同的DAQ_List,每个DAQ_List 由一个任务完成周期发送。
Command 处理机在收到主设备要求启动某DAQ_List 命令时, 调用OS 函数OSTaskCreate()启动相应的任务,该任务每完成一次发送就调用OS 函数OSTimeDlyHMSM( )挂起一定的时间,这个时间就是主设备对这个DAQ_List 要求的发送周期。在收到主设备要求停止某DAQ_List 命令时,调用OS 函数OSTaskDel( )函数删除该任务。
(1)Command 处理机
Command 处理机主要是获取并解读主设备的CCP 命令,并执行该命令;命令执行完成后,向主设备发送应答;若执行时出错,应答中向主设备报错;若主设备命令要求对DAQ进行操作,则将该操作传达给DAQ 处理机,由DAQ 处理机完成DAQ 操作。
Command 处理机由一个RTOS 任务来完成,其示意性代码如下,GetMsg 函数为CAN 驱动程序的接收消息函数,调用此函数则等待获取CAN 端口接收到的消息帧。一旦接收到新的消息帧则函数返回,用户可通过&msg_command 获取该消息帧的内容。
void task (void * data) {
for( ; ; ) {
GetMsg(&msg_command); //等待并获取一个CCP 命令
CCP_Command (&msg_command); //将命令送给CCP 命令处理函数
}
}
(2)DAQ 处理机
DAQ 处理机的任务是根据主设备的需要,定时向CAN 总线上发送DAQ 数据。它由启动从设备的DAQ 发送、停止从设备的DAQ 发送、执行DAQ 循环发送的任务3 个部分构成。
启动或停止从设备的 DAQ 发送,由Command 处理机调用函数Start_DAQ (DAQ List
number ,)和Stop_DAQ (DAQ List number)来完成,该函数启动或停止相应的DAQ 发送任务,
其示意性代码如下:
Start_DAQ(INT8U DAQ_List_num) { //启动第n 个DAQ_List
DAQ_List[n].Started = 1;
DAQ_List[n].Prepared = 1;
OSTaskCreate (第n 个DAQ_List 的任务); //调用系统函数,创建DAQ 发送任务,
并使任务进入调度
}}
Stop_DAQ(INT8U DAQ_List_num) { //停止第n 个DAQ_List
DAQ_List[n].Started = 0;
DAQ_List[n].Prepared = 0;
OSTaskDel (第n 个DAQ_List 的任务); //调用系统函数,删除DAQ 发送任务
}
执行DAQ 循环发送的任务,需要按照ODT 设置把DAQ 数据发送到CAN 总线上,同时需要按照DAQ 周期要求循环执行,该任务示意性代码如下:
void DAQ_task ( ) {
for( ; ; ) {
CCP.Upload(0); //根据ODT 设置把DAQ 数据发送到CAN 总线上
OSTimeDlyHMSM(Period); //调用RTOS 函数,等待一个周期的时间
}
}
在这里我们采用的是μC/OS-II 这种实时操作系统,但在标定过程中,我们处理的数据量很大,通信速度也很快,CAN 接收到一条消息就产生一次中断,中断服务子程序,每次中断都要引起一次任务调度。CPU 大量的时间花在任务切换上,若CPU 还需处理其他事件,则可能出现接收缓冲寄存器接收溢出的错误,造成数据丢失。因此,在这里采用一种基于环形缓冲区的方式来实现CAN Driver。整个CAN Driver 由中断处理程序和底层驱动模块组成。中断处理程序在每次CAN 控制器完成收发时,唤醒驱动程序,进行下一步工作,设备相关程序通过对CAN 控制器寄存器的读写,完成对CAN 端口的配置和状态检测等工作,同时为设备无关软件和用户程序提供接口。而底层驱动模块则主要任务是结合收发消息缓冲区,为应用程序提供了接收和发送消息的接口函数。
(1)中断处理程序
中断级程序的程序流程图如图 2 所示。首先根据不同的中断类别进入不同的中断级程序。若为接收完成中断,则清除中断源,将接收到的消息放入接收缓冲区;将该消息存入接收缓冲区存入指针所指向的地址,将该指针向下移动,接收缓冲区计数器加1,并发出信号量通知应用程序有新的消息已经接收到,若有任务正在等待CAN 上的新消息,则该任务进入就绪状态等待OS 的调度。
图2 中断级程序的程序流程图
若为发送完成中断,则将发送缓冲区的待发送消息读出;将有待发送消息且优先级最高的一个中读取最旧的消息,发送缓冲区计数器减1,发出信号量通知应用程序有一个消息被发出,并汇报当前发送缓冲区的状态;还应判断是否为最后一个待发送的消息,若不是,则清除中断源并将消息发送到总线上,若是最后一个,则禁止发送完成中断后发送该消息,将这个发送完成中断保留到应用程序下一次发送消息的时候允许并产生。
(2)底层驱动模块
底层驱动模块主要是为应用程序提供了接收和发送消息的接口函数。当接收消息时,如图3 实线所示,应用程序在信号量处等待;收到一个消息后,ISR从串行端口读入消息,将其存入环状缓冲区。然后ISR 发出信号量,通知在等待串口数据的任务已收到一个消息。等待任务收到信号量后,进入就绪状态,准备被OS 调度器激活。当内核调度该任务运行时,该任务从环状缓冲区中取出消息,完成接收消息的过程。
图3 缓冲区接收发送消息
发送消息的方法如图3 虚线所示。当发送环状缓冲区已满时,信号量作为指示,暂停发送任务。为发送消息,任务等待信号量。如果环状缓冲区未满,则任务继续向环状缓冲区存储欲发送的消息。如果存储的消息是缓冲区的第一个字节,则发送中断允许,中断程序准备启动。CAN 发送ISR 从环行缓冲区中取出最旧的消息,同时发送信号量,通知发送任务,表明环状缓冲区有空间接收另外的消息。接着ISR 将消息从CAN 端口发送到总线上。
4.2 CCP Driver
基于实时操作系统的CCP Driver,标定系统在这里是通过Command 处理机和DAQ 处理机两部分来实现的。
Command 处理机由一个系统任务来完成。该任务在OS 初始化后就启动运行,识别CAN 网络上的CCP 主设备发送给该从设备的会话命令。根据命令做相应动作,并回送命令应答,完成会话。DAQ 处理机由1~n 个系统任务来完成。本项目支持对不同时间要求的监视参数设定不同的DAQ 周期,不同时间要求的监视参数填入不同的DAQ_List,每个DAQ_List 由一个任务完成周期发送。
Command 处理机在收到主设备要求启动某DAQ_List 命令时, 调用OS 函数OSTaskCreate()启动相应的任务,该任务每完成一次发送就调用OS 函数OSTimeDlyHMSM( )挂起一定的时间,这个时间就是主设备对这个DAQ_List 要求的发送周期。在收到主设备要求停止某DAQ_List 命令时,调用OS 函数OSTaskDel( )函数删除该任务。
(1)Command 处理机
Command 处理机主要是获取并解读主设备的CCP 命令,并执行该命令;命令执行完成后,向主设备发送应答;若执行时出错,应答中向主设备报错;若主设备命令要求对DAQ进行操作,则将该操作传达给DAQ 处理机,由DAQ 处理机完成DAQ 操作。
Command 处理机由一个RTOS 任务来完成,其示意性代码如下,GetMsg 函数为CAN 驱动程序的接收消息函数,调用此函数则等待获取CAN 端口接收到的消息帧。一旦接收到新的消息帧则函数返回,用户可通过&msg_command 获取该消息帧的内容。
void task (void * data) {
for( ; ; ) {
GetMsg(&msg_command); //等待并获取一个CCP 命令
CCP_Command (&msg_command); //将命令送给CCP 命令处理函数
}
}
(2)DAQ 处理机
DAQ 处理机的任务是根据主设备的需要,定时向CAN 总线上发送DAQ 数据。它由启动从设备的DAQ 发送、停止从设备的DAQ 发送、执行DAQ 循环发送的任务3 个部分构成。
启动或停止从设备的 DAQ 发送,由Command 处理机调用函数Start_DAQ (DAQ List
number ,)和Stop_DAQ (DAQ List number)来完成,该函数启动或停止相应的DAQ 发送任务,
其示意性代码如下:
Start_DAQ(INT8U DAQ_List_num) { //启动第n 个DAQ_List
DAQ_List[n].Started = 1;
DAQ_List[n].Prepared = 1;
OSTaskCreate (第n 个DAQ_List 的任务); //调用系统函数,创建DAQ 发送任务,
并使任务进入调度
}}
Stop_DAQ(INT8U DAQ_List_num) { //停止第n 个DAQ_List
DAQ_List[n].Started = 0;
DAQ_List[n].Prepared = 0;
OSTaskDel (第n 个DAQ_List 的任务); //调用系统函数,删除DAQ 发送任务
}
执行DAQ 循环发送的任务,需要按照ODT 设置把DAQ 数据发送到CAN 总线上,同时需要按照DAQ 周期要求循环执行,该任务示意性代码如下:
void DAQ_task ( ) {
for( ; ; ) {
CCP.Upload(0); //根据ODT 设置把DAQ 数据发送到CAN 总线上
OSTimeDlyHMSM(Period); //调用RTOS 函数,等待一个周期的时间
}
}
- 以灯光控制为例说明LIN总线在车身控制中的应用(05-24)
- 现代电动车辆中电控技术应用(03-01)
- CAN总线混合动力汽车电控系统的设计与实现(08-29)
- 利用CAN总线的进行汽车轮速传感器系统设计(09-22)
- CAN总线在CFA6470混合动力汽车中的应用(09-25)
- 基于CAN总线的汽车发动机智能电子控制器研究(10-20)