在定时/计数器的程序设计中,通常有两个函数:初始化函数和中断服务函数。
- 在初始化函数中,一般需要进行以下几个配置:
(1) 配置工作模式,即对TMOD寄存器编程。
(2)计算技术初值,即对THx和TLx寄存器进行赋值。
(3) 使能定时/计数器中断,即ET0或ET1置1。
(4)打开总中断,即EA =1。
(5)启动定时器,即TR0或TR1置1。 - 在中断服务函数中,一般需要进行以下的编程:
(1) 如果不是自动重装模式,需要对THx和TLx重新赋值。
(2) 进行间隔定时到达的逻辑处理(越少越好)。
TF1、TF0:分别是定时器1、定时器0的溢出标志位。当定时器x计满溢出时,由硬件使TFx位置“1”,并申请中断。进入中断服务程序后,由硬件自动清“0”,在查询方式下用软件清“0”。
编程实现:利用定时/计数器的T0的模式1实现间隔定时,每隔1秒L1指示灯闪烁一下(点亮0.5s,熄灭0.5s),每隔10秒L8指示灯闪烁一下(点亮5s,熄灭5s)
#include <STC15F2K60S2.H>
void selectHC(unsigned char n);
void InTimer();
/*利用定时/计数器的T0的模式1实现间隔定时,
每隔1秒L1指示灯闪烁一下(点亮0.5s,熄灭0.5s),
每隔10秒L8指示灯闪烁一下(点亮5s,熄灭5s)
*/
sbit beer=P0^6;
sbit L1=P0^0;
sbit L8=P0^7;
void main()
{
selectHC(5);beer=0;P2&=0X1f;P0=0xFF;
selectHC(4);
InTimer();
while(1);
}
void InTimer()
{
TMOD=0X01;
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
ET0=1;
EA=1;
TR0=1;
}
unsigned char count=0;
//=======================================================================
void seviceTimer() interrupt 1
{
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
count++;
if(count%10==0) //定时器计时50ms,10个50ms为500ms,L1闪烁
{
L1=~L1;
}
if(count==100) //定时器计时50ms,100个50ms为5s,L1闪烁
{
L8=~L8;
count=0;
}
}
//=======================================================================
void selectHC(unsigned char n)
{
switch(n)
{
case 4:P2=(P2&0x1f)|0x80;break; //LED
case 5:P2=(P2&0x1f)|0xA0;break; //蜂鸣器 继电器
case 6:P2=(P2&0x1f)|0xC0;break; //数码管位选
case 7:P2=(P2&0x1f)|0xE0;break; //数码管段选
}
}
编程实现:利用定时器T0、数码管模块和2个独立按键,设计一个秒表,具有清零、暂停、启动功能。
- 显示格式为:分—秒—0.05秒(即50ms)
08—26—18表示:8分26秒900毫秒。- 独立按键S4为:暂停/启动
独立按键S5为:清零
按键均为按下有效
#include <STC15F2K60S2.H>
void selectHC(unsigned char n);
void InTimer();
void delay_ms(int n);
void show(unsigned int w,unsigned int n);
void keyscan();
sbit beer=P0^6;
sbit S4=P3^3;
sbit S5=P3^2;
unsigned char min=0; //分钟
unsigned char sec=0; //秒
unsigned char count=0; //毫秒
unsigned char table[]={
0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xbf};//0xbf为数码管显示 ——
unsigned char which[]={
0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
void main()
{
int i;
selectHC(5);beer=0;P2&=0X1f;P0=0xFF;
InTimer();
while(1)
{
keyscan();
for(i=0;i<8;i++)
{
switch(i)
{
case 7:show(8,count%10);delay_ms(5);break;
case 6:show(7,count/10);delay_ms(5);break;
case 5:show(6,10);delay_ms(5);break;
case 4:show(5,sec%10);delay_ms(5);break;
case 3:show(4,sec/10);delay_ms(5);break;
case 2:show(3,10);delay_ms(5);break;
case 1:show(2,min%10);delay_ms(5);break;
case 0:show(1,min/10);delay_ms(5);break;
}
}
}
}
/***********************************************
开关扫描函数
************************************************/
void keyscan()
{
if(S4==0)
{
while(S4==0);
TR0=!TR0;
}
if(S5==0)
{
while(S5==0);
count=0;
sec=0;
min=0;
}
}
/***********************************************
定时器T0初始化函数
************************************************/
void show(unsigned int w,unsigned int n)
{
selectHC(6);
P0=which[w-1];
selectHC(7);
P0=table[n];
delay_ms(5);
P0=0xff;
P2&=0x1f;
}
/***********************************************
定时器T0初始化函数
************************************************/
void InTimer()
{
TMOD=0X01;
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
ET0=1;
EA=1;
TR0=1;
}
/***********************************************
定时器T0中断服务函数
************************************************/
void seviceTimer() interrupt 1
{
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
count++;
if(count==20) //说明到了20*50ms=1S,秒标志位加1
{
count=0;
sec++;
if(sec==60)
{
sec=0;
min++;
if(min==60)
{
min=0;
}
}
}
}
/***********************************************
寄存器选择函数
************************************************/
void selectHC(unsigned char n)
{
switch(n)
{
case 4:P2=(P2&0x1f)|0x80;break; //LED
case 5:P2=(P2&0x1f)|0xA0;break; //蜂鸣器 继电器
case 6:P2=(P2&0x1f)|0xC0;break; //数码管位选
case 7:P2=(P2&0x1f)|0xE0;break; //数码管段选
}
}
/***********************************************
延时函数
************************************************/
void delay_ms(int n)
{
int i,j;
for(i=n;i>0;i--)
for(j=110;j>0;j--);
}