📄 时钟_1602.c
字号:
#include<reg51.h>
#include<intrins.h>
#define uchar unsigned char
uchar tmp[4]= {"28^C"};
uchar num[12]={"0123456789 :"};//数字数数组
uchar time[8]={0};
uchar t1_set[4]={0};
uchar adj[6]={"adjust"};
uchar adj_0[6]={" time"};
uchar adj_1[6]={" t1 "};
uchar off[4]={"off "};
uchar ON[4]= {"on "};//ON[]两个字母均为大写,用小写时会出错,也不知为什么
uchar hour0=12,hour1=12,minute0=0,minute1=0,second=0;//设置初始值,显示12。00
uchar ten_hour,hour,ten_minute,minute;//
uchar key=0,right=0,set=0;//
bit key_flag=0;//
bit s_flag=0;
bit adj_flag=0;
bit dp_flag=0;
bit time_flag=0;
bit out=1,out1;
sbit set_key=P3^2;
sbit up_key=P3^3;
sbit right_key=P3^4;
sbit on_off_key=P3^5;
sbit p_out1=P1^0;
void t0(void);//定时0中断函数声明
void t1(void);//定时1中断函数声明
void time_display(void);//走时显示子程序
void t_adj(void);//走时调整子程序
void t1_adj(void);//
void t1_out(void);
void key_scan(void);//键盘扫描子程序
/******************************************************************
1602程序部分
数据总线接到p2口 用到1ms延时程序 <intrins.h>函数
*******************************************************************/
uchar command[]={0x38,0x38,0x38,0x38,0x08,0x01,0x06,0x0c}; /* P2=0x01;//清屏并光标复位
P2=00111000;//显示模式设置,8位总线,2行,5*7
P2=0x0c;//开显示。光标和闪烁
P2=0x06;//文字不动,光标自动右移
P2=0x80;//写入的起始位置,第1行第1列*/
sbit e=P3^7;
sbit rw=P3^6;
sbit rs=P3^0;
sbit busy=P2^7;
//--------------------------延时程序-------------------------------
void delay(uchar i)
{ uchar a;
while(i--)
{for(a=0;a<=125;a++)
{;}
}
}
//--------------------查LCD是否忙程序-----------------------
void wait(void)
{ do
{ P2=0xff;
rs=0;//
rw=1;//
e=0;
_nop_();
e=1; }
while(busy==1);
}
//-------------------数据写入函数-------------------------
void dataw(uchar da)
{ wait();
rs=1;
rw=0;
e=1;
P2=da;
e=0;
}
//-------------------指令和显示地址写入子函数------------
void comw(uchar da)
{ wait();
rs=0;
rw=0;
e=1;
P2=da;
e=0;
}
//--------------------------初始化--------------------------------
void init(void)
{ uchar i;
delay(20);
e=1;
for(i=0;i<8;i++)
{comw(command[i]);
delay(5);
}
}
//--------------------------清屏-----------------------------------
void clen(void)
{ uchar i;
comw(0x80);
for(i=0;i<16;i++)
dataw(0x02);
comw(0xc0);
for(i=0;i<16;i++)
dataw(0x02);
}
/****************************************************************************
主函数
*****************************************************************************/
main()
{ uchar i=0;
TMOD=0x11; //设置工作方式,T0 50ms 中断计时,T1定时10ms中断,数码管和键盘扫描
TH0=(65536-46080)/256;//
TL0=(65536-46080)%256;// 50ms定时
TH1=(65536-10000)/256;
TL1=(65536-10000)%256;//10ms定时
TR1=1; //
TR0=1; //
ET0=1; //
ET1=1; //
EA=1; //
init();//1602初始化
while(1)
{
if(key_flag) key_scan();//当确定有键按下了,就调用键盘扫描程序,判断那个键按下了
switch(set) //根据set的值判断该显示哪个
{ case 0:{if(s_flag==1){s_flag=0;time_display();}} break;//走时显示
case 1:{if(adj_flag==1){adj_flag=0;t_adj();}}break;//走时调整显示
case 2:{if(adj_flag==1){adj_flag=0;t1_adj();}}break;}//定时输出1调整显示
//case 3:t2_adj();break;}//定时输出2调整显示
t1_out();//判断定时输出1时间到了没有
// t2_out();//判断定时输出2时间到了没有
}
}
/****************************************************************************************
显示时间子程序
*****************************************************************************************/
void time_display(void)
{ uchar i=0;
time[0]=hour0/10;//
time[1]=hour0%10;
time[3]=minute0/10;
time[4]=minute0%10;
time[6]=second/10;
time[7]=second%10;//将时间拆分
clen();
////////////////////////////////////////////////////////////
//第1行
comw(0x84);
for(i=0;i<8;i++)
{ if(i==2||i==5) dataw(num[11]);
else dataw(num[time[i]]);
// if(i==2&&time[7]%2) P2=num[10];//秒闪
}
////////////////////////////////////////////////////////////
//第2行
comw(0xc6);
for(i=0;i<=3;i++)
dataw(tmp[i]);
}
/****************************************************************************************
显示时间调整子程序
*****************************************************************************************/
void t_adj(void)
{ uchar i;
time[0]=hour0/10;//
time[1]=hour0%10;
time[3]=minute0/10;
time[4]=minute0%10;//将时间拆分
if(dp_flag==1){if(right<2) time[right]=10;
else if(right>=2) time[right+1]=10;}//判断是否是当前调整位 ,是当前调整位闪烁
//////////////////////////////////////////////////////
//第1行
comw(0x80);
for(i=0;i<6;i++)
dataw(adj[i]); //" adjust"
for(i=0;i<6;i++)
dataw(adj_0[i]);//" time "
/////////////////////////////////////////////////////
//第2行
comw(0xc5);
for(i=0;i<5;i++)
{if(i==2)dataw(num[11]);
else dataw(num[time[i]]);}
}
/****************************************************************************************
显示闹钟1调整子程序
*****************************************************************************************/
void t1_adj(void)
{ uchar i;
t1_set[0]=hour1/10;//
t1_set[1]=hour1%10;
t1_set[3]=minute1/10;
t1_set[4]=minute1%10;//将定时1设定的时间拆分
/////////////////////////////////////////////////////////////////////////////////////////////////
if(dp_flag==1){if(right<2) t1_set[right]=10;
else if(right>=2) t1_set[right+1]=10;}//判断是否是当前调整位 ,是当前调整位闪烁
///////////////////////////////////////////////////////////////////////////////////////////////////
comw(0x02);
//第1行
comw(0x80);
for(i=0;i<6;i++)
dataw(adj[i]); //" adjust"
for(i=0;i<6;i++)
dataw(adj_1[i]);//" t1 "
///////////////////////////////////////////////////////////////////////////////////////////////////
//判断显示t1是显示on还是off
if(out==1){for(i=0;i<4;i++) dataw(off[i]);}
else {for(i=0;i<4;i++)dataw(ON[i]);}//ON[]两个字母均为大写,用小写时会出错,也不知为什么
/////////////////////////////////////////////////////
//第2行
comw(0xc5);
for(i=0;i<5;i++)
{if(i==2)dataw(num[11]);
else dataw(num[t1_set[i]]);}
}
/****************************************************************************************
定时控制1输出子程序
*****************************************************************************************/
void t1_out(void)
{ if(out1==0) p_out1=0;
else p_out1=1;
if(hour0==hour1&&minute0==minute1) {p_out1=1;out1=1;}
}
/****************************************************************************************
键盘扫描子程序
*****************************************************************************************/
void key_scan (void)
{
key_flag=0;//将键盘按下标志位清零
if(set_key==0) { set++;if(set==3) set=0;//设置加1,切换状态
while(set_key==0);//等待键松开
}
if(right_key==0){right++;if(right==4) right=0;//右移,切换调整位
while(right_key==0) {;}}//等待键松开
switch(set) //根据当前调整,将其时间传送给调整的缓存数组
{ case 1: {ten_hour=hour0/10,hour=hour0%10,ten_minute=minute0/10,minute=minute0%10; adj_flag=1;} break;//时间调整
case 2: {ten_hour=hour1/10,hour=hour1%10,ten_minute=minute1/10,minute=minute1%10;adj_flag=1;} break;//定时1调整
//case 3: {ten_hour=hour2/10,hour=hour2%10,ten_minute=minute2/10,minute=minute2%10;} break;//定时2调整
}
if(up_key==0) { switch(right)//根据调整位进行相应调整
{ case 0:{ten_hour++;if(ten_hour==3)ten_hour=0;} break;//十时调整
case 1:{hour++;if((ten_hour!=2&&hour==10)||(ten_hour==2&&hour==4)) hour=0;} break;//时调整
case 2:{ten_minute++;if(ten_minute==6) ten_minute=0;} break;//十分调整
case 3:{minute++;if(minute==10) minute=0;} break;//分调整
}
while(up_key==0) {;}//等待键松开
}
if(on_off_key==0)out=~out;//设置是否启动定时
while(on_off_key==0){;};//等待键松开
switch(set) //将调整后的时间传送回去
{ case 1:{hour0=ten_hour*10+hour;minute0=ten_minute*10+minute;}break;
case 2:{hour1=ten_hour*10+hour;minute1=ten_minute*10+minute;out1=out;}break;
// case 3:{hour2=ten_hour*10+hour,minute2=ten_minute*10+minute,out2=out;}break;
}
}
/****************************************************************************************
T0中断子程序
*****************************************************************************************/
void t0(void) interrupt 1 using 1
{ uchar a,b;
b++;a++;
TH0=(65536-46080)/256;//
TL0=(65536-46080)%256;// 50ms定时
if(a==5) {a=0;dp_flag=~dp_flag;}
if(b==20) {b=0;s_flag=1;second++;}//够1s则将数码管小数点取反,则看到闪烁
if(second==60){second=0;minute0++;}//够1分钟则加分钟计数加1
if(minute0==60){minute0=0,hour0++;}////够1小时则小时计数加1
if(hour0==24)hour0=0;//够24小时则清零
}
/****************************************************************************************
T1中断子程序
*****************************************************************************************/
void t1(void) interrupt 3 using 2
{
uchar j,key_1;
j++;
TH1=(65536-10000)/256;
TL1=(65536-10000)%256;//10ms定时
P3=0xff;//键盘扫描程序
if(j==2){j=0,key=P3&00111100;
if(key=key_1) key_flag=1; }
key_1=P3&00111100;//10ms内若两次的结果一样,表明有按键按下
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -