Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1521417
  • 博文数量: 226
  • 博客积分: 3997
  • 博客等级: 少校
  • 技术积分: 2369
  • 用 户 组: 普通用户
  • 注册时间: 2010-06-19 17:26
个人简介

Never save something for a special occasion. Every day in your life is a special occasion.

文章分类

全部博文(226)

文章存档

2018年(5)

2017年(11)

2016年(1)

2015年(17)

2014年(14)

2013年(30)

2012年(5)

2011年(52)

2010年(107)

分类: 嵌入式

2010-11-07 18:39:35

8/16bits 软定时器实现
 
需求:
作为是系统的控制中心,mcu常常要掌握时间尺度,比如
一个按键根据按键时间是否大于3s分为长短按键,长短按键分别实现不同功能;
故障时响报警,如果10s内无干预则自动停止运行;
每1s对电流积分,计算电量。
...
高级语言如VB编程中可以使用定时器,方便地掌握时间。曾经在某电话公司工作过很短一段时间,电话系统中需要使用大量定时器。那时我还是菜菜鸟,对定时器的需求理解也很浅,没有掌握那种软定时器的使用,更别说它是怎么实现的,现在想来后悔——离开时正如师父所说“连毛都没带走”。现在我学习uCOS-II,时常感叹设计的巧妙,这对本文的软定时器的实现有所启发。
 
① 平台、指标
8bit MCU。
精度 1ms
时长 256、65536
数量 N=8
占用内存 N*TR + x // tr是计时单元,与时长有关。x 是软定时系统共用变量。
超时方式 设置标志,停止计时。
 
② 用户接口定义
根据时长,定时器分为 8位、16位,共8个。
宏定义 N_TIME8 配置 8位定时器的数量。
void InitTimers();
void SetTimer(int id,int time);
void EnTimer(int id);
void DisTimer(int id);
bool IsTimeOut(int id);
 
③ 编程实现

#include <stdio.h>

typedef unsigned char uint8;
typedef unsigned short uint16;

#define N_TIME8 4    // configure number of 8bit-timer.

uint8 TR8[N_TIME8];    // Timer register

uint16 TR16[8-N_TIME8];

uint8 TER; // timer Enable register

uint8 TFR; // timeout flags.

void Tick(); // decrement every TimerRegister, if 1→0 set TFi.

/*
void InitTimers();
void SetTimer(int id,int time); // macro
bool IsTimeOut(int id);
void DisTimer(int id);
*/


/*
Tick() 由硬件定时器驱动,周期1ms。
8个定时器分为2组,建立一个表用于快速下一个使能了的计数器。这个表只有16字节,可以节省一些时间开销。这对于中断服务程序来说是很宝贵的。

  反问:这样真的节省时间了吗?
  ① 当所有定时器都开启时,这种方式与 for(i=0; i<8; i++)相比,哪个更快?
  ② 多少定时器开启时,两种方式耗时相当?
*/


uint8 NextTimerTab[16]={0,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0};
void Tick()
{
    uint8 map;
    uint8 nextTimer;
    
    // group1: timer 0,1,2,3

    // 使能了,并且非0的定时器需要倒计时。// 这过滤了为0的定时器,计时单元自减时不需要判断是否为0.

    map = (TER & ~TFR) & 0x0f;
    while(map != 0)
    {
        nextTimer = NextTimerTab[map];
        map &= ~(1<<nextTimer);
        if(nextTimer<N_TIME8)
        {
            if(--TR8[nextTimer] == 0)
                TFR |= 1<<nextTimer;
        }
        else
        {
            if(--TR16[nextTimer-N_TIME8] == 0)
                TFR |= 1<<nextTimer;
        }
    }
    
    // group2: timer 4,5,6,7

    map = (TER&~TFR) & 0xf0;
    map >>= 4;
    while(map != 0)
    {
        nextTimer = NextTimerTab[map];
        map &= ~(1<<nextTimer);
        nextTimer += 4; // index

        if(nextTimer<N_TIME8)
        {
            if(--TR8[nextTimer] == 0)
                TFR |= 1<<nextTimer;
        }
        else
        {
            if(--TR16[nextTimer-N_TIME8] == 0)
                TFR |= 1<<nextTimer;
        }
    }
}

void InitTimers()
{
TER = 0;
TFR = 0;
// TR[]={0};
}
/*
// void SetTimer(id,time); // macro
 可以放心,一般8bit-mcu的编译器不会把它优化掉。这里用do{}while(0)实现了语句块的宏定义
*/

#define SetTimer(id, time) do{if(id<N_TIME8)TR8[id]=time;else TR16[id-N_TIME8]=time;}while(0)

#define EnTimer(id) (TER |= 1<<id)

#define DisTimer(id) (TER &= ~(1<<id))

/*
// bool IsTimeOut(int id); // macro
id的值不会大于7,why? C的原则:信任程序员 & 程序员应该知道自己正在做什么。
*/

#define IsTimeOut(id) (TFR & (1<<id))

/*
前面几个操作都是用宏实现的。为什么呢?
不是因为函数调用消耗更多时间,想想你自己吧,一年才在家呆2周,老妈会因为你早日睡懒觉而生气吗?
因为函数调用需要堆栈。8bit-mcu 如holtek函数调用使用硬件堆栈,要严格控制函数层次。
*/


// ④ demo

void main()
{
    int i=0;

    InitTimers();
    SetTimer(0, 3); // 8bits-timer

    SetTimer(1, 5);
    SetTimer(5, 7);// 16bits-timer

    EnTimer(0);
    EnTimer(1);
    EnTimer(5);

    while(1)
    {
        Tick();        // Debug in VC6.0. Simulate timer-ISR ~
        if(i++>10)break; // End loop. 10 > max(3,5,7) 

        printf("\n%d====================\n", i);
        if(!IsTimeOut(0))
            printf("0\t");
        else
        {
            printf("0_%s\t", "time out");
            //DisTimer(5); // test DisTimer()
        }
        if(!IsTimeOut(1))
            printf("1\t");
        else
            printf("1_%s\t", "time out");
        if(!IsTimeOut(5))
            printf("5\t");
        else
            printf("5_%s\t", "time out");
    }
    printf("End\n");
}


输出:


1====================
0 1 5
2====================
0 1 5
3====================
0_time out 1 5
4====================
0_time out 1 5
5====================
0_time out 1_time out 5
6====================
0_time out 1_time out 5
7====================
0_time out 1_time out 5_time out
8====================
0_time out 1_time out 5_time out
9====================
0_time out 1_time out 5_time out
10====================
0_time out 1_time out 5_time out
11====================
0_time out 1_time out 5_time out End


Press any key to continue


阅读(1703) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~