http://www.amobbs.com/thread-3640606-1-1.html
用C语言编程已经1年多,一直以来都有一个疑问:
在大循环+中断(前后台系统)中,如何能使多个任务得到及时的响应?
举例:(编译器:GCC+AVRStudio Ver 4.14)
#include
#include #include /*********************全局变量区********************/volatile unsigned char Temp_Flag
= 0; //温度采集标志位volatile unsigned char Key_Flag = 0; //键盘扫描标志位volatile unsigned char Time_Flag
= 0; //时间刷新标志位/*************系统初始化子函数*************/void System_Initial(void){ .........; //省略}/*************中断服务子函数*************/ISR(...) //系统每10ms产生一次中断请求,即时基为10ms.{++Temp_Flag;++Key_Flag;++Time_Flag;}/*************主函数*************/int main(void){cli(); //关全局中断System_Initial(); //系统初始化sei();while(1){ /**********************任务1***********************/ if(tempFlag
== 10) //每100ms调用一次温度采集 { tempFlag = 0; Fun1(); //读取传感器温度大概花费800ms的时间. } /**********************任务2***********************/ if(keyFlag
== 1) //每10ms调用一次键盘扫描(状态机) { keyFlag = 0; switch(KeyScan()) { case 1: Fun2(); //此函数大约花费100ms时间. break; case 2: Fun3(); //此函数大约花费200ms时间. break; default: break;
} } /**********************任务3***********************/ if(timeFlag
== 100) //每1s更新时间并在LCD1602显示 { timeFlag = 0; Fun4(); //此函数大约花费400ms时间. } }}
有时候,系统运行到Fun1()函数的时候按下键盘,此时无法得到相应,当然以上多任务采用RTOS可以方便的解决,但是我想知道在前后台系统中遇到2个或以上的任务时,有什么更好的方法使各个任务得到及时的响应?
■把func都拆成一步一步,状态机。
■每个任务尽量减小运行时间,,,,不要在任务里等,,,
■第一:
Fun1(); //读取传感器温度大概花费800ms的时间.
看到这样的程序结构就头大,前后台系统一个函数处理800ms不释放MCU,用多任务系统算了。
第二:看了你的回复,一个程序在单核的MCU中运行,再多任务也是分时使用MCU的,都想保证立马执行,可能吗?这个要根据任务的轻重缓急,以及允许响应延迟的时间来安排,如果使用前后台系统,那么就尽量不要出现执行800ms的函数,并且把实时性要求高的任务使用中断处理.
看了你的函数,我肯定地说,你程序中很多地方是死等,而不是使用状态查询的方式。800ms算算1MIPS的单片机,执行了多少条指令了?
2L的DX说得很明白,“把func都拆成一步一步,状态机 ”。
■什么叫状态机,我举个例子说明吧。一个函数,你要执行
Setp1 2 3 ,但是每步之间,都需要等待某个状态100ms,才能执行setp2。
你的程序结构:
step1; // 第一步开始
delay100ms; // 第一步执行完毕,注意:这个期间MCU是浪费来等外设执行STEP1完毕的
step2; // 第二步开始
delay100ms; // 第二步执行完毕,注意:这个期间MCU是浪费来等外设执行STEP2完毕的
step3;
而状态机,你可以简单的分为三个状态,设置一个status 变量,表示当前执行的状态。
int status = 0;
switch( status ) {
case 0: {
step1; // 第一步开始
status++; // 到下一个状态
break; //
} //
case 1: {
if( 第一步完毕 ){
step2; // 第二步开始
status++; // 到下一个状态
}
break;
case 2: {
if( 第二步完毕 ){
step3; // 第三步开始
status = 0; // 整个任务完毕,回到开始
}
break;
}
default:
status = 0; // 这里,说明状态出错了,这里可以加些错误的报警提示
break; //
}
这样以来,就不用死等了。
■其实多任务编程思路和状态机差不多。
多任务编程:无非是由操作系统来调度。(从就绪表中选中一个优先级最高的任务执行)
■读取传感器温度大概花费800ms的时间,要这么久吗?你得检讨一下。30
us就足够有余。
键盘是硬件层和系统层做的,不是用到按键时才去扫描。