您当前的位置:五五电子网电子知识电子学习基础知识电脑-单片机-自动控制51定时器(计算器)的研究与程序设计 正文
51定时器(计算器)的研究与程序设计

51定时器(计算器)的研究与程序设计

点击数:7236 次   录入时间:03-04 11:48:48   整理:http://www.55dianzi.com   电脑-单片机-自动控制
晶振的误差
    我们的晶振一般误差都是20PPM的,百万分之二十。想提高精度,只能选择误差更小的晶振,但它毕竟不是为精确定时设计的,很难达到时钟芯片晶振的精度。
单片机中断系统的误差。
    定时器产生中断请求以后,并不一定能马上响应这个中断。
    单片机要把当前的指令执行完。51的指令是1到4个周期。如果赶上两周期指令,就会延误一个指令周期。最慢的情况会延误3个周期响应中断。这点误差倒是没什么关系。
    但是如果单片机正处理其他的中断(同级或更高级)。要等其执行完其他中断,再执行一条主程序指令,才会响应定时器0中断。因为程序千差万别,所以其他中断占用的时间,就没准儿了。更要命的是,这类影响是随机的,你根本无法纠正。
    看起来好像没有办法了,但是你深入研究定时器的工作原理以后,你会发现这个问题还是有可能解决的。请仔细看一下,我上面的中断程序,“TH0=0xEE;” 你是否注意到,我没有给TL0重新赋值。这可不是疏忽忘了。我们知道定时器只要开着,TH0和TL0就会不断的增一,增到FF FF,再增一就溢出,这时TF0被硬件置1(也就是中断请求)。我们要注意的就是不管定时器中断是否被响应,TH0和TL0仍然会不断增一,FF FF增一00 00 再增一 00 01 再增一 00 02 。这就是我为什么要选择5毫秒作为定时长度的原因。因为TH0=EE TL0=00。最主要的就是TL0=00。定时器在溢出产生中断以后,不论响应还是不响应,TL0并不停止计数。虽然中断响应有可能被延迟,但是延迟的时间仍然被计算。延迟的时间在下一次中断时会“补上”。这就是只对TH0重赋值的原因。从理论上说,真正是一个微秒都不差。研究出这个用法以后,着实让我兴奋了好长时间。呵呵。
    还有一点需要注意。其他的中断占用的时间太长,TL0增数超过256,定时器中断响应时TH0已经大于0了,直接写TH0=0xEE;就有误差了.可以改成 TH0=TH0+0xEE;但这样也会有一点点问题,我们不在这里详细讨论。最好还是控制其他的中断占用时间不要超过240个机器周期。
每秒钟最后一次入中断的误差。原因和上面说的相同,误差在下一秒也会“补上”。

定时器例程之二 :模拟时钟
这也是JHC-51-A的实验6-1的内容。
以下是部分程序
void init_timer0(void)
{
//以下为初始化定时器
TMOD|=0x01;  //选择定时器0,工作模式1:16位定时器
TH0=0xEE;    //置定时初始值
TL0=0x00;
//初始化完毕。
ET0=1;  //开定时器0中断,允许定时器0中断。
EA=1;    //开全局中断。允许所有中断
TR0=1;  //开始计数 
}
unsigned char time_allow;    //整点报时标志
unsigned char time_num;      //报时的次数 ,
unsigned char FMq_times;    //整点报时 蜂鸣器声音维持时间计数
unsigned char set_kk_times; 
unsigned char ms5_times;    //5ms中断计次
unsigned char hour,min,sec;  //定义时,分,秒。
void timer0() interrupt 1 using 1    //5ms中断一次定时器中断处理函数
{
//重新置位计数初始值  在工作方式1下,需要重新置位定时初始值,程序才会再一次进入中断,
//工作方式0,3也是如此,只有工作方式2不需要重新置位初始值。
TH0=0xEE;    //置定时初始值
if(++ms5_times>=200)  //5ms中断一次,计数200次 达到1s
{
    ms5_times=0;
    dc1=0;          //处理小数点  点亮
    sec++;          //时钟 秒+1
    if(sec>=60)      //秒计数达到60
    {
        sec=0;
        min++;      //分钟+1
        if(min>=60)  //分钟计数达到60
        {
            min=0;
            hour++;  //小时+1
            if(hour>23) hour=0; //24小时制,计数达到24,清零
        }
    }
}
if(0==sec)
{
    if(0==min)            //如果时间达到整点。允许报时功能
    {
        if(hour>12) time_num=hour-12; //如果时间超过12点,报时声音次数相应减 12
          else if(0==hour) time_num=12;    //如果时间为零点。报时声音为12次
          else time_num=hour;          //报时次数为时间值
          time_allow=1;                //报时允许标志置位
    }
    if(30==min)            //如果时间达到半点,允许报时功能
    {
        time_allow=1;      //报时标志置位
        time_num=1;        //报时次数 1次
    }
}
if(1==time_allow)          //如果报时允许
{
    if(fmq_times++>200)
    {
        fmq_times=0;
        spk=1;        //蜂鸣器停止发声
        time_num--;    //报时次数减 1
    } 
    if(100==fmq_times) spk=0;  //蜂鸣器发声
    if(0==time_num) time_allow=0;    //报时结束 清零报时标志位
}
if(ms5_times==80) dc1=1; //处理小数点 熄灭
if(set_kk_times++>200) set_kk_times=0;
disp_LED(display);  //刷新数码管
}



上一页  [1] [2] 


本文关键字:程序设计  定时器  计算器  电脑-单片机-自动控制电子学习 - 基础知识 - 电脑-单片机-自动控制