多定时器处理1(30天自制操作系统--读书笔记)

       自认为写过很多MCU程序,但总是回头想想,我所了解的MCU编程思想大体有两种,其中具体的想法我得再找时间写下来。

       总想总结出一个可扩展的,易移植的写法,但能力还没到这个层次。但《30天自制操作系统》这本书确实给我了一个思路,就像我已经写过的两篇读书笔记。

       将两个独立的内容--FIFO和内存动态管理做到高度模块化,尤其是其中数据结构模型的设计更是我学习的好例子。

       今天要学习的设计内容是多定时器处理。原书对这部分的处理讲的很详细,由浅入深,看得我由衷佩服作者,也可能是因为我水平低,稍稍看出点门道来就高兴得不得了。

       呵呵,进入正题。

       1、数据结构的抽象

#define MAX_TIMER 500

#define TIMER_FLAG_NOUSE 0    //没使用
#define TIMER_FLAG_ALLOC 1    //已配置状态
#define TIMER_FLAG_USING 2    //已使用状态

struct TIMER
{
    unsigned int timeout,flag;     //设定的定时时间,定时器的状态
    struct FIFO8 *fifo;            //定时器关联的fifo
    unsigned char data;            //当定时时间到时,向fifo中写入的数值
}

struct TIMERCTL
{
    unsigned int count;            //定时器计数基数
    struct TIMER timer[MAX_TIMER]; //设定系统最多使用的定时器个数
}

TIMERCTL timerctl;     //定义一个定时器控制变量

      2、定时器控制管理变量的初始化

void TIMERCTL_Initial(void)
{
    char i=0;
    timer.count = 0;               //基数清零
    for(i=0;i<MAX_TIMER;i++)
    {
        timerctl.timer[i].flag = TIMER_FLAG_NOUSE;   /*标记为未使用*/        
    }
}

    3、申请一个定时器

struct TIMER* timer_alloc(void)    //分配一个可以使用的定时器
{
    int i=0;
    for(i=0;i<MAX_TIMER;i++)
    {
        if(timerctl.timer[i].flag == TIMER_FLAG_NOUSE)
        {
            timerctl.timer[i].flag = TIMER_FLAG_ALLOC;   //标记为已分配
            return &timer[i];
        }
    }
    
    return NULL;       //没有可用的了
}

    4、释放一个定时器

void timer_free(struct TIMER* timer)  //释放一个定时器
{
    timer.flag = TIMER_FLAG_NOUSE;
    return ;
}

    5、要使用一个定时器时,先初始化定时器

//初始化一个定时器,timer应该先去调用timer_alloc申请,fifo也应该先创立,data表示当定时时间到了之后
//向关联fifo中写入的数据
void timer_init(struct TIMER* timer,struct FIFO8* fifo,unsigned char data)
{
    timer.fifo = fifo;
    timer.data = data;
    
    return ;
}

   6、设定定时器的定时时间,同时也启动了定时器

//设定timer定时器的定时时间为timeout
void timer_settime(struct TIMER* timer,unsigned int timeout)
{
    timer.timeout = timeout;        
    timer.flag = TIMER_FLAG_USING;  //这条语句相当于启动了定时器
    
    return ;
}

   7、定时器中断处理函数

//定时器中断函数
void Timer_Interrupt(void)
{
    int i=0;
    timerctl.count ++;
    for(i=0;i<MAX_TIMER;i++)        //扫描所有的定时器
    {
        if(timerctl.timer[i].flag == TIMER_FLAG_USING)
        {
            timerctl.count--;
            if(timerctl.count == 0) //减得时间到了
            {
                fifo8_put(timerctl.timer[i].fifo,timerctl.timer[i].data);  //向关联fifo中写入数据
                timerctl.timer[i].flag = TIMER_FLAG_ALLOC;      //改变标志位
            }
        }
    }
    
    return ;
}

    如何使用以上代码:

    1、初始化一个fifo,包括以下内容

    struct FIFO8 timer0fifo;

    char timer0buf[8];

    fifo8_init(&timer0fifo,8,timer0buf);     //这句话就是初始化一个fifo,8是缓存大小,timer0buf是实际缓存地址。

    2、定义一个timer,先申请再初始化它

    struct TIMER* timer0;

    timer0 = timer_alloc();                   //申请一个定时器对象

    timer_init(timer0,timer0fifo,1);        //这里也就是将timer0fifo与timer0关联,1是定时器到达时,向关联fifo中写入的值

    3、设定定时时间,启动定时器

    timer_settime(timer0,1000);          //这里设定的定时时间t=1000*T T为定时器硬件设定的时间间隔,比如1ms,那么这里就设定了一个1s的定时器

    4、通过在主程序中查询定时器关联fifo的状态,判断定时时间是否到了,并处理相关事情

    while(1)
   {
          ...(其他省略)
          if(fifo8_status(&timer0fifo) != 0)      //定时时间到了,定时器向关联fifo中写入了数据
         {
               i = fifo8_get(&timer0fifo);
               if(i == 1)
               {
                   //do_something
               }
         }
   }

      这样可以完成类似LED灯闪烁的任务了。当然这个定时器定时时间到了之后,还可以再初始化这个定时器,比如改变定时到时向fifo中写入的数值,然后再启动定时器,这样

判断fifo8_get的值就有意义了。这样可以完成文本输入中光标闪烁的任务(定时亮,定时灭,定时时间一样,处理不一样)。

     今天的内容就到此为止了,实际原作者比这写得更好,明天继续深入。

 

    

posted @ 2015-05-06 22:30  kanite  阅读(444)  评论(0编辑  收藏  举报