http://www.amobbs.com/thread-3640606-1-1.html
用C语言编程已经1年多,一直以来都有一个疑问:
在大循环+中断(前后台系统)中,如何能使多个任务得到及时的响应?
举例:(编译器:GCC+AVRStudio Ver 4.14)
#include <avr/io.h>
#include <util/delay.h>#include <avr/interrupt.h>
/*********************全局变量区********************/
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就足够有余。
键盘是硬件层和系统层做的,不是用到按键时才去扫描。