一、定时器中断说明:
1.如果不会使用51单片机的定时器和中断,那么学单片机就没有多大意义,因为中断这项功能为实现单片机多任务提高了便利。
2.当对计时要求精确时,一般是采用定时计数中断的方法产生一个精确的时间单位,比如5ms,然后结合软件办法达到所需目的。
3.定时中断模块分为两个部分:定时部分和中断服务部分。
定时部分工作原理如下:首先设置定时器工作方式、初始化值、设置定时器中断和开启中断,例如:
TMOD=0X01;//指定T0,工作方式1
TH0=-(5000/256); //加载高字节计数初值
TL0=-(5000%256); //加载低字节计数初值
IE=0X82; //允许T0产生中断
TR0=1; //启动T0中断
中断服务函数部分的作用:一是重置定时器T0的初始值、二是记录中断次数,每中断一次,计数单元count加1.
二、模块代码:
1. 定时部分,如:
void init_timer()
{
TMOD=0X01; //设置T0工作方式1
TH0=-(5000/256); //加载高字节计数初值
TL0=-(5000%256); //加载低字节计数初值
IE=0X82;//允许T0产生中断
TR0=1;//启动T0中断
}
2. 中断服务函数,如:
void T0_srv(void) interrupt 1
{
TH0=-(5000/256); //重新加载高字节计数初值
TL0=-(5000%256);
count++;
}
说明:该定时器定时时间为5ms,即5ms产生一次中断。计数单元count使用前首先要定义。
三、电路图:
(此图数码管显示参照了XY850/XY900开发板部分,下面程序只指定后2个数码管显示)
四、功能说明:
1. 用定时器实现长时间延时(通电一分钟后点亮LED一分钟、然后熄灭一分钟再点亮,循环);
2. 在程序中我们还要做一个任务:按键(接P3.2)计数0~99-数码管显示。
// == 以上做到互不影响。
四、程序实例(单片机同时进行2个任务):
//------------------------------------------------------------------
//程序名称:用T0实现1分钟定时点亮LED + 按键数码管计数
//实验硬件:XY850或XY900_USB单片机开发系统板, 晶体11.0592
//程序编写:月夜听风 mail: mcusy_cn@126.com http://www.mcusy.cn
//------------------------------------------------------------------
#include <reg52.h>
#define uchar unsigned char
sbit duan= P3^3; //数码管段选通端
sbit wei= P3^4; //数码管位选通端
sbit Key= P3^2; //定义手动按键
sbit LED =P2^0; //定义输出端口P2.0为LED
uchar count =0 ; //定义5MS的计数单元/清0
uchar sec= 0; //定义秒单位/清0
uchar shi,ge,num,s ; //定义要显示的十位、个位计数和num,s
void init_timer();//声明定时函数
void out(); //声明LED输出函数
void out_DIS(); //声明数码管计数部分输出函数
uchar code table[]={0xc0,0xf9,0xa4,0xb0, // 0,1,2,3
0x99,0x92,0x82,0xf8,0x80,0x90,0xff};// 4,5,6,7,8,9,off 数码管显示码
table_wei[]={0x02,0x01,0x08,0x04,0x20,0x10,0x80,0x40};//0~7依次位码表
//--------------------------延时函数---------------------------------
void delay(void)//延时
{
unsigned char x,y;
for(x=10;x>0;x--)
for(y=220;y>0;y--);
}
//--------------------------主函数-----------------------------------
main()
{
init_timer();//调用T0初始化
while(1)//循环
{
out() ;//调用LED输出
out_DIS(); //调用数码管手动计数
}
}
//----------------------------定时函数-------------------------------
void init_timer() //以下初值约50ms(晶体11.0592)
{
TMOD=0X01; //设置T0工作方式1
TH0=-(4800/256); //加载高字节计数初值
TL0=-(4800%256); //加载低字节计数初值
IE=0X82; //允许T0产生中断
TR0=1; //启动T0中断
}
//------------------------T0中断服务函数-----------------------------
void T0_src(void) interrupt 1
{
TH0=-(4800/256); //重新加载高字节计数初值
TL0=-(4800%256);
count++; //计数单元值加1
}
//--------------------LED一分钟间隔输出模块--------------------------
void out() //以下若想做到超过一分钟或更长时间怎么办?想想看
{
if(count>=200) //中断200次后
{sec++;count=0;} //秒加1,count清0
if(sec==60) //秒计满60次?
{LED=~LED; sec=0;}//反向输出1次,清0
}
//---------------------按键计数数码管输出模块------------------------
void out_DIS()
{
if(Key==0) //检测按键
num++; //数加1
if(num==100) //是否加满100?
{num=0;} //清零
for(s=0;s<=20;s++)//按键速度
{
shi=num/10; //提取十位
ge=num%10; //提取个位
duan=1;P0=table[shi];duan=0;//选通段,显示十位
wei=1;P0=table_wei[6];wei=0;//选通位,第6个数码显示
delay();
duan=1;P0=table[ge];duan=0; //选通段,显示个位
wei=1;P0=table_wei[7];wei=0;//选通位,第7个数码显示
delay();
}
}