zoukankan      html  css  js  c++  java
  • 多定时器处理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的值就有意义了。这样可以完成文本输入中光标闪烁的任务(定时亮,定时灭,定时时间一样,处理不一样)。

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

        

  • 相关阅读:
    URLEncode解决url中有特殊字符的问题
    监控系统概览
    SpringBoot 上传文件夹
    关于postgresql报 ERROR: XXX does not exist
    postgresql学习
    git学习
    学习博客
    面试准备
    jvm
    线程池面试题
  • 原文地址:https://www.cnblogs.com/kanite/p/4483462.html
Copyright © 2011-2022 走看看