系统定时简易封装

2009年06月24日 22:14    发布者:machunshui
裸奔的时候,
因为在一个子任务当中,
为提高效率,不能傻等,
需要系统定时的情况很多,
处理起来比较麻烦,
如果对系统定时器进行简单的封装,
就会比较方便,

下面的就是我写的一个用系统定时器封装后处理闪烁灯的例子:

main.h:

#ifndef _MAIN_H
#define _MAIN_H

#include

#define MAX_SYSTIMER_COUNT 6
extern unsigned short sysTimer;


unsigned char SetSysTimer(unsigned char id,unsigned short value);
unsigned char GetSysTimer(unsigned char id);

#endif


main.c:

#include "main.h"
#include "led.h"

__CONFIG(INTIO & WDTDIS & PWRTEN & MCLREN & CP & CPD & BOREN & IESODIS & FCMEN & LVPDIS & DEBUGEN & WP0 & BORV21 );

unsigned char t0InitValue;


unsigned short sysTimer;


////////////初始化timer0//////////////////////
void InitTimer0(void)
{

    OPTION = 0x06;                    //1:128分频
   
    //8M 时钟,10ms定时
    t0InitValue = 256-(20000/128);    /*256-100=156us,定时10ms = 20000 step/128 = 156.25*/
    TMR0 = t0InitValue;
   
    T0IF = 0;
    T0IE = 1;                        //开中断
}

////////////////初始化系统定时/////////////////////////////////
void InitSysTimer(void)
{
    unsigned char i;
    for(i = 0; i < MAX_SYSTIMER_COUNT; i++)
    {
        sysTimer = 0;
    }   
}

//////////////////////系统定时器计数/////////////////////////////
void CountSysTimer(void)
{
    unsigned char i;
    for(i = 0; i < MAX_SYSTIMER_COUNT; i++)
    {
        if(sysTimer > 0)
            sysTimer--;
    }   
}

////////////////////设置系统定时器/////////////////////////////////////////
unsigned char SetSysTimer(unsigned char id,unsigned short value)
{
    if(id < MAX_SYSTIMER_COUNT)
    {
        sysTimer = value;
        return 1;
    }
    else
        return 0;   
}

/////////////////////获取系统定时状态////////////////////////////////////////
unsigned char GetSysTimer(unsigned char id)
{
    if(sysTimer == 0)
        return 1;
    else
        return 0;
}                    

/////////////////系统初始化/////////////////////   
void InitSys(void)
{
    INTCON = 0;            //关闭总中断,禁止外设,timer0,外部,电平中断,清除timer0,外部,电平中断标志
   
    ANSEL = 0;
    ANSELH = 0;            //所有IO都为数字口

    InitLedFlash();
   
    InitSysTimer();        //初始化系统定时器
    InitTimer0();        //初始化定时器0
    PEIE = 1;            //开外设中断
    GIE = 1;            //开总中断
}


///////////中断函数//////////////
void interrupt ISR(void)
{
    if(T0IE && T0IF)
    {
        CountSysTimer();//系统定时器计数
        TMR0 = t0InitValue;
        T0IF = 0;
    }   
}


//////////////////主函数///////////////////////   
void main()
{
    OSCCON = 0x78;//时钟8M,时钟模式由配置字决定
    InitSys();   
    while(1)
    {
        FlashLed();
    }        
}


led.c:

#include "main.h"
#include "led.h"

void InitLedFlash(void)
{
    TRISD0 = 0;//输出
}

void FlashLed()
{
    if(GetSysTimer(0))
    {
        RD0 ^= 1;
        SetSysTimer(0,100);//100*10ms = 1s
    }   
}
该文章有附件资料,如需下载请访问 电脑版

网友评论

machunshui 2009年06月24日
带proteus仿真的完整工程:
sz_kd 2009年06月25日
呵呵,采用状态机就是避免死等
machunshui 2009年06月25日
实际上状态机的叫法过于玄乎,
就是一种任务分割而已,
就是把任务分割称若干断不可再分割的代码段,
根据条件执行这些代码段.

实际上这种封装带来的好处是不死等延时处理的方便,
而不是代替任务分割这种方法.
古道热肠 2009年07月07日
呵呵,写得不错,如果用Bool变量作为布尔型值来处理,更省内存.
machunshui 2009年07月07日
呵呵,
我觉得这种封装真的很好用啊.

我写的那个" 基于PIC的I2C从动模块的键盘,显示例子",

键盘延时和数码管显示闪烁延时用起来很方便.
machunshui 2009年07月07日
用位结构的省RAM,
但是多几行代码,
运行速度降低了,

这个东西要在定时中断里面不断扫描,
还是快一点好
machunshui 2009年07月07日
要说改进可以把void CountSysTimer(void)采用宏定义的方法,
省去函数调用,
在定时器中断里面运行速度快一点.
McuPlayer 2009年07月07日
嗯不错,我也在一个产品中做了类似的工作
1、把所有的CPU空闲时间收集起来交给一个Idel函数来处理,如果以后要休眠就在这个函数内部做就好了。
2、中断采取类似DPC调用的方式处理几个相关的工作
3、建立mini的MessageQuen
gfd 2010年07月26日
太强了