Dotcpp  >  编程教程  >  定时器  >  微调定时精确时间

微调定时精确时间

点击打开在线编译器,边学边练

1.定时器&蜂鸣器

一般定时器中断函数里的内容最好是能够快速地去执行完,比如只执行几条简单的语句,这样与主函数配合才会使程序更加高效。前期教学里,我们只使用定时器中断负责某个IO引脚间隔跳变或者使一个变量间隔自加1的简单语句。

比如我们现在要实现间隔50ms左右的时间让流水灯左右循环移动的同时,还需要无源蜂鸣器一直响,这样的功能,思路该怎么去思考?

首先我们知道无源蜂鸣器要想鸣叫的比较尖锐,那P1.6需要一个合适的脉冲信号,这个信号笔者打算使P1.6高低电平保持的时间为300微秒不断循环。

所以我们用定时器中断实现P1.6的电平间隔跳变,主函数里负责完成流水灯的任务即可。

定时器8


2.代码

#include <reg52.h> 
#include <function.h>//详见第六章第8讲

u8 T0RH, T0RL;
void TIM0_Init(u32 us,int trim)//trim:微调
{
    u32 tmp;                       //临时变量
    
    tmp = 11059200 / 12;           //定时器计数频率
    tmp = ( tmp * (us/100) )/10000;//计算所需的计数值
    tmp = 65536 - tmp;             //计算定时器重载值
    tmp = tmp+trim;                //补偿中断响应延时造成的误差
    T0RH = (unsigned char)(tmp>>8);//定时器重载值拆分为高低字节  
    T0RL = (unsigned char)tmp;
    TMOD &= 0xF0; //清0低四位 
    TMOD |= 0x01; //设置定时器0为工作模式1   
    TH0 = T0RH;   //加载T0重载值   
    TL0 = T0RL;
    ET0 = 1;      //闭合定时器0中断的开关        
    TR0 = 1;      //启动定时器0         
} 

void main()
{  
    u8 i,dir;
    LED_Init();       //初始化LED硬件模块
    EA = 1;           //闭合总中断开关
    TIM0_Init(300,0); //用定时器0定时300us,不微调
    while(1)
    {
        if(i<8)dir=0;//向左移
        if(dir==0)P0=~(0x01<<i);

        if(i>=8)dir=1;//向右移 
        if(dir==1)P0=~( 0x80>>(i-7) );//当i大于等于8之后,(i-7)其实也还是在1~7之间变化

        i++;
        if(i>=15)i=1;//让i一直在1~14之间变化
        delay_ms(50);
    }
}

void TIM0_IRQHandler() interrupt 1
{
    TH0 = T0RH;   //重新加载重载值
    TL0 = T0RL;
    BEEP=!BEEP;
}

可以看到使用定时器中断比外部中断触发还要高效。


3.讲解微调

然后回到上一讲说过的怎么测试然后去微调使定时时间更精确。

拿我们这讲的代码来说,首先在不微调的情况下,也就是传入的参数trim为0,看看定时的时间是多少。
进入软件调试模式,在“BEEP=! BEEP;”设置断点,在没有微调之前观察每次执行“BEEP =! BEEP;”的间隔时间。

定时器9


按下RST复位之后,先按两次RUN

定时器10


再按一次RUN


定时器11


定时时间为0.003285-0.002979= 0.000306s

所以定时时间超了6微秒,则需要给trim一个合适的参数,这里笔者调出了最合适的数为6,所以我们初始化定时器时改为

TIM0_Init(300,6); //用定时器0定时300us,6是微调使定时时间更精确

这样每次跳转到中断函数去执行的间隔时间就为精确的300us了。

当我们要定时十毫秒或者二三十毫秒时,微调的数可能就不是6了,而是20之间或者其他数,所以每次想要精确定时就需要软件调试亲自测试。


本文固定URL:https://www.dotcpp.com/course/381

上一课:

代码参考

下一课:

单独文件封装

单片机教程
第一章 单片机入门
第二章 LED及入门
第三章 蜂鸣器
第四章 数码管
第五章 独立按键
第六章 多文件编程
第七章 外部中断
第八章 定时器
第九章 舵机与超声波模块
第十章 串口通信
第十一章 1602液晶屏
第十二章 IIC通信
第十三章 红外遥控与温度传感器
第十四章 AD与DA
第十五章 混合例程
第十六章 完结
Dotcpp在线编译      (登录可减少运行等待时间)