模板:定时器、外部中断0,以及查询和中断
这里拿一个上电即开始作0-60秒表的题目 做案例:
中断服务程序里 或 查询方式的那个延时函数里都是要重新赋初值的。
中断方式
当定时模式为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、设初值的操作了。
作者QQ4577105