📄 4display.c
字号:
#include <reg51.h>
unsigned char ComperHourAlarm,ZeroNoDisplay,flashcount,ZeroYesDisplay;
unsigned int TClock;
unsigned int change;
unsigned int plus;
unsigned int TimerCount;
unsigned char temp[8];
unsigned int PLDELAY;
unsigned code DispTab [] = {0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0xff,0xbf,0x08,0x03,0x06,0xA1,0x91,
0xC7,};
//字形码0-9,不显示,-,a,b,c,d,Y,L,
unsigned char DispBuf [4] = {0,6,1,0,};//显示缓冲区,
/* 以下是对显示的驱动位作标记*/
sbit Hour1 = P2^1; //小时显示第一位.
sbit Hour2 = P2^2; //小时显示第二位.
sbit Min1 = P2^3; //分显示第一位.
sbit Min2 = P2^4; //分显示第二位.
sbit PL = P1^5; //电源电压低.
sbit Relay = P3^7;
/*----------以下是对键所在位作标志------------*/
sbit SetKey = P3^3; //功能键所在引脚.
sbit MoveKey = P3^1; //位移动键所在引脚.
sbit IncKey = P3^0; //加一键所在引脚.
unsigned char SetFlag; //定义调整的数据位置.
unsigned char Set; //要设置的数据中间传送位.
unsigned char Mi,Max; //数据要调整的范围.
/*---------以下是对常量和变量进行定义----------*/
unsigned char DispCount; //用于显示中对显示位数进行计数.
unsigned char ZeroNoDisplay; //用于显示小时位时如显示为09,则将其中的零不显示.
unsigned char flashcount; //定时0中断中用到的变量.
/*------------------秒脉冲中断用--------------*/
unsigned char Year,Month,Date,Hour,Min,Sec,Wek; //计数器.
unsigned int t;
bit Clock;
bit CheckDy;
/*------------------闪烁程序中用到-------------*/
unsigned char FlashSet; //闪动延时值.
bit FlashFlag; //闪动标志位.
unsigned char SetFlag;
/*--------------------延时程序---------------------*/
void mDelay (unsigned int Delay)
{ unsigned int i;
for (; Delay>0; Delay--) //延时时间很难选折.会产生不希望产生的鬼影.
{for (i=0;i<100;i++)
{;}
}
}
/*--------------加一程序--------------------*/
void inc ( void)
{
Set++; //对设置位加一.
if (Set > Max ) //如果设置数大于规定最大值,则归位最小值.
{Set = Mi;} //归位最小值.
}
/*---------------显示及缓冲区刷新程序---------------------*/
void Display ()
{ switch ( DispCount )
{
case 0: //小时十位显示.
Min2 = 1; //关闭年显示第二位.
ZeroNoDisplay = DispBuf [ DispCount ]; //输出段码.
if (ZeroNoDisplay==0)
{
P0 = DispTab [10]; //小时第一位为零时不显示.
}
else
{
P0 = DispTab [ DispBuf [ DispCount ] ];
}
Hour1 = 0; //点亮月显示第一位.
break;
case 1: //小时位个位显示.
Hour1 = 1; //关闭月显示第一位.
ZeroNoDisplay = DispBuf [ DispCount ]; //输出段码.
if (Clock == 1)
{P0 = ( DispTab[ZeroNoDisplay] & 0x7f );}
else
{P0 = DispTab [ DispBuf [ DispCount ] ];} //输出段码.
Hour2 = 0; //点亮月显示第二位.
break;
case 2: //分位十位显示.
Hour2 = 1; //关闭月显示第二位.
P0 = DispTab [ DispBuf [ DispCount ] ];
Min1 = 0; //点亮日显示第一位..
break;
case 3: //分位个位显示.
Min1 = 1; //关闭日显示第二位.
P0 = DispTab [ DispBuf [ DispCount ] ];
Min2 = 0; //点亮小时显示第一位.
break;
}
mDelay (1);
DispCount++;
if ( DispCount==4 ) //显示位数计数,以确定下一轮显示哪一位.
{
DispCount = 0;
}
}
/*----------------调时中用到的延时---------------------*/
void lDelay (unsigned int hDelay)
{ unsigned int i;
for (;hDelay>0; hDelay--)
{ for (i=0;i<120;i++)
{Display ();}
}
}
/*--------------缓冲区刷新程序---------------------*/
void scan()
{
DispBuf [1] = Hour%10;
DispBuf [0] = Hour/10; //将小时送入缓冲区.
DispBuf [3] = Min%10;
DispBuf [2] = Min/10; //将分送入缓冲区.
}
/*---------t0中断执行程序,用于t秒脉冲信号产生,按键及定时鸣叫.---------------*/
void t0(void) interrupt 1 using 0
{
t++;
if ( t == 2000) //半秒时指示.
{Clock = 0;} //秒闪指示位.
if (t ==4000) //如果计数到1秒,则T清零.
{ t=0;
if ( t == 0)
{Clock = 1;}
Sec++;
if ( Sec > 59 ) //秒计到59则秒位清零.
{ CheckDy = 1;
Sec = 0;
Min++;
if ( Min > 59 ) //分计到59则分位清零.
{ Min = 0 ;
Hour++;
if ( Hour > 12 ) //小时计到12,则小时位清零.
{ Hour = 1;
}
}
}
}
}
/*----------------t1中断程序----------------------
/*-----t1中断执行程序,用于执行调整参数时的数字闪烁,闪烁时间到自动退出调整程序.--------*/
void t1 (void) interrupt 3 using 2
{
TH1=(65536-50000)/256; //T1重置定时数据.
TL1=(65536-50000)%256;
FlashSet--;
if ( FlashSet == 0 )
{ FlashSet = 6 ;
FlashFlag = ~ FlashFlag; //对闪动位取反,以决定下一轮是否闪动.
if ( FlashFlag ==1)
{
switch (SetFlag) //看是要哪一位闪烁.
{
case 0:
DispBuf [0] = 10;
DispBuf [1] = 10; //年位闪烁.
break;
case 1:
DispBuf [2] = 10;
DispBuf [3] = 10; //月位闪烁.
break;
}
}
else
{ DispBuf [1] = Hour%10; //调整时的缓冲区刷新程序.
DispBuf [0] = Hour/10; //将小时送入缓冲区.
DispBuf [3] = Min%10;
DispBuf [2] = Min/10; //将分送入缓冲区.
}
}
}
/*------外部中断1用于执行键盘中断,进行参数调整.----------------------*/
void int1 () interrupt 2 using 2
{
if ( SetKey ==0 ) //Set键按下进入中断程序.
{
lDelay (10); //延时十毫秒.
if ( SetKey == 0) //再次查询SET键有否按下.
{
TR0 =0; //关闭TR0运行.
ET0 = 0; //关闭TR0中断,以实现调整时的闪烁
TR1 = 1; //开启TR1运行.
ET1 = 1; //开TR1中断,以实现调整时的闪烁.
EX1 = 0; //关闭外部中断1.
// EX1 = 0; //关闭外部中断1.
while ( SetKey == 0 ) //设置键按下释放否,未释放则等待.
{
Display ();
}
while ( SetKey == 1 ) //SetKey键按下,则进入
{ Display ();
if ( MoveKey == 0)
{SetFlag++; //需移动到的标志位.
if (SetFlag==2)
{SetFlag=0;}
}
while ( MoveKey == 0) //秒位键按下释放否,未释放则等待.
{Display ();}
if ( IncKey == 0 )
{ switch ( SetFlag )
{
case 0: Mi = 1;
Max = 12;
Set = Hour;
inc ( );
Hour = Set;
break;
case 1: Mi = 0;
Max = 59;
Set = Min;
inc ();
Min = Set;
break;
}
while ( IncKey == 0 )
{
Display ();
}
}
}
while ( SetKey == 0 )
{
Display ();
}
SetFlag = 0;
TR0 = 1; //开启TR0运行.
ET0 = 1; //开TR0中断,以实现调整时的闪烁.
TR1 = 0; //关闭TR1运行.
ET1 = 0; //开TR1中断,以实现调整时的闪烁.
EX1 = 1; //开启外部中断1,响应键盘中断.
}
}
}
/*---------------------主程序-------------------*/
void main (void)
{
EA = 1; //总中断允许.
ET0 = 1; //允许定时器0中断.
TR0 = 1; //开定时器1中断.
PT1= 1; //定时器1为高优先级.
EX1 = 1; //允许外部1中断.
IT1 = 1; //设置外部中断1为外部触发中断.
TMOD = 0x12; //定时器模式.
Hour = 8;
Min = 18;
PLDELAY = 50;
Relay = 0;
DispCount = 0;
SetFlag = 0;
FlashSet = 6; //闪动中用到.
TH0=0x06; //定时数据.
TL0=0x06;
TH1=(65536-50000)/256; //T1重置定时数据.
TL1=(65536-50000)%256;
while (1)
{
Display ();
scan();
if ( CheckDy == 1 ) //检查是否使能电源检测.
{ if ( PL == 0 ) //如果电源电压低则在屏幕上显示电源电压低.
{ for ( ;PLDELAY > 0;PLDELAY-- ) //屏幕上延时显示电源电压低.
{ DispBuf [1] = 16; //调整时的缓冲区刷新程序.
DispBuf [0] = 15; // 电压检测在每分钟的开始开启检测使能,
DispBuf [3] = 17; //
DispBuf [2] = 11; //
Display ();
}
}
CheckDy = 0;
PLDELAY = 50;
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -