分享一个不错的【程序框架】+【按键状态机】+【LED状态机】程序

2019-07-20 22:17发布

本帖最后由 流年丶 于 2019-7-7 20:52 编辑

游客,如果您要查看本帖隐藏内容请回复
用了几年的前后台程序框架,稳定可靠,保证每次执行的任务都为最高优先级任务,楼下会对该程序框架做一些说明。
按键状态机:支持短按,长按,双击处理,程序简洁,简单易懂。
LED状态机:支持各个频率的LED闪烁,常亮,常暗操作。
注:该程序是从 基于2G通讯项目中截取下来的两个模块,项目源码不好分享,有兴趣可以加我Q:842936992
//本程序只供学习使用,未经作者许可,不得用于其它任何用途
//引用请注明出处,有问题可在本帖中提出讨论,也可加我Q一起交流探讨



友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
49条回答
流年丶
1楼-- · 2019-07-21 00:36
本系统采用不可剥夺型内核,即当某个任务在执行时,必须等到当前任务执行完毕后,才交出CPU的使用权。每个任务被赋予不同的优先级,本系统中共有0~63个优先级,由8位变量MainTask和8位的数组SubTask[8]共同管理。当主任务MainTask的第0位置位,则表明SubTask[0]非零,主任务0下存在被激活的子任务,若SubTask[0] = 0x01,则表明优先级为0的任务已被激活,该任务具有最高的优先级。MainTask、SubTask[8]与优先级的关系如图所示。
当主任务MainTask的第7位置位,则表明主任务7下存在被激活的子任务,若SubTask[7] = 0x80,则表明优先级为63的任务已被激活,该任务具有最低的优先级。
流年丶
2楼-- · 2019-07-21 02:45
任务调度的流程如图所示。
流年丶
3楼-- · 2019-07-21 04:28
通常情况系统处于休眠模式,当被定时器唤醒需要扫描任务时,先判断主任务号MainTask是否为0,如果为0,则继续进入休眠状态,否则,由MainTask获取当前最高的主任务,代码如下:
      while(1)
      {
          while(SYS_MainTask)
          {
              INT8U temp = SYS_TaskMapTbl[SYS_MainTask];
              SYS_TaskTbl[temp].go_fun(temp);
          }
      }
TaskMapTbl[]是一个任务优先级查询表,输入一个8位数,输出从第0位开始,第1个bit1所在的位数,例如0X01的第0位为bit1,因此TaskMapTbl[0x01]=0,0X06的第1位和第2位为bit1,第1位在第2位的前面(优先更高),因此TaskMapTbl[0x06]=1。
可见,语句INT8U temp = TaskMapTbl[MainTask];获取了当前优先级最高的主任务。
TaskTbl[]是一个数组,该数组中的成员是函数指针,数组共有8个数据成员,每个数据成员为主任务的函数入口地址,其定义如下。
typedef struct
{
    void (*go_fun)(INT8U prio);                //带参数的函数指针 用于执行任务函数
}SYS_TaskStruct;
const SYS_TaskStruct  TaskTbl[8] = {           //任务列表 TASK0优先级最高
    TASK0,
    TASK1,
    TASK2,
    TASK3,
    TASK4,
    TASK5,
    TASK6,
    TASK7
};
可见,语句TaskTbl[temp].go_fun(temp);即执行主任务函数。
进入主任务函数后,同样道理,可先由相应的SubTask[]来获取并执行该主任务下最高优先权的子任务。
由于任务间的调用经常是相互的,某一任务执行完成后,有可能激活另一优先权更高的任务,系统在每个任务执行完成后,重新判断MainTask,因此可确保下一个被执行的任务一定是优先权最高的任务。
流年丶
4楼-- · 2019-07-21 06:44
 精彩回答 2  元偷偷看……
流年丶
5楼-- · 2019-07-21 11:54
 精彩回答 2  元偷偷看……
流年丶
6楼-- · 2019-07-21 13:02
/*****************************************************************************
Function name : APP_LED_Task
Description: APP LED模块的任务函数,在HCI_Task中当HCI_LED事件被置位的时候,将被执行
Input: NONE               
Return: NONE     
Notes:
******************************************************************************/
void APP_LED_Task(void)
{
    U8 HWOpMode;
    U8 ucIndex;
    for(ucIndex = 0; ucIndex < LED_MAX; ucIndex++)
    {
        HWOpMode = LED_OFF;
        if(APP_LED_FLASH == s_AppLedTB[ucIndex].OpMode)
        {
            if(s_AppLedTB[ucIndex].usDelayCnt >= TASK_HCI_LED_TB)
            {
                s_AppLedTB[ucIndex].usDelayCnt -= TASK_HCI_LED_TB;
            }
            else
            {
                s_AppLedTB[ucIndex].usDelayCnt = 0;
            }
            
            if(s_AppLedTB[ucIndex].usDelayCnt > 0)
            {
                continue;
            }
            
            HWOpMode = ((LED_ON == s_AppLedTB[ucIndex].HWState) ? (LED_OFF) : (LED_ON));
            s_AppLedTB[ucIndex].usDelayCnt =  s_AppLedTB[ucIndex].usPeriod;
            
            
            if(255 == s_AppLedTB[ucIndex].ucTime)
            {
                continue;  
            }
            if(--s_AppLedTB[ucIndex].ucTime == 0)
            {
                s_AppLedTB[ucIndex].OpMode = APP_LED_OFF;
            }   
        }
        else
        {
            
            if(s_AppLedTB[ucIndex].ulTimeCnt >= TASK_HCI_LED_TB)
            {
                s_AppLedTB[ucIndex].ulTimeCnt -= TASK_HCI_LED_TB;
            }
            else
            {
                s_AppLedTB[ucIndex].ulTimeCnt = 0;
            }
            
            if((s_AppLedTB[ucIndex].ulTimeCnt > 0) || (~0 == s_AppLedTB[ucIndex].ulTimeOut))
            {
                continue;
            }
            HWOpMode = LED_OFF;
        }
        
        if(HWOpMode == s_AppLedTB[ucIndex].HWState)
        {
            continue;
        }
        BSP_LED_Operate(ucIndex, HWOpMode);
        s_AppLedTB[ucIndex].HWState = HWOpMode;        
    }
}

一周热门 更多>