|
本帖最后由 liuda 于 2015-1-21 22:38 编辑
Proteus仿真截图
/*****************************************************************************
程序名称:六位数码管时钟表
编译器:Keil uVision 4
程序功能:上电后,程序按初始时间开始时钟演示,时间显示按24小时制。
时间调整:按A键,显示加1,按B键,显示减1,按C键,清零
MCU:AT89C51
晶振:11.0592M
外围部件:
键盘:4按键A、B、C、D分别接在P1.0、P1.1、P1.2和P1.3上,低电平有效
A、B、C键分别控制时、分、秒的选择,D键铵下进行时间调整。
显示:4位共阴极LED,P0口送显示数据,P1口低四位位选
内部资源:
使用定时计数器1中断,用于定时及显示
警告:
1. 按键未加防抖动程序
2. 此程序经过编译并通过Proteus仿真,未通过实物检验。
作者:花落水流红,空寂萧然山——萧然
完成日期:2012/6/11
============================================================================*/
#include <reg51.h> //包含必要头文件
//定义按键
sbit HourAdjust = P1^0; //时调整选择键
sbit MinuteAdjust = P1^1; //分调整选择键
sbit SecondAdjust = P1^2; //秒选择选择键
sbit Adjust = P1^3; //调整键
//定义标志位
bit SecondFlag = 0; //秒标志
bit FlashFlag = 0; //秒闪标志
bit Second10Flag = 0; //10秒标志
bit HourAdjustFlag = 0; //时调整标志,A键按下置1,10秒后清0
bit MinuteAdjustFlag = 0; //分调整标志,A键按下置1,10秒后清0
bit SecondAdjustFlag = 0; //秒调整标志,A键按下置1,10秒后清0
unsigned char Led1,Led2,Led3,Led4,Led5,Led6; //定义缓存
int TimeCount,Second10Count; //定义计数器
unsigned char code LedTab[]= //定义共阴极数码管表,0x00用于清除显示
{0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x00};
void Delay100us(int Times); //定义延时函数
//*****************************定时器中断服务程序******************************r
//程序功能:动态驱动数码管,同时完成定时功能。
void timer() interrupt 3 using 2
{
TR1 = 0;
TL1 = 0x13; TH1 = 0x2C; //重新赋值
P0 = 0x00; //显示小时
P2 = 0xfe;
P0 = LedTab[Led1];
Delay100us(1);
P0 = 0x00;
P2 = 0xfd;
if(FlashFlag) //秒显(1秒显,1秒隐)分前小数点
P0 = LedTab[Led2] | 0x80;
else
P0 = LedTab[Led2] & 0x7f;
Delay100us(1);
P0 = 0x00; //显示分
P2 = 0xfb;
P0 = LedTab[Led3];
Delay100us(1);
P0 = 0x00;
P2 = 0xf7;
if(FlashFlag) //秒显秒前小数点
P0 = LedTab[Led4] | 0x80;
else
P0 = LedTab[Led4] & 0x7f;
Delay100us(1);
P0 = 0x00; //显示秒
P2 = 0xef;
P0 = LedTab[Led5];
Delay100us(1);
P0 = 0x00;
P2 = 0xdf;
P0 = LedTab[Led6];
Delay100us(1);
TR1 = 1;
if(TimeCount < 100) //秒计数器
TimeCount++;
else
{
TimeCount = 0x00;
SecondFlag = 1; //置位秒标志
if(Second10Flag) //10秒计数器
if(Second10Count < 20)
Second10Count++;
else
{
Second10Count = 0x00; //10秒计数器清0
Second10Flag = 0; //清除10s标志
HourAdjustFlag = 0; //清除调整标志位
MinuteAdjustFlag = 0;
SecondAdjustFlag = 0;
}
}
}
//============================================================================
main(void)
{
//初始化
int Second = 30; //初始化时间
int Minute = 12;
int Hour = 20;
Led1 = 0x00; //清除显存
Led2 = 0x00;
Led3 = 0x00;
Led4 = 0x00;
Led5 = 0x00;
Led6 = 0x00;
SecondFlag = 0;
TimeCount = 0x00;
//设置定时器中断
TMOD = 0x10f; //GATE=0 01010001
//C/T=0--定时/计数器1工作于定时方式
//M1=1;M0=0--选择工作模式1,构成最大定时器
//T0:在此程序不使用
TL1 = 0x13; TH1 = 0x2C; //指定定时时间为50ms 65536-50/(11.0592/12)=11283=2C13h
EA = 1; //开总中断
TF1 = 0;
ET1 = 1; //开定时器中断
TR1 = 1; //开始计时
while(1)
{
//*****************************************************************************
//对时间进行调整程序
if(SecondFlag)
{
if(Second%2 == 0)
FlashFlag = 1;
else
FlashFlag = 0;
if(Second < 59)
Second++;
else
{
if(Minute < 59)
Minute++;
else
{
if(Hour < 23)
Hour++;
else
Hour = 0;
Minute = 0;
}
Second = 0;
}
SecondFlag = 0;
}
//-----------------------------------------------------------------------------
//*****************************************************************************
//时间调整程序
if(HourAdjustFlag) //调整时程序
if(Second10Flag)
if(FlashFlag) //时秒显
{
Led1 = 0x0a; //时隐
Led2 = 0x0a;
}
else
{
Led1 = Hour/10; //时显
Led2 = Hour%10;
}
else
{
Led1 = Hour/10;
Led2 = Hour%10;
}
else
{
Led1 = Hour/10;
Led2 = Hour%10;
}
if(MinuteAdjustFlag) //调整分程序
if(Second10Flag)
if(FlashFlag) //分秒显
{
Led3 = 0x0a;
Led4 = 0x0a;
}
else
{
Led3 = Minute/10;
Led4 = Minute%10;
}
else
{
Led3 = Minute/10;
Led4 = Minute%10;
}
else
{
Led3 = Minute/10;
Led4 = Minute%10;
}
if(SecondAdjustFlag) //调整秒程序,控制秒显
if(Second10Flag)
if(FlashFlag)
{
Led5 = 0x0a;
Led6 = 0x0a;
}
else
{
Led5 = Second/10;
Led6 = Second%10;
}
else
{
Led5 = Second/10;
Led6 = Second%10;
}
else
{
Led5 = Second/10;
Led6 = Second%10;
}
if(!HourAdjust) //时调整按键按下
{
while(!HourAdjust); //等待松开
HourAdjustFlag = 1; //置位时标志位
MinuteAdjustFlag = 0; //清除分标志位
SecondAdjustFlag = 0; //清除秒标志位
Second10Flag = 1; //置位10秒标志位
}
if(!MinuteAdjust) //分调整键按下
{
while(!MinuteAdjust);
MinuteAdjustFlag = 1;
HourAdjustFlag = 0;
SecondAdjustFlag = 0;
Second10Flag = 1;
}
if(!SecondAdjust) //秒调整键按下
{
while(!SecondAdjust);
SecondAdjustFlag = 1;
HourAdjustFlag = 0;
MinuteAdjustFlag = 0;
Second10Flag = 1;
}
if(!Adjust) //调整键按下
{
while(!Adjust);
if(HourAdjustFlag) //调整时,加1
if(Hour < 23)
{
Hour++;
Second10Count = 0;
}
else
Hour = 0;
if(MinuteAdjustFlag) //调整分,加1
if(Minute < 59)
{
Minute++;
Second10Count = 0;
}
else //调整秒,清零
Minute = 0;
if(SecondAdjustFlag)
Second = 0;
}
}
}
//********************************延时程序************************************
void Delay100us(int Times)
{
Times = Times * 100;
while(Times--);
}
//必要说明,定时器中断函数是经过计算的50ms,但在使用Proteus仿真时时间不准确。
//比实际表要快。对此不进行调整,因为中断函数是经过硬件检验通过的。
|
|