实现59分59秒的反跑表,定时器0实现每一秒中断
定时器1实现每40ms刷新数码管一次
每计时一分钟蜂蜜器响一次,包括反跑的时候
用外部中断INT0、INT1实现按键扫描,正启动跑表或反启动跑表
无按键时实现正跑表
/*****************************************************************
时钟:11.0592MHz,KEIL编程环境
开发日期:2010年6月25日
*****************************************************************/
#include<reg52.h>
#include<absacc.h>
#include<string.h>
#define uchar unsigned char
#define uintunsigned int
sbit LED_COM1 = P1^4; //the 4 8_segment LEDs common control port.
sbit LED_COM2 = P1^5;
sbit LED_COM3 = P1^6;
sbit LED_COM4 = P1^7;
sbit INT0_E=P3^2;
sbit INT1_E=P3^3;
#define LCD_273 XBYTE[0xfe00]
uchartimer0_interrupt_counter=0; //中断记录次数
uchartimer1_interrupt_counter=0;
ucharNUM_miao=0,NUM_fen=0; //记录秒和分
uchar INT0_flag=0;
uchar INT1_flag=0;
uchar table[10]={0x0C0,0x0F9,0x0A4 ,0x0B0,0x99,0x92, 0x82,0x0F8,0x80,0x90 };//开发板为共阳的
void TIME_init()
{
TMOD=0x11;//定时器0和定时器1工作于方式1
ET0=1;//开定时器/计数器0允许
TR0=1;//中断定时器0开通
EA=1; //开总中断
ET1=1;//开定时器/计数器1允许
TR1=1;//中断定时器1开通
/***************外部中断0**********************/
IT0=0; //跳沿触发
EX0=1;//允许外部中断0产生中断
IT1=0; //跳沿触发
EX1=1; //允许外部中断1产生中断
/*******************优先级设置******************************/
PX0=1;
PX1=1;
PT0=0;
PT1=0;
}
/*************************************************************************************************/
void delay(uint time) //延时函数
{
uint i=0,j=0;
for(i=time;i>0;i--);
}
void display(uchar i,uchar com_counter ) // i表示亮的数,j表示第几个数码管亮
{
LCD_273=table;
if(com_counter == 1)
{
LED_COM1 = 0;
LED_COM2 = 1;
LED_COM3 = 1;
LED_COM4 = 1;
}
if(com_counter == 2)
{
LED_COM1 = 1;
LED_COM2 = 0;
LED_COM3 = 1;
LED_COM4 = 1;
}
if(com_counter == 3)
{
LED_COM1 = 1;
LED_COM2 = 1;
LED_COM3 = 0;
LED_COM4 = 1;
}
if(com_counter == 4)
{
LED_COM1 = 1;
LED_COM2 = 1;
LED_COM3 = 1;
LED_COM4 = 0;
}
com_counter += 1;
if(com_counter >= 4)
com_counter = 0;
}
/*******************************************************************************
函数:定时器0中断服务程序,产生20*50ms=1s的延时
介绍:每1s计时
********************************************************************************/
void timer0_ISR(void) interrupt 1
{
TH0=0x4B;//给予初值在11.0592MHZ下定时50ms:0x4BEC
TL0=0xEC;
timer0_interrupt_counter+=1;
if(timer0_interrupt_counter==20) //20 times interrupt about 50ms.
{
timer0_interrupt_counter=0;// set interrupt counter as 0
if(INT0_flag==1)
{
//INT0_flag=0;
NUM_miao++;
if(NUM_miao==60)
{
P1&=0xF7; //每计时到一分钟蜂鸣器响一次
delay(100);
P1|=0x08;//停止蜂鸣器响
NUM_miao=0;
NUM_fen++;
if(NUM_fen==60){INT0_flag=0;NUM_fen=0;}
}
}
if(INT1_flag==1)
{
// NUM_miao=60;
// NUM_fen=60;
//INT1_flag=0;
NUM_miao--;
if(NUM_miao==0)
{
P1&=0xF7; //每计时到一分钟蜂鸣器响一次
delay(100);
P1|=0x08;//停止蜂鸣器响
NUM_miao=60;
NUM_fen--;
if(NUM_fen==0){INT1_flag=0;NUM_fen=60;}
}
}
else
{
NUM_miao++;
if(NUM_miao==60)
{
P1&=0xF7; //每计时到一分钟蜂鸣器响一次
delay(100);
P1|=0x08;//停止蜂鸣器响
NUM_miao=0;
NUM_fen++;
if(NUM_fen==60)NUM_fen=0;
}
}
}
}
/*******************************************************************************
函数:定时器1中断服务程序,产生20ms*2=40ms延时
介绍:每50msms刷新数码管
********************************************************************************/
void timer1_ISR(void) interrupt 3//动态扫描中断 每位40ms
{
TH1=0xFC;//给予初值在11.0592MHZ下定时20ms:0xB802
TL1=0x78;
timer1_interrupt_counter+=1;
if(timer1_interrupt_counter==1)
{
display(NUM_fen/10,1); //显示分的十位 P1^4
}
if(timer1_interrupt_counter==2)
{
display(NUM_fen%10,2);
}
if(timer1_interrupt_counter==3)
{
display(NUM_miao/10,3); //显示秒的十位P1^6
}
if(timer1_interrupt_counter==4)
{
display(NUM_miao%10,4); //显示秒的个位P1^7
}
if(timer1_interrupt_counter>5)timer1_interrupt_counter=0;
}
/**************************************************************
函数:外部中断0服务程序
介绍:触发按键KEY1,实现秒表正跑
**************************************************************/
void INT0_ISR(void) interrupt 0
{
INT1_flag=0; //清零反跑标志
INT0_flag=1;
NUM_miao=0; //重装正跑数据
NUM_fen=0;
//INT0_E=1; //中断后对应的INT0引脚设置为高电平
//IE0=0;
}
/**************************************************************
函数:外部中断1服务程序
介绍:触发按键KEY2 ,实现秒表反跑
**************************************************************/
void INT1_ISR(void) interrupt 2
{
INT0_flag=0;//清零正跑标志
NUM_miao=60;//重装反跑数据
NUM_fen=59;
INT1_flag=1;
//INT1_E=1;//中断后对应的INT1引脚设置为高电平
//IE1=0;
}
voidmain()
{
TIME_init();
P1=0x08; //因为51单片机上电复位后I/0口是高电平
P3=0xff;
while(1)
{
;
}