📄 基于液晶显示的万年历.c
字号:
/*
实验项目:基于AT89S52单片机的时钟,日历,整点报时及温度显示
描述:本实验通过单片机内部晶振实现时钟,由DS18B20实现温度采集.实验中采用10位键输入方式,利用AT89S52编码键盘输入.
全部输出由LCD1602显示,电源部分采用掉电工作方式,实现了时间信息的掉电保护,使在掉电状态下单片机时钟仍然工作。
操作说明:
键盘中 P3.0,P3.1,P3.2,P3.3 端口依次为LCD背光输出,报时接口,闹钟接口
P1端口为输入调整键盘
P0口为液晶数据输出口中
P2.0,P2.1,P2.2 依次为液晶RS,RW,E 接口
*/
#include <reg51.h>
#include <intrins.h>
sbit lcd_led=P3^0;
sbit alarm_time=P3^1;
sbit alarm=P3^2;
bit scan_key(void);
void proc_key0(void);
void proc_key1(void);
extern void LCD_WriteCommand(unsigned char cmd); //写指令数据到LCD
extern void LCD_DisplayOneString(unsigned char X,unsigned char Y,unsigned char a[]);//显示一个字符串
extern void LCD_DisplayNum(unsigned charX,unsigned char Y,unsigned char num); //显示一个数字 //外部函数声明区
extern void LCD_DisplayoneNum(unsigned char X,unsigned char num);
extern void LCD_Init(void); //LCD初始化
extern void delayus(unsigned int num); //液晶延时
void delayms(unsigned char ms); //键盘延时
extern void LCD_DisplayOneChar(unsigned char X,unsigned char Y,unsigned char Z);//显示一个字符
extern unsigned char ReadTemperature(void);
void readkey(unsigned char date);
unsigned char keyscan(void);
unsigned char hour,min,sec,year,mon,day,week0,temp0,ahour,amin;
unsigned char atime,time,enter; //调整控制变量
unsigned char s0,s1,x0,x1;
unsigned char num,record;
unsigned char sec100;
unsigned int lcd;
unsigned char math;
unsigned char dis_time[11]; //时间调整保留数组
unsigned char code week[]={"week"};
unsigned char code temp[]={"temp"};
unsigned char Init,show2;
void main(void)
{ unsigned char show3,show1;
lcd=0;
alarm_time=0;
alarm=0;
TMOD = 0x11; // 定时器0, 1工作模式1, 16位定时方式
TH0 =(65536-50000)/256;
TL0 =(65536-50000)%256;
TH1 = 0xFC;
TL1 = 0x17;
hour =12;
min =0;
sec =0;
year=0;
mon=10;
day=1;
ahour=12;
amin=0;
week0=1;
sec100 = 0;
IE = 0x8A; // 使能timer0,1 中断
TR0=1;
TR1=1;
record=15;
LCD_Init();
LCD_WriteCommand(0x00);
x0=0;
x1=3;
s0=0;
atime=0;
time=0;
Init=0;
while(1)
{
temp0=ReadTemperature();//读温度
if(atime==0)
{
if(time==0)
{
if(show2)
{
LCD_Init();LCD_WriteCommand(0x01);show2=0;
}
LCD_WriteCommand(0x0c);
LCD_WriteCommand(0x06);
LCD_DisplayOneString(9,0,temp);
LCD_DisplayOneChar(13,0,0x3a);
LCD_DisplayNum(14,0,temp0);
LCD_DisplayOneString(9,1,week);
LCD_DisplayNum(0,0,hour);
LCD_DisplayOneChar(2,0,0xB0);
LCD_DisplayNum(3,0,min);
LCD_DisplayOneChar(5,0,0xB0); //正常显示时间,月历,星期及当前温度
LCD_DisplayNum(6,0,sec);
LCD_DisplayNum(0,1,year);
LCD_DisplayOneChar(2,1,0x2f);
LCD_DisplayNum(3,1,mon);
LCD_DisplayOneChar(5,1,0x2f);
LCD_DisplayNum(6,1,day);
LCD_DisplayOneChar(13,1,0x3a);
LCD_DisplayOneChar(14,1,(week0+0x30));
show3=1;
show1=1;
}
if(time)
{ dis_time[0]=hour/10;
dis_time[1]=hour%10;
dis_time[2]=min/10;
dis_time[3]=min%10;
dis_time[4]=year/10;
dis_time[5]=year%10;
dis_time[6]=mon/10;
dis_time[7]=mon%10;
dis_time[8]=day/10;
dis_time[9]=day%10;
dis_time[10]=week0%10;
//显示初始化
if(show1)
{
LCD_Init();LCD_WriteCommand(0x01);show1=0;
}
LCD_WriteCommand(0x0c);
LCD_WriteCommand(0x06);
LCD_DisplayNum(0,0,hour);
LCD_DisplayOneChar(2,0,0xB0);
LCD_DisplayNum(3,0,min);
LCD_DisplayNum(6,0,year);
LCD_DisplayOneChar(8,0,0xB0);
LCD_DisplayNum(9,0,mon);
LCD_DisplayOneChar(11,0,0xB0);
LCD_DisplayNum(12,0,day); //时间调整部分显示模式
LCD_DisplayOneChar(15,0,(week0+0x30));
if(scan_key())
{
delayms(10);
if(scan_key())
{ record=num;
if(num>=0&&num<=9)
{ dis_time[s0]=num;
s0++;
if(x0==2|x0==5|x0==8|x0==14) x0++;
LCD_DisplayoneNum(x0,num);
x0++;
}
}
}
if(s0>10)
{
time=0;
s0=0; //如果调整完成自动回到主显示界面
x0=0;
}
hour=dis_time[0]*10+dis_time[1];
min=dis_time[2]*10+dis_time[3];
year=dis_time[4]*10+dis_time[5];
mon=dis_time[6]*10+dis_time[7];
day=dis_time[8]*10+dis_time[9];
week0=dis_time[10];
show3=1;
show2=1;
}
}
else
{ dis_time[0]=ahour/10;
dis_time[1]=ahour%10;
dis_time[2]=amin/10;
dis_time[3]=amin%10;
if(show3)
{
LCD_WriteCommand(0x01);show3=0;
}
LCD_WriteCommand(0x0c);
LCD_WriteCommand(0x06);
LCD_DisplayNum(0,0,ahour);
LCD_DisplayOneChar(2,0,0xB0); //显示闹钟
LCD_DisplayNum(3,0,amin);
if(scan_key())
{ delayms(10);
if(scan_key())
{ record=num;
if(num>=0&&num<=9)
{ dis_time[s0]=num;
s0++;
if(x1==0)
x1++;
if(x1<5)
{ LCD_DisplayoneNum(x1,num);
x1++;
}
}
}
}
if(s0>3)
{
atime=0;
s0=0; //如果调整完成自动回到主显示界面
x1=2;
}
ahour=dis_time[0]*10+dis_time[1];
amin=dis_time[2]*10+dis_time[3];
show1=1;
show2=1;
}
}
}
//时钟产生部分
void timer1() interrupt 1 using 2 //定时工作,作为时钟
{ unsigned int i,j;
i=year+2000;
TH0 =(65536-49975)/256;
TL0 =(65536-49975)%256;
sec100++;
if(sec100>=20)
{ sec100=0;
sec++; Init++;if(Init++==3){Init=0;show2=1;}
if(sec>59)
{ sec=0;if(min==59){alarm_time=1;for(j=20;j>0;j--){}alarm_time=0;} //报时响应
min++;
if(min>59)
{ min=0; //变换时间
hour++;
if(hour>23)
{ hour=0;
day++;
week0++;
if(week0>6) week0=0;
switch(mon)
{ case 2: if(i%4==0&&i%100!=0||i%400==0) if(day>28){day=1;mon++;if(mon>12){mon=1;year++;}} break;
if(day>29){day=1;mon++;if(mon>12){mon=1;year++;}} break;
case 1: if(day>31){day=1;mon++;if(mon>12){mon=1;year++;}} break;
case 3: if(day>31){day=1;mon++;if(mon>12){mon=1;year++;}} break;
case 5: if(day>31){day=1;mon++;if(mon>12){mon=1;year++;}} break;
case 7: if(day>31){day=1;mon++;if(mon>12){mon=1;year++;}} break;
case 8: if(day>31){day=1;mon++;if(mon>12){mon=1;year++;}} break;
case 10:if(day>31){day=1; mon++;if(mon>12){mon=1;year++;}} break;
case 12:if(day>31){day=1;mon++;if(mon>12){mon=1;year++;}} break;
default:if(day>30){day=1;mon++;if(mon>12){mon=1;year++;}} break;
}
}
}
}
}
}
//键盘部分程序
void delayms(unsigned char ms)
{ unsigned char i;
while(ms--)
{
for(i = 0; i < 120; i++);
}
}
bit scan_key()
{
return(num^record);
}
//闹钟部分中断响应
void searchtime() interrupt 3 using 1
{
TH1 = 0xFC;
TL1 = 0x17;
math=keyscan();
readkey(math);
if((ahour==hour)&&(amin==min))
alarm=1;
else alarm=0;
if(scan_key())
{ if(atime==0&&num==10) time=1;
if(time==0&&num==11) atime=1;
if(num==12)
{ s0=0;
x0=0;
x1=2;
time=0;
atime=0;
}
if(num!=15) lcd=1;
}
if(lcd) lcd++;
if(lcd>5000) lcd=0;
if(lcd!=0) lcd_led=1;
else
lcd_led=0;
}
unsigned char keyscan(void)
{ unsigned char test,tmp;
P1=0xf0;
if((P1&0xf0)!=0xf0)
{if((P1&0xf0)!=0xf0)
{ test=0xfe;
while((test&0x10)!=0)
{ P1=test;
if((P1&0xf0)!=0xf0)
{ tmp=(P1&0xf0)|0x0f;
return(~(test)+~(tmp));
}
else test=(test<<1)|0x01;
}
}
}
return(0);
}
void readkey(unsigned char date)
{ switch(date)
{ case 0X11: num=0;break;
case 0X21: num=1;break;
case 0X41: num=2;break;
case 0X81: num=3;break;
case 0X12: num=4;break;
case 0X22: num=5;break;
case 0X42: num=6;break;
case 0x82: num=7;break;
case 0x14: num=8;break;
case 0x24: num=9;break;
case 0x44: num=10;break;
case 0x84: num=11;break;
case 0x18: num=12;break;
case 0x0: num=15;break;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -