查看: 1756|回复: 9

系统定时简易封装 [复制链接]

machunshui (离线)
积分
18937
帖子
229
发表于 2009-6-24 22:14:32 |显示全部楼层
关键词: 封装 , 系统
裸奔的时候,
因为在一个子任务当中,
为提高效率,不能傻等,
需要系统定时的情况很多,
处理起来比较麻烦,
如果对系统定时器进行简单的封装,
就会比较方便,

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

main.h:

#ifndef _MAIN_H
#define _MAIN_H

#include <pic.h>

#define MAX_SYSTIMER_COUNT 6
extern unsigned short sysTimer[MAX_SYSTIMER_COUNT];


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[MAX_SYSTIMER_COUNT];


////////////初始化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[i] = 0;
    }   
}

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

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

/////////////////////获取系统定时状态////////////////////////////////////////
unsigned char GetSysTimer(unsigned char id)
{
    if(sysTimer[id] == 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 (离线)
积分
18937
帖子
229
发表于 2009-6-24 22:16:47 |显示全部楼层
带proteus仿真的完整工程:

pic-basic.rar

56.99 KB, 下载次数: 7, 下载积分: 积分 -1

sz_kd (离线)
积分
4237
帖子
257
发表于 2009-6-25 09:40:22 |显示全部楼层
呵呵,采用状态机就是避免死等
500 字节以内
不支持自定义 Discuz! 代码
machunshui (离线)
积分
18937
帖子
229
发表于 2009-6-25 10:03:14 |显示全部楼层
实际上状态机的叫法过于玄乎,
就是一种任务分割而已,
就是把任务分割称若干断不可再分割的代码段,
根据条件执行这些代码段.

实际上这种封装带来的好处是不死等延时处理的方便,
而不是代替任务分割这种方法.
古道热肠 (离线)
积分
497
帖子
32
发表于 2009-7-7 12:27:33 |显示全部楼层
呵呵,写得不错,如果用Bool变量作为布尔型值来处理,更省内存.
machunshui (离线)
积分
18937
帖子
229
发表于 2009-7-7 13:36:04 |显示全部楼层
呵呵,
我觉得这种封装真的很好用啊.

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

键盘延时和数码管显示闪烁延时用起来很方便.
machunshui (离线)
积分
18937
帖子
229
发表于 2009-7-7 13:38:47 |显示全部楼层
用位结构的省RAM,
但是多几行代码,
运行速度降低了,

这个东西要在定时中断里面不断扫描,
还是快一点好
machunshui (离线)
积分
18937
帖子
229
发表于 2009-7-7 14:08:15 |显示全部楼层
要说改进可以把void CountSysTimer(void)采用宏定义的方法,
省去函数调用,
在定时器中断里面运行速度快一点.
McuPlayer (离线)
积分
75024
帖子
4011
发表于 2009-7-7 20:33:52 |显示全部楼层
嗯不错,我也在一个产品中做了类似的工作
1、把所有的CPU空闲时间收集起来交给一个Idel函数来处理,如果以后要休眠就在这个函数内部做就好了。
2、中断采取类似DPC调用的方式处理几个相关的工作
3、建立mini的MessageQuen
gfd (离线)
积分
59
帖子
26
发表于 2010-7-26 10:23:01 |显示全部楼层
太强了
您需要登录后才可以发表评论 登录 | 立即注册

关于我们  -  服务条款  -  使用指南  -  站点地图  -  友情链接  -  联系我们
电子工程网 © 版权所有   京ICP备11013910号 | 京公网安备11010502021702
回顶部