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之间或者其他数,所以每次想要精确定时就需要软件调试亲自测试。

点赞(0)

C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:

一点编程也不会写的:零基础C语言学练课程

解决困扰你多年的C语言疑难杂症特性的C语言进阶课程

从零到写出一个爬虫的Python编程课程

只会语法写不出代码?手把手带你写100个编程真题的编程百练课程

信息学奥赛或C++选手的 必学C++课程

蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程

手把手讲解近五年真题的蓝桥杯辅导课程

Dotcpp在线编译      (登录可减少运行等待时间)