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

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






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值