在有嵌入式操作系统的情况下,可以利用多任务和信号量,事件等设计嵌入式软件。但是在没有操作系统的裸机中,更需要有好的架构。例如利用事件和状态机模拟实现多任务,或者利用定时器和消息队列,信号量等模拟实现多任务,有了多任务就能灵活的设计软件架构。

    借住定时器和任务队列实现的一种模拟多任务:

    1. #include <stdio.h>
    2. #include "timTask.h"
    3. #include "disp.h"
    4. /*=====================================================
    5. = 变量定义
    6. =====================================================*/
    7. //任务队列
    8. typedef struct{
    9. char flagState; //运行方式 0: 无任务
    10. // 1: 运行
    11. char flagRun; //完成状态 0: 正在计数
    12. // 1: 计数完成
    13. char flagType; //处理方式 0: 主任务处理
    14. // 1: 中断处理
    15. ulong cntRun; //运行计数器
    16. ulong numCircle; //循环计数器
    17. void (*pTaskFunc)(void); //任务
    18. }TypeTimTask;
    19. TypeTimTask timTaskTab[TIM_TASK_NUMBER];
    20. /*************************************************************************
    21. * 函数原型:
    22. * 功能描述:
    23. * 入口参数:
    24. * 出口参数:
    25. * 返 回 值:
    26. *************************************************************************/
    27. void TimTaskInit(void)
    28. {
    29. int i;
    30. for (i=0; i<TIM_TASK_NUMBER; i++)
    31. {
    32. timTaskTab[i].pTaskFunc = 0;
    33. timTaskTab[i].cntRun = 0;
    34. timTaskTab[i].numCircle = 0;
    35. timTaskTab[i].flagRun = 0;
    36. timTaskTab[i].flagState = 0;
    37. }
    38. SPT_register_call_back(TimTaskUpdate);
    39. SPT_set(TIM_TASK_PERIOD *64 / 1000);
    40. }
    41. /*************************************************************************
    42. * 函数原型:
    43. * 功能描述:
    44. * 入口参数:
    45. * 出口参数:
    46. * 返 回 值:
    47. *************************************************************************/
    48. short TimTaskAdd(ulong fsttim, ulong cirtim, void (*pTaskFunc)(void), uchar type)
    49. {
    50. int i;
    51. int pos = -1;
    52. //查找位置
    53. for (i=0; i<TIM_TASK_NUMBER; i++)
    54. {
    55. if (timTaskTab[i].pTaskFunc == pTaskFunc)
    56. {
    57. pos = i;
    58. break;
    59. }
    60. if ((pos == -1) && (timTaskTab[i].flagState == 0))
    61. {
    62. pos = i;
    63. }
    64. }
    65. //任务已满
    66. if (pos == -1)
    67. {
    68. return -1;
    69. }
    70. //
    71. timTaskTab[pos].pTaskFunc = pTaskFunc;
    72. timTaskTab[pos].cntRun = fsttim / TIM_TASK_PERIOD;
    73. timTaskTab[pos].numCircle = cirtim / TIM_TASK_PERIOD;
    74. timTaskTab[pos].flagRun = 0;
    75. timTaskTab[pos].flagType = type;
    76. timTaskTab[pos].flagState = 1;
    77. return 0;
    78. }
    79. /*************************************************************************
    80. * 函数原型:
    81. * 功能描述:
    82. * 入口参数:
    83. * 出口参数:
    84. * 返 回 值:
    85. *************************************************************************/
    86. void TimTaskDel(void (*pTaskFunc)(void))
    87. {
    88. int i;
    89. for (i=0; i<TIM_TASK_NUMBER; i++)
    90. {
    91. if (timTaskTab[i].pTaskFunc == pTaskFunc)
    92. {
    93. timTaskTab[i].flagState = 0;
    94. timTaskTab[i].flagRun = 0;
    95. return;
    96. }
    97. }
    98. }
    99. /*************************************************************************
    100. * 函数原型:
    101. * 功能描述:
    102. * 入口参数:
    103. * 出口参数:
    104. * 返 回 值:
    105. *************************************************************************/
    106. void TimTaskUpdate(void)
    107. {
    108. int i;
    109. SPT_set(TIM_TASK_PERIOD *64 / 1000);
    110. for (i=0; i<TIM_TASK_NUMBER; i++)
    111. {
    112. if (timTaskTab[i].flagState != 0)
    113. {
    114. if (timTaskTab[i].cntRun != 0)
    115. {
    116. timTaskTab[i].cntRun--;
    117. }
    118. else
    119. {
    120. //判断处理位置
    121. if (timTaskTab[i].flagType != 0)
    122. (*timTaskTab[i].pTaskFunc)();
    123. else
    124. timTaskTab[i].flagRun = 1;
    125. //判断重载
    126. if (timTaskTab[i].numCircle)
    127. timTaskTab[i].cntRun = timTaskTab[i].numCircle;
    128. else
    129. timTaskTab[i].flagState = 0;
    130. }
    131. }
    132. }
    133. }
    134. /*************************************************************************
    135. * 函数原型:
    136. * 功能描述:
    137. * 入口参数:
    138. * 出口参数:
    139. * 返 回 值:
    140. *************************************************************************/
    141. void TimTaskProc(void)
    142. {
    143. int i;
    144. for (i=0; i<TIM_TASK_NUMBER; i++)
    145. {
    146. if (timTaskTab[i].flagRun != 0)
    147. {
    148. timTaskTab[i].flagRun = 0;
    149. (*timTaskTab[i].pTaskFunc)();
    150. }
    151. }
    152. }

    可以借住函数指针实现一种灵活的菜单和按键实时处理结构。类似于windows下win32的消息驱动机制,
    通过中断等方式把实时事件封装成消息。以下为定义界面刷新显示和响应按键处理的结构: