OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 8127|回复: 7

STM32 简单多任务调度

[复制链接]

8

主题

21

帖子

0

精华

新手上路

积分
30
金钱
30
注册时间
2017-5-25
在线时间
20 小时
发表于 2017-9-1 21:37:37 | 显示全部楼层 |阅读模式

  STM32的开发目前大多数还开处于“裸奔”的阶段,处于开发成本的考虑,可能还未嵌入任何的RTOS系统,由于没有操作系统的支持,因而不能方便的对多任务进行调度和管理,在main函数中你可能会写成如下方式:
1.  int main(void)   
2.  {   
3.      while (1)   
4.      {   
5.          Task1(); // 调用任务1   
6.          Task2(); // 调用任务2   
7.      }   
8.  }  

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

        其中fTask为任务指针,指向具体的任务,uNextTick为该任务下一次执行的时间,uLenTick为任务的调度周期或叫调度频率,即每隔多长时间执行一次。
        按照这个结构,可以预先定义一个结构体数组,然后将要调用的任务和任务的调度时间按照如下方式罗列出来:
1.  // 任务列表   
2.  static sTask mTaskTab[] =   
3.  {   
4.       {Task_SysTick,    0, 0}   
5.      ,{Task1,           0, 10}    // 10ms执行一次   
6.      ,{Task2,           0, 200}   // 200ms执行一次      
7.  };  

        其中第一个任务Task_SysTick为计算系统时间的任务,用以获取上电后运行的时间(Task_SysTick任务相关代码附在文章后面)。这里默认任务下一次执行的时间为0,在main函数中,不断的轮询这个数组,然后将当前任务的下一次调用时间和当前时间比较,如果发现轮到该任务执行,就执行该任务,执行完成后,将该任务的下一次执行时间设为当前时间加任务的调度时间,然后按照此方法去执行下一个需要执行的任务,代码如下:
1.  while (1)   
2.  {   
3.      // 任务循环   
4.      for (i = 0; i < ARRAYSIZE(mTaskTab); i++)   
5.      {   
6.          if (mTaskTab.uNextTick <= GetTimingTick())   
7.          {   
8.              mTaskTab.uNextTick += mTaskTab.uLenTick;   
9.              mTaskTab.fTask();      
10.         }   
11.     }   
12. }   

        这样,就可以对多个任务做一个简单的调度,以后添加任务时只需要在mTaskTab表中添加即可,需要强调的是,由于执行每个任务也需要耗费时间,就会导致一个任务的实际调度周期可能会比设定的调度周期要长,这样会存在时间不准的情况,当然这仅仅是适合于对轮询周期不是很严格的任务,如果想要任务在严格的时间周期内执行或者需要更精确的时间处理,则必须采用定时器的方式了。
附:
        完整的main文件代码:
1.  #ifndef ARRAYSIZE   
2.  #define ARRAYSIZE(a) (sizeof(a) / sizeof((a)[0]))   
3.  #endif   
4.     
5.  // 任务结构   
6.  typedef struct{   
7.        void (*fTask)(void);   
8.        u64 uNextTick;   
9.        u32 uLenTick;   
10. }sTask;   
11.   
12.   
13. // 任务列表   
14. static sTask mTaskTab[] =   
15. {   
16.      {Task_SysTick,    0, 0}   
17.     ,{Task1,           0, 10}   // 10ms执行一次   
18.     ,{Task2,           0, 200}  // 200ms执行一次      
19.        
20.     // 在这之前添加任务   
21. };   
22.   
23. /*******************************************************************************  
24. * Function Name  : main  
25. * Description    : Main program.  
26. * Input          : None  
27. * Output         : None  
28. * Return         : None  
29. *******************************************************************************/   
30. int main(void)   
31. {   
32.     int i = 0;   
33.     // 硬件初始化   
34.     HW_init();   
35.     // 初始化系统Tick任务   
36.     dev_SysTick_init(void);   
37.     // ...     
38.     while (1)   
39.     {   
40.         // 任务循环   
41.         for (i = 0; i < ARRAYSIZE(mTaskTab); i++)   
42.         {   
43.             if (mTaskTab.uNextTick <= GetTimingTick())   
44.             {   
45.                 mTaskTab.uNextTick += mTaskTab.uLenTick;   
46.                 mTaskTab.fTask();      
47.             }   
48.         }   
49.     }   

}
Task_SysTick任务相关代码:
1.  volatile int64u g_TimingTick = 0;   
2.  volatile int64u g_TimingTickOld = 0;   
3.     
4.  //=================================================================================================   
5.  //【函 数 名 称】 void dev_SysTick_init(void)   
6.  //【参       数】   
7.  //【功       能】 初始化   
8.  //【返   回  值】 None   
9.  //【创   建  者】 2010-07-27 firehood   
10. //=================================================================================================   
11. void dev_SysTick_init(void)   
12. {   
13.     TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;   
14.   
15.     /* Time base configuration */   
16.     TIM_TimeBaseStructure.TIM_Period = 65535;                  
17.     TIM_TimeBaseStructure.TIM_Prescaler = 36000-1;   
18.     TIM_TimeBaseStructure.TIM_ClockDivision = 0;      
19.     TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;   
20.        
21.     TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);   
22.        
23.     TIM_SetCounter(TIM2, 0);   
24.   
25.     /* TIM enable counter */   
26.     TIM_Cmd(TIM2, ENABLE);   
27. }   
28.   
29. //=================================================================================================   
30. //【函 数 名 称】 void GetTimingTick(void)   
31. //【参       数】   
32. //【功       能】 获取MCU启动后的运行时间   
33. //【返   回  值】 MCU启动后的运行时间,单位ms   
34. //【创   建  者】 2010-07-27 firehood   
35. //=================================================================================================   
36. int64u GetTimingTick(void)   
37. {   
38.     return g_TimingTick;   
39. }   
40.   
41. //=================================================================================================   
42. //【函 数 名 称】 void Task_SysTick(void)   
43. //【参       数】   
44. //【功       能】 Tick任务,从TIM2获取系统时间   
45. //【返   回  值】 None   
46. //【创   建  者】 2010-07-27 firehood   
47. //=================================================================================================   
48. void Task_SysTick(void)   
49. {   
50.     int16u temp = TIM_GetCounter(TIM2);   
51.   
52.     if (temp > 1000)   
53.     {   
54.         TIM_SetCounter(TIM2, 0);   
55.         g_TimingTickOld = g_TimingTickOld + temp;   
56.         temp = 0;   
57.     }   
58.     g_TimingTick = g_TimingTickOld + temp;   
59. }  


正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

1

主题

35

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
318
金钱
318
注册时间
2016-10-17
在线时间
98 小时
发表于 2017-9-5 08:35:56 | 显示全部楼层
回复 支持 反对

使用道具 举报

7

主题

24

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
210
金钱
210
注册时间
2017-11-1
在线时间
67 小时
发表于 2017-11-21 17:24:09 | 显示全部楼层
有本书叫时间触发嵌入式系统设计模式,可以看看
回复 支持 反对

使用道具 举报

17

主题

354

帖子

0

精华

高级会员

Rank: 4

积分
797
金钱
797
注册时间
2017-5-21
在线时间
340 小时
发表于 2017-11-21 18:21:39 来自手机 | 显示全部楼层
当时51就是这么设计的
回复 支持 反对

使用道具 举报

0

主题

1

帖子

0

精华

新手上路

积分
22
金钱
22
注册时间
2019-8-2
在线时间
9 小时
发表于 2019-10-21 15:36:16 | 显示全部楼层
不知道为什么,我测试了一下,我的temp=0??
回复 支持 反对

使用道具 举报

28

主题

113

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1501
金钱
1501
注册时间
2021-8-10
在线时间
273 小时
发表于 2021-10-18 21:42:07 | 显示全部楼层
51上学过这个 时间片轮询,用起来挺舒服的。
回复 支持 反对

使用道具 举报

0

主题

8

帖子

0

精华

新手上路

积分
49
金钱
49
注册时间
2020-9-7
在线时间
4 小时
发表于 2021-10-19 10:17:24 | 显示全部楼层
有所收获,谢谢博主
回复 支持 反对

使用道具 举报

18

主题

151

帖子

0

精华

高级会员

Rank: 4

积分
508
金钱
508
注册时间
2020-4-22
在线时间
241 小时
发表于 2021-12-2 10:55:23 | 显示全部楼层
43.             if (mTaskTab.uNextTick <= GetTimingTick())   
44.             {   
45.                 mTaskTab.uNextTick += mTaskTab.uLenTick;   
46.                 mTaskTab.fTask();      

兄弟,这一段少了[i];是mTaskTab[i];
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-22 22:27

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表