模板:定时器、外部中断0,以及查询和中断

这里拿一个上电即开始作0-60秒表的题目 做案例:

写定时器不管用中断还是查询方式写,时间到了就溢出,初值就自动变成了0,所以我们在中断服务程序里查询方式的那个延时函数里都是要重新赋初值的。

中断方式

当定时模式为01时,中断方式:

跑一遍后溢出,TFx由硬件自动清零了,所以在中断服务函数中就不用多此一举TFx=0了。

我们也不需要在主函数和中断服务函数里写TRx=1,因为中断本身就是多线程一样一直在运行。

TMOD=0X01; 对模式的设置,中断服务函数里不用再写这句话了,这个在主函数一开始就设置了,再设置编译直接会报错,认为TMOD是个错误变量了。

查看代码
//sbit 定义四个数码管
unsigned char count,miao;
//中断方式 对miao的操作
void timer0()interrupt 1
{
    //TMOD=0X01;    这里不用再写这句话了,这个主函数一开始就设置了,再设置编译直接回报错,认为TMOD是个错误变量了。
    //TR0=1;        中断函数中TR0=1可写可不写,因为中断本身就是一直运行的状态,每到设置的计数到后,就直接中断,并不需要软启动			TR0=1;了。
    TH0=0XEE;    	//因为定时跑一遍完后,就溢出清零了,所以如果想继续,那就让它每次都对其重新赋值
    TL0=0X00;
    count++;
    if(count==200){
    miao++;
    count=0;
        if(miao==61)miao=0;
    }
}
//使数码管显示的函数

/*.................*/
void main(){
    TMOD=0X01;    //设置T0为工作方式1
    TH0=0XEE;    
    TL0=0X00;
    ET0=1;    	//开启定时器0中断允许
    EA=1;   	//开启总中断允许
    TR0=1;    	//上电就直接启动T0开始计数
    while(1){
    disp(miao);
    }
}

 

查询方式

当定时模式为01时,查询方式:

跑一遍后溢出,TFx变成了1,必须软件清零,所以在查询方式的延时函数中就得写TFx=0了。

因为我们用的不是中断方式,所以主函数中就不需要写EA=1; ETx=1;

我们需要在查询方式延时函数里写TRx=1,因为查询方式当溢出了TFx=1;就停止了,我们要另外重新开启。而主函数里的TRx=1;控制什么时候开始计数。

查看代码
//sbit 定义四个数码管
unsigned char count,miao;
void main(){
    TMOD=0X01;    //设置T0为工作方式1
    TH0=0XEE;    
    TL0=0X00;
    TR0=1;    //上电就直接启动T0开始计数
   			  //由于我们用的不是中断方式,所以不需要写ET0=1;EA=1;开启这些中断允许
    
    while(1){
    disp(miao);
    delay1s();
    miao++;
    if(miao==61)miao=0;
    }
}
//查询方式 对miao的操作  主函数里就不用写开启中断的语句EA=1;ET1=1;了
void delay1s()
{
   unsigned char i=0;
   for(i=0;i<200;i++){
    //TMOD=0X01;    这里不用再写这句话了,这个主函数一开始就设置了,再设置编译直接回报错,认为TMOD是个错误变量了。
    TH0=0XEE;    //因为定时跑一遍完后,就停止了,所以如果想继续,那就让它每次都对其赋值一样
    TL0=0X00;
    TR0=1;  //查询方式是一直计数的方式,所以记完溢出了,TR0=0被停止了,所以溢出后就必须再开启,不是中断方式一直运行的。
    while(!TF0);    //查询是否溢出,计数完了溢出时,TF0=1;。
    TF0=0;        //5ms时间到,将T0溢出标志位TF0清零
   }
}
//使数码管显示的函数
/*.................*/

如果我们想上电板子什么都不做,按一次按键了板子才开始进行动作(开始秒表),那么我们在主函数里就写TR0=0;或者干脆不写TR0在主函数里,然后写个按键的子函数,如果按了某按键则TR0=!TR0;当按了该按键,主函数里的TR就相当于个总开关,板子就会开始执行相应动作了。再按一次则暂停计数,再按一次则继续计数。
拿中断方式的0-60秒表 做案例:

查看代码
 //sbit 定义四个数码管
unsigned char count,miao;
void pause();
void main(){
    TMOD=0X01;    //设置T0为工作方式1
    TH0=0XEE;    
    TL0=0X00;
    ET0=1;    //开启定时器0中断允许
    EA=1;     //开启总中断允许
    //TR0=1;    //上电就直接启动T0开始计数
    while(1){
    pause();
    disp(miao);
    }
}
//中断方式 对miao的操作
void timer0()interrupt 1
{
    //TMOD=0X01;    这里不用再写这句话了,这个主函数一开始就设置了,再设置编译直接回报错,认为TMOD是个错误变量了。
    //TR0=1;        中断函数中TR0=1可写可不写,因为中断本身就是一直运行的状态,每到设置的计数到后,就直接中断,并不需要软启动TR0=1;
    TH0=0XEE;    //因为定时跑一遍完后,就停止了,所以如果想继续,那就让它每次都对其赋值一样
    TL0=0X00;
    count++;
    if(count==200){
    miao++;
    count=0;
        if(miao==61)miao=0;
    }
}
//延时函数
void delay(unsigned int i)
{
  while(i)i--;    
}
//使数码管显示的函数
/*.................*/
void pause()
{
    if(P21==0){
        delay(1000);    //前沿去抖
        if(P21==0){
        delay(1000);    //后延去抖
        while(!P21);    //判断按键释放
            TR0=!TR0;    
        
    }
}

 

如果是单纯的外部中断0:
这里拿 外部中断的方式实现按键控制 1 个 LED 的亮灭 做案例

查看代码
#include<reg51.h>
sbit led=P3^7; 
void main()
{
	IT0=1; //外部中断 0 边沿触发方式:电平触发的稳定 边沿触发的灵敏(常用)
	EX0=1; //开启外部中断 0
	EA=1; //开启总中断允许
	led=1; //指示灯初始为灭
	while(1) ;
}
void pause() interrupt 0 //外部中断 0 程序入口	INTO就是板子的P3^2,INT1是板子的P3^3,但是板子没有按键3.3
{
	led=!led;
}
//单片机执行完中断程序后 继续回到主函数之前那个状态位置继续运行。在执行主函数的同时,外设中断扫描也继续同时执行。
//中断的特点:同步工作,实时处理。
//由于它不存在计数,所以不需要写TMOD、TR、设初值的操作了。

 

posted @ 2022-10-22 10:42  iZJ"Qq4577105  阅读(166)  评论(0编辑  收藏  举报