单片机程序构架_单片机编程架构标准

Task_SysTime();

Task_MenuProc();

Task_MtnLink();

Task_CommProc();

}
int main( void )
{
Sys_Init(); //系统初始化

while( 1 )                                
{ 
	Task_Tick();	//任务轮询

	if( 0 == sem_wait( &gSem_EVT_QUIT_APP ) ) 
	   break;     //应用退出
}

}


  
 以上为借助信号量和定时器实现的一种简单的模拟多任务,其实也算不上是多任务,因为如果一个函数执行时间很长,如何打断它?



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





#include <stdio.h>
#include “timTask.h”
#include “disp.h”

/=====================================================
= 变量定义
=====================================================
/
//任务队列
typedef struct{
char flagState; //运行方式 0: 无任务
// 1: 运行
char flagRun; //完成状态 0: 正在计数
// 1: 计数完成
char flagType; //处理方式 0: 主任务处理
// 1: 中断处理
ulong cntRun; //运行计数器
ulong numCircle; //循环计数器
void (*pTaskFunc)(void); //任务
}TypeTimTask;

TypeTimTask timTaskTab[TIM_TASK_NUMBER];

/*************************************************************************

  • 函数原型:

  • 功能描述:

  • 入口参数:

  • 出口参数:

  • 返 回 值:
    *************************************************************************/
    void TimTaskInit(void)
    {
    int i;

    for (i=0; i<TIM_TASK_NUMBER; i++)
    {
    timTaskTab[i].pTaskFunc = 0;
    timTaskTab[i].cntRun = 0;
    timTaskTab[i].numCircle = 0;
    timTaskTab[i].flagRun = 0;
    timTaskTab[i].flagState = 0;
    }
    SPT_register_call_back(TimTaskUpdate);
    SPT_set(TIM_TASK_PERIOD *64 / 1000);
    }

/*************************************************************************

  • 函数原型:

  • 功能描述:

  • 入口参数:

  • 出口参数:

  • 返 回 值:
    *************************************************************************/
    short TimTaskAdd(ulong fsttim, ulong cirtim, void (*pTaskFunc)(void), uchar type)
    {
    int i;
    int pos = -1;
    //查找位置
    for (i=0; i<TIM_TASK_NUMBER; i++)
    {
    if (timTaskTab[i].pTaskFunc == pTaskFunc)
    {
    pos = i;
    break;
    }
    if ((pos == -1) && (timTaskTab[i].flagState == 0))
    {
    pos = i;
    }
    }
    //任务已满
    if (pos == -1)
    {
    return -1;
    }
    //
    timTaskTab[pos].pTaskFunc = pTaskFunc;
    timTaskTab[pos].cntRun = fsttim / TIM_TASK_PERIOD;
    timTaskTab[pos].numCircle = cirtim / TIM_TASK_PERIOD;
    timTaskTab[pos].flagRun = 0;
    timTaskTab[pos].flagType = type;
    timTaskTab[pos].flagState = 1;

    return 0;
    }

/*************************************************************************

  • 函数原型:

  • 功能描述:

  • 入口参数:

  • 出口参数:

  • 返 回 值:
    *************************************************************************/
    void TimTaskDel(void (*pTaskFunc)(void))
    {
    int i;

    for (i=0; i<TIM_TASK_NUMBER; i++)
    {
    if (timTaskTab[i].pTaskFunc == pTaskFunc)
    {
    timTaskTab[i].flagState = 0;
    timTaskTab[i].flagRun = 0;
    return;
    }
    }
    }

/*************************************************************************

  • 函数原型:

  • 功能描述:

  • 入口参数:

  • 出口参数:

  • 返 回 值:
    *************************************************************************/
    void TimTaskUpdate(void)
    {
    int i;

    SPT_set(TIM_TASK_PERIOD *64 / 1000);

    for (i=0; i<TIM_TASK_NUMBER; i++)
    {
    if (timTaskTab[i].flagState != 0)
    {
    if (timTaskTab[i].cntRun != 0)
    {
    timTaskTab[i].cntRun–;
    }
    else
    {
    //判断处理位置
    if (timTaskTab[i].flagType != 0)
    (*timTaskTab[i].pTaskFunc)();
    else
    timTaskTab[i].flagRun = 1;
    //判断重载
    if (timTaskTab[i].numCircle)
    timTaskTab[i].cntRun = timTaskTab[i].numCircle;
    else
    timTaskTab[i].flagState = 0;
    }
    }
    }
    }

/*************************************************************************

  • 函数原型:

  • 功能描述:

  • 入口参数:

  • 出口参数:

  • 返 回 值:
    *************************************************************************/
    void TimTaskProc(void)
    {
    int i;

    for (i=0; i<TIM_TASK_NUMBER; i++)
    {
    if (timTaskTab[i].flagRun != 0)
    {
    timTaskTab[i].flagRun = 0;
    (*timTaskTab[i].pTaskFunc)();
    }
    }
    }


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





#ifndef _PAGE_H
#define _PAGE_H

#include “heads.h”

/*=====================================================

=====================================================/
typedef struct{
void (
OnPaint)(void);
void (* OnKey)(short);
}TypePage;

/*=====================================================

=====================================================*/
void WndPageSet(const TypePage *pg, int type = 0);
TypePage * WndGetPage(void);
void WndPageEsc(void);
void WndOnKey(short key);
void WndOnPaint(void);
void WndMenuInit(const char *pmn, char mline);
void WndMenuSelet(int m);
char WndMenuGetSelet(void);
long WndGetPaseword(int x, int y, char *psw, int len, long qevent);




#include “pageWnd.h”

/*=====================================================

=====================================================/
char flagPaint = 0;
void (
pOnPaint)(void) = 0;
void (* pOnKey)(short) = 0;

const char *pMenuStr;
uchar menuSelect = 0;
uchar menuLine = 0;
uchar menuTop;

TypePage *pageCurrent;
TypePage *pageTreeTab[10];
uchar pageIndex = 0;

/*=====================================================

=====================================================*/
void WndDrawMenu(void);

/*************************************************************************

  • 函数原型:
  • 功能描述:
  • 入口参数:
  • 出口参数:
  • 返 回 值:
    *************************************************************************/
    void WndPageSet(const TypePage *pg, int type)
    {
    if (pg == &pageMain) //防止出错
    {
    pageIndex = 0;
    }
    else if (type == 0)
    {
    pageTreeTab[pageIndex++] = pageCurrent;
    }
    pageCurrent = (TypePage *)pg;
    pOnPaint = pg->OnPaint;
    pOnKey = pg->OnKey;
    flagPaint = 1;
    }

/*************************************************************************

  • 函数原型:
  • 功能描述:
  • 入口参数:
  • 出口参数:
  • 返 回 值:
    *************************************************************************/
    TypePage * WndGetPage(void)
    {
    return pageCurrent;
    }

/*************************************************************************

  • 函数原型:

  • 功能描述:

  • 入口参数:

  • 出口参数:

  • 返 回 值:
    *************************************************************************/
    void WndPageEsc(void)
    {
    TypePage *pg;

    if (pageIndex != 0)
    {
    pageIndex–;
    pg = pageTreeTab[pageIndex];
    }
    else
    {
    pg = (TypePage *)&pageMain;
    }
    pageCurrent = pg;
    pOnPaint = pg->OnPaint;
    pOnKey = pg->OnKey;
    flagPaint = 1;
    }

/*************************************************************************

  • 函数原型:
  • 功能描述:
  • 入口参数:
  • 出口参数:
  • 返 回 值:
    *************************************************************************/
    void WndOnPaint(void)
    {
    if (flagPaint != 0)
    {
    flagPaint = 0;
    (*pOnPaint)();
    }
    }

/*************************************************************************

  • 函数原型:
  • 功能描述:
  • 入口参数:
  • 出口参数:
  • 返 回 值:
    *************************************************************************/
    void WndOnKey(short key)
    {
    if (pOnKey != 0)
    {
    (*pOnKey)(key);
    }
    }

/*************************************************************************

  • 函数原型:
  • 功能描述:
  • 入口参数:
  • 出口参数:
  • 返 回 值:
    *************************************************************************/
    void WndMenuInit(const char *pmn, char mline)
    {
    menuSelect = 0;
    pMenuStr = pmn;
    menuLine = mline;
    menuTop = 0;
    WndDrawMenu();
    }

/*************************************************************************

  • 函数原型:

  • 功能描述:

  • 入口参数:

  • 出口参数:

  • 返 回 值:
    *************************************************************************/
    void WndMenuSelet(int m)
    {
    //光标滑动
    if (m > 0) //下移
    {
    menuSelect++;
    if (menuSelect == menuLine)
    menuSelect = 0;

      if (menuSelect > menuTop + 4)
      {
      	if (menuLine < menuTop + 4)
      		menuTop = menuLine - 4;
      	else
      		menuTop = menuSelect - 4;
      }
    

    }
    else if (m < 0) //上移
    {
    if (menuSelect == 0)
    menuSelect = menuLine - 1;
    else
    menuSelect–;
    }
    //图框移动
    if (menuSelect < menuTop) //上移
    {
    menuTop = menuSelect;
    }
    else if (menuSelect >= menuTop + 4) //下移
    {
    menuTop = menuSelect - 3;
    }

    WndDrawMenu();
    }

/*************************************************************************

  • 函数原型:
  • 功能描述:
  • 入口参数:
  • 出口参数:
  • 返 回 值:
    *************************************************************************/
    char WndMenuGetSelet(void)
    {
    return menuSelect + 1;
    }

/*************************************************************************

  • 函数原型:

  • 功能描述:

  • 入口参数:

  • 出口参数:

  • 返 回 值:
    *************************************************************************/
    void WndDrawMenu(void)
    {
    int i;

    char buf[17];
    const char *pmn = pMenuStr + menuTop * 16;

    DispClr();
    for (i=0; i<4; i++)
    {
    if (menuTop + i == menuLine)
    break;
    memcpy(buf, pmn, 16);
    buf[16] = ‘\0’;
    if (menuSelect == menuTop + i)
    DispSetStyle(DISP_POSITION | DISP_REVERSE | DISP_7x9);
    else
    DispSetStyle(DISP_POSITION | DISP_NORMAL | DISP_7x9);
    DispString(0, i * 2, buf);
    pmn += 16;
    }
    }

/*************************************************************************

  • 函数原型:

  • 功能描述:

  • 入口参数:

  • 出口参数:

  • 返 回 值:
    *************************************************************************/
    long WndGetPaseword(int x, int y, char *psw, int len, long qevent)
    {
    int pin = 0;
    long keyevt;
    char key;
    char buf[20];

    memset(buf, ‘', len);
    buf[len] = ‘\0’;
    PSW_INPUT_LOOP:
    DispString(x, y, buf);
    keyevt = delay_and_wait_key(0, EXIT_KEY_ALL, 0);
    if (keyevt == qevent)
    {
    psw[0] = ‘\0’;
    return keyevt;
    }
    switch (keyevt)
    {
    case EXIT_KEY_0:
    key = ‘0’;
    break;
    case EXIT_KEY_1:
    key = ‘1’;
    break;
    case EXIT_KEY_2:
    key = ‘2’;
    break;
    case EXIT_KEY_3:
    key = ‘3’;
    break;
    case EXIT_KEY_4:
    key = ‘4’;
    break;
    case EXIT_KEY_5:
    key = ‘5’;
    break;
    case EXIT_KEY_6:
    key = ‘6’;
    break;
    case EXIT_KEY_7:
    key = ‘7’;
    break;
    case EXIT_KEY_8:
    key = ‘8’;
    break;
    case EXIT_KEY_9:
    key = ‘9’;
    break;
    case EXIT_KEY_COMM:
    if (pin != 0)
    {
    buf[–pin] = '
    ’;
    }
    goto PSW_INPUT_LOOP;
    break;
    case EXIT_KEY_ENTER:
    psw[pin] = 0;
    return 0;
    default:
    goto PSW_INPUT_LOOP;
    }
    if (pin != len)
    {
    psw[pin] = key;
    buf[pin] = ‘*’;
    pin++;
    }
    goto PSW_INPUT_LOOP;
    }



在软件设计时,如果添加界面和对应的按键处理,很灵活,只需要新添加一个文件就可以了,文件的内容,只需要实现OnPain和对应的OnKey





#include “PageMenu.h”

/*=====================================================

=====================================================/
const char mainMenuTab[] = /

1234567890123456*/"\

  1. 现场采集 \
  2. 数据上传 \
  3. 存储状态查询 \
  4. 时间设置 \
  5. 对比度设置 \
  6. 恢复出厂设置 \
  7. 关于 ";

/*=====================================================

=====================================================*/
void PageMenuOnPain(void);
void WndMenuOnKey(short key);

const TypePage pageMenu = {PageMenuOnPain, WndMenuOnKey};

/*************************************************************************

  • 函数原型:
  • 功能描述:
  • 入口参数:
  • 出口参数:
  • 返 回 值:
    *************************************************************************/
    void PageMenuOnPain(void)
    {
    WndMenuInit(mainMenuTab, 7);
    }

/*************************************************************************

  • 函数原型:

  • 功能描述:

  • 入口参数:

  • 出口参数:

  • 返 回 值:
    *************************************************************************/
    void WndMenuOnKey(short key)
    {
    int res;

    switch (key)
    {
    case KEY_F1:
    case KEY_ENTER:
    res = WndMenuGetSelet();
    switch (res)
    {
    case 1:
    WndPageSet(&pageSimp);
    break;
    case 2:
    WndPageSet(&pagePclink);
    break;
    case 3:
    WndPageSet(&pageInquire);
    break;
    case 4:
    WndPageSet(&pageRtc);
    break;
    case 5:
    WndPageSet(&pageGray);
    break;
    case 6:
    SPageInit();
    WndPageSet(&pageMenu, 1);
    break;
    case 7:
    WndPageSet(&pageAbout);
    break;
    }
    break;
    case KEY_F2:
    case KEY_F3:
    WndPageSet(&pageMain);
    break;
    case KEY_1:
    WndPageSet(&pageSimp);
    break;
    case KEY_2:
    WndPageSet(&pagePclink);
    break;
    case KEY_3:
    WndPageSet(&pageInquire);
    break;
    case KEY_4:
    WndPageSet(&pageRtc);
    break;
    case KEY_5:
    WndPageSet(&pageGray);
    break;
    case KEY_6:
    SPageInit();
    WndPageSet(&pageMenu, 1);
    break;
    case KEY_7:
    WndPageSet(&pageAbout);
    break;
    case KEY_UP:
    WndMenuSelet(-1);
    break;
    case KEY_DOWN:
    WndMenuSelet(1);
    break;
    case KEY_POWER:
    WndPageSet(&pagePower);
    break;
    }
    }


  
 pageMain,pageAbout,pageRtc,pagePclink等文件,他们的结构很类似。都是实现了OnPaint和OnKey函数。  
 如:pagePclink.c文件内容:  
 实现了PagePclinkOnPaint和PagePclinOnKey函数.



CommPclink函数是自己想要实现的功能,可以自己定义。





#include “pagePclink.h”

/*=====================================================

=====================================================*/
void PagePclinkOnPaint(void);
void PagePclinOnKey(short key);

const TypePage pagePclink = {PagePclinkOnPaint, PagePclinOnKey};

/*************************************************************************

  • 函数原型:
  • 功能描述:
  • 入口参数:
  • 出口参数:
  • 返 回 值:
    *************************************************************************/
    void PagePclinkOnPaint(void)
    {
    DispClr();
    DispSetStyle(DISP_CENTER | DISP_REVERSE | DISP_7x9);
    DispString(0, 0, " 数据上传 ");
    DispSetStyle(DISP_POSITION|DISP_NORMAL|DISP_7x9);
    DispString(0, 6, “[连接] [返回]”);
    }

/*************************************************************************

  • 函数原型:
  • 功能描述:
  • 入口参数:
  • 出口参数:
  • 返 回 值:
    *************************************************************************/
    void PagePclinOnKey(short key)
    {
    switch (key)
    {
    case KEY_F1:
    CommPclink();
    break;
    case KEY_F3:
    WndPageEsc();
    break;
    }
    }



#ifndef _PAGE_POWER_H
#define _PAGE_POWER_H

#include “pageWnd.h”

/*=====================================================

=====================================================*/
extern const TypePage pagePower;

#endif

#include “PagePower.h”
#include “disp.h”

/*=====================================================

=====================================================*/
void PagePowerOnPaint(void);
void PagePowerOnKey(short key);

const TypePage pagePower = {PagePowerOnPaint, PagePowerOnKey};

/*************************************************************************

  • 函数原型:
  • 功能描述:
  • 入口参数:
  • 出口参数:
  • 返 回 值:
    *************************************************************************/
    void PagePowerOnPaint(void)
    {
    DispClr();
    DispSetStyle(DISP_CENTER | DISP_REVERSE | DISP_7x9);
    DispString(0, 0, " 电源管理 ");
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值