打印
[应用相关]

STM32 简单多任务调度

[复制链接]
2375|7
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
Vitality1|  楼主 | 2015-3-28 10:51 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
STM32的开发目前大多数还开处于“裸奔”的阶段,处于开发成本的考虑,可能还未嵌入任何的RTOS系统,由于没有操作系统的支持,因而不能方便的对多任务进行调度和管理,在main函数中你可能会写成如下方式:
[cpp] view plaincopy


  • int main(void)  
  • {  
  •     while (1)  
  •     {  
  •         Task1(); // 调用任务1  
  •         Task2(); // 调用任务2  
  •     }  
  • }  

       但简单这样写的话会存在一个问题,假如任务1是一个很紧急的任务,如AD采样任务,需要不断的去执行,而任务2是一个不太紧急的任务,只要保证一段时间执行一次就行(如控制LED灯闪烁,只需要每1s钟闪烁一次),这样的话一是频繁的调用任务2占用了任务1执行的时间,二是任务2根本不需要这样频繁的执行,白白耗费了CPU的处理。因此可以考虑实现一个调度策略来解决这个问题。对于每个任务,我们可以定义这样一个结构:
[cpp] view plaincopy


  • typedef struct{  
  •       void (*fTask)(void);  
  •       int64u uNextTick;  
  •       int32u uLenTick;  
  • }sTask;  

        其中fTask为任务指针,指向具体的任务,uNextTick为该任务下一次执行的时间,uLenTick为任务的调度周期或叫调度频率,即每隔多长时间执行一次。
        按照这个结构,可以预先定义一个结构体数组,然后将要调用的任务和任务的调度时间按照如下方式罗列出来:
[cpp] view plaincopy


  • // 任务列表  
  • static sTask mTaskTab[] =   
  • {  
  •      {Task_SysTick,    0, 0}  
  •     ,{Task1,           0, 10}    // 10ms执行一次  
  •     ,{Task2,           0, 200}   // 200ms执行一次     
  • };  

        其中第一个任务Task_SysTick为计算系统时间的任务,用以获取上电后运行的时间(Task_SysTick任务相关代码附在**后面)。这里默认任务下一次执行的时间为0,在main函数中,不断的轮询这个数组,然后将当前任务的下一次调用时间和当前时间比较,如果发现轮到该任务执行,就执行该任务,执行完成后,将该任务的下一次执行时间设为当前时间加任务的调度时间,然后按照此方法去执行下一个需要执行的任务,代码如下:
[cpp] view plaincopy


  • while (1)  
  • {  
  •     // 任务循环  
  •     for (i = 0; i < ARRAYSIZE(mTaskTab); i++)  
  •     {  
  •         if (mTaskTab.uNextTick <= GetTimingTick())  
  •         {  
  •             mTaskTab.uNextTick += mTaskTab.uLenTick;  
  •             mTaskTab.fTask();      
  •         }  
  •     }  
  • }   

        这样,就可以对多个任务做一个简单的调度,以后添加任务时只需要在mTaskTab表中添加即可,需要强调的是,由于执行每个任务也需要耗费时间,就会导致一个任务的实际调度周期可能会比设定的调度周期要长,这样会存在时间不准的情况,当然这仅仅是适合于对轮询周期不是很严格的任务,如果想要任务在严格的时间周期内执行或者需要更精确的时间处理,则必须采用定时器的方式了。
附:
        完整的main文件代码:
[cpp] view plaincopy


  • #ifndef ARRAYSIZE  
  • #define ARRAYSIZE(a) (sizeof(a) / sizeof((a)[0]))  
  • #endif  
  •   
  • // 任务结构  
  • typedef struct{  
  •       void (*fTask)(void);  
  •       u64 uNextTick;  
  •       u32 uLenTick;  
  • }sTask;  
  •   
  •   
  • // 任务列表  
  • static sTask mTaskTab[] =   
  • {  
  •      {Task_SysTick,    0, 0}  
  •     ,{Task1,           0, 10}   // 10ms执行一次   
  •     ,{Task2,           0, 200}  // 200ms执行一次      
  •       
  •     // 在这之前添加任务  
  • };  
  •   
  • /*******************************************************************************
  • * Function Name  : main
  • * Description    : Main program.
  • * Input          : None
  • * Output         : None
  • * Return         : None
  • *******************************************************************************/  
  • int main(void)  
  • {  
  •     int i = 0;  
  •     // 硬件初始化  
  •     HW_init();  
  •     // 初始化系统Tick任务  
  •     dev_SysTick_init(void);  
  •     // ...   
  •     while (1)  
  •     {  
  •         // 任务循环  
  •         for (i = 0; i < ARRAYSIZE(mTaskTab); i++)  
  •         {  
  •             if (mTaskTab.uNextTick <= GetTimingTick())  
  •             {  
  •                 mTaskTab.uNextTick += mTaskTab.uLenTick;  
  •                 mTaskTab.fTask();      
  •             }  
  •         }  
  •     }   

}
Task_SysTick任务相关代码:
[cpp] view plaincopy


  • volatile int64u g_TimingTick = 0;  
  • volatile int64u g_TimingTickOld = 0;  
  •   
  • //=================================================================================================  
  • //【函 数 名 称】 void dev_SysTick_init(void)  
  • //【参       数】   
  • //【功       能】 初始化  
  • //【返   回  值】 None  
  • //【创   建  者】 2010-07-27 firehood  
  • //=================================================================================================  
  • void dev_SysTick_init(void)  
  • {  
  •     TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;  
  •   
  •     /* Time base configuration */  
  •     TIM_TimeBaseStructure.TIM_Period = 65535;                 
  •     TIM_TimeBaseStructure.TIM_Prescaler = 36000-1;   
  •     TIM_TimeBaseStructure.TIM_ClockDivision = 0;      
  •     TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;   
  •       
  •     TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);  
  •       
  •     TIM_SetCounter(TIM2, 0);  
  •   
  •     /* TIM enable counter */  
  •     TIM_Cmd(TIM2, ENABLE);  
  • }  
  •   
  • //=================================================================================================  
  • //【函 数 名 称】 void GetTimingTick(void)  
  • //【参       数】   
  • //【功       能】 获取MCU启动后的运行时间  
  • //【返   回  值】 MCU启动后的运行时间,单位ms  
  • //【创   建  者】 2010-07-27 firehood  
  • //=================================================================================================  
  • int64u GetTimingTick(void)  
  • {  
  •     return g_TimingTick;  
  • }  
  •   
  • //=================================================================================================  
  • //【函 数 名 称】 void Task_SysTick(void)  
  • //【参       数】   
  • //【功       能】 Tick任务,从TIM2获取系统时间  
  • //【返   回  值】 None  
  • //【创   建  者】 2010-07-27 firehood  
  • //=================================================================================================  
  • void Task_SysTick(void)  
  • {  
  •     int16u temp = TIM_GetCounter(TIM2);  
  •   
  •     if (temp > 1000)  
  •     {  
  •         TIM_SetCounter(TIM2, 0);  
  •         g_TimingTickOld = g_TimingTickOld + temp;  
  •         temp = 0;  
  •     }  
  •     g_TimingTick = g_TimingTickOld + temp;  
  • }  



沙发
powerful1| | 2015-3-28 11:11 | 只看该作者
还未嵌入任何的RTOS系统,由于没有操作系统的支持,因而不能方便的对多任务进行调度和管理,可以参照这个设计

使用特权

评论回复
板凳
energy1| | 2015-3-28 11:31 | 只看该作者
使STM32的开发目告别“裸奔”

使用特权

评论回复
地板
runningwzf| | 2015-3-28 21:46 | 只看该作者
调度只是操作系统的一个功能,另外还有同步、资源控制、优先级呢?
在STM的产品上一直用ucos,稳定性、可移植性均非常好,建议大家用

使用特权

评论回复
5
quray1985| | 2015-3-29 09:39 | 只看该作者
哇,讲到了我的难处
我上次用ad的时候就遇到了这个问题
果断收藏

使用特权

评论回复
6
搞IT的| | 2015-3-29 10:25 | 只看该作者
也遇到过类似问题,不过没有进行楼主这样的总结。。

使用特权

评论回复
7
lsarmlsarm| | 2015-3-29 20:59 | 只看该作者
学习

使用特权

评论回复
8
lovecat2015| | 2015-3-30 16:46 | 只看该作者
讲的是stm32与ucos ii的应用,ucos是很稳定的系统,并且开源
很有帮助,谢谢

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

81

主题

421

帖子

9

粉丝