DSP

前后台系统 多任务运行 状态机实现

2019-07-13 19:57发布

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;
    defaultbreak;    
    }
   }

   /**********************任务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就足够有余。
键盘是硬件层和系统层做的,不是用到按键时才去扫描。