STM32的开发目前大多数还开处于“裸奔”的阶段,处于开发成本的考虑,可能还未嵌入任何的RTOS系统,由于没有操作系统的支持,因而不能方便的对多任务进行调度和管理,在main函数中你可能会写成如下方式:
[cpp] view plaincopy 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的处理。因此可以考虑实现一个调度策略来解决这个问题。对于每个任务,我们可以定义这样一个结构:
[cpp] view plaincopy 1.
typedef struct{ 2.
void (*fTask)(
void); 3. int64u uNextTick; 4. int32u uLenTick; 5. }sTask;
其中fTask为任务指针,指向具体的任务,uNextTick为该任务下一次执行的时间,uLenTick为任务的调度周期或叫调度频率,即每隔多长时间执行一次。 按照这个结构,可以预先定义一个结构体数组,然后将要调用的任务和任务的调度时间按照如下方式罗列出来:
[cpp] view plaincopy 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函数中,不断的轮询这个数组,然后将当前任务的下一次调用时间和当前时间比较,如果发现轮到该任务执行,就执行该任务,执行完成后,将该任务的下一次执行时间设为当前时间加任务的调度时间,然后按照此方法去执行下一个需要执行的任务,代码如下:
[cpp] view plaincopy 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文件代码:[cpp] view plaincopy 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任务相关代码:[cpp] view plaincopy 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. }
一周热门 更多>