📄 rili.c
字号:
//***********液晶1602显示电子万年历程序***************//
#include <reg51.h>
#include <intrins.h>
#include <stdio.h>
#define uchar unsigned char
#define uint unsigned int
//********端口定义*******
sbit rs = P0^0; //lcd数据命令选择位
sbit rw = P0^1; //lcd写入读出选择位
sbit ep = P0^2; //lcd使能位
sbit led=P0^3;
sbit setkey=P1^0; //调时模式选择位
sbit setjia=P1^1; //+1位
sbit setjian=P1^2; //-1位
//***********变量定义************
uint year=2008;
uchar month=12,day=31,Week,hour=0,minute=0,second=0; //设置初始显示的时间日期
uchar sec100=0; //1秒的计数变量,加满100为1秒
uchar mod=0; //调时标志位
uchar code tab[]={"SUN,MON,TUE,WED,THU,FRI,SAT"};
void lcd_sef_chr(); //自定义字符函数声明
//**********闰年月星期表
code uchar WeekTab[]=
{
(3 << 5) + 31, //1月
(6 << 5) + 29, //2月
(0 << 5) + 31, //3月
(3 << 5) + 30, //4月
(5 << 5) + 31, //5月
(1 << 5) + 30, //6月
(3 << 5) + 31, //7月
(6 << 5) + 31, //8月
(1 << 5) + 30, //9月
(4 << 5) + 31, //10月
(0 << 5) + 30, //11月
(2 << 5) + 31 //12月
};
/*---------------2000年~2099年星期算法--------------------------------------------*/
uchar WeekDay20(uint year, uchar m, uchar d)
{
uchar y,week, day;
y=year%100;
day = WeekTab[m - 1]; //月表
week = day >> 5; //月星期数
day &= 0x1f; //月天数
if ((m < 3) && (y & 0x03))
{ //平年
if (m == 2) day--; //平年月天数
week++; //平年月表+1
}
y = y + (y >> 2); //年+年/4
week = (week + y + d + 2) % 7;//(星期=年+年/4+月表+2日)%7
return (week << 5) | day; //返回星期和月天数
}
//延时子程序----------------------------------------------------
void delay(uchar ms)
{
uchar i;
while(ms--)
{
for(i = 0; i< 250; i++)
{
_nop_();
_nop_();
_nop_();
_nop_();
}
}
}
//测试LCD忙碌状态----------------------------------------
bit lcd_bz()
{
bit result;
rs = 0;
rw = 1;
ep = 1;
result = (bit)(P2 & 0x80); //读出lcd忙碌标志位
ep = 0;
return result; //函数返回值,返回1表示lcd忙碌,返回0表示lcd空闲
}
//写入指令数据到LCD-----------------------------------------
void lcd_wcmd(uchar cmd)
{
while(lcd_bz()); //等待lcd到空闲
rs = 0;
rw = 0;
ep = 0;
P2 = cmd; //将指令写入lcd
ep = 1;
ep = 0;
}
//设定显示位置子程序-----------------------------------------
void lcd_pos(uchar pos)
{
lcd_wcmd(pos | 0x80); //将显示地址写入lcd
}
//写一个字符数据到LCD----------------------------------------
void lcd_wdat(uchar dat)
{
while(lcd_bz()); //等待lcd到空闲
rs = 1;
rw = 0;
ep = 0;
P2 = dat; //将数据写入lcd
ep = 1;
ep = 0;
}
//写n位数据到指定posi的位置------------------------------------
void lcd_datas(uchar posi,int dat,char n) //在posi的位置显示名字为dat的n位数据
{
uchar i,j,data1;
int s;
lcd_pos(posi);
for(i=1;i<=n;i++) //从第一位开始显示,到第n位显示完毕
{
s=1;
for(j=1;j<=n-i;j++)
s=s*10;
data1=dat/s;
lcd_wdat(data1+'0');
dat=dat%s;
}
}
//LCD初始化--------------------------------------------------
void lcd_init()
{ //LCD初始化设定
lcd_wcmd(0x38); //
lcd_wcmd(0x0c); //
lcd_wcmd(0x06); //
lcd_wcmd(0x01); //清除LCD的显示内容
}
//***显示星期程序*****
write_week(uchar week)
{
lcd_wcmd(12 | 0x80);
lcd_wdat(tab[4*week]);
lcd_wdat(tab[4*week+1]);
lcd_wdat(tab[4*week+2]);
}
//显示一屏时间------------------------------------------------
void display_lcd()
{
lcd_wcmd(0x01); //清除LCD?
delay(1);
lcd_datas(0,year,4); //显示第一行数据
lcd_wdat(0X00);
lcd_datas(5,month,2);
lcd_wdat(0X01);
lcd_datas(8,day,2);
lcd_wdat(0X02);
Week=WeekDay20(year, month, day)>>5;
write_week(Week);
lcd_datas(67,hour,2); //显示第二行数据
lcd_wdat(':');
lcd_datas(70,minute,2);
lcd_wdat(':');
lcd_datas(73,second,2);
}
//显示空字符----------------------------------------------------
void no_display(uint pos,char n) //pos:显示的地址。n:要显示的位数
{
lcd_pos(pos);
while(n--)
{
lcd_wdat(' ');
}
}
//年加1子程序---------------------------------------------
void inc_year()
{
year++;
if(year==9999)
year=0000;
Week=WeekDay20(year, month, day)>>5;
write_week(Week);
lcd_datas(0,year,4);
}
//月加1子程序---------------------------------------------------
void inc_month()
{
month++;
if(month>12)
{
month=01;
inc_year();
}
Week=WeekDay20(year, month, day)>>5;
write_week(Week);
lcd_datas(5,month,2);
}
//天加1子程序-------------------------------------------
void inc_day()
{
day++;
if(month==4||month==6||month==9||month==11)
{
if(day>30)
day=01;
inc_month();
}
else if(month==2)
{
if((year%400==0)||(year%4==0)&&(year%100!=0))
{
if(day>29)
day=1;
inc_month();
}
else if(day>28)
{
day=1;
inc_month();
}
}
else
{
if(day>31)
day=01;
inc_month();
}
Week=WeekDay20(year, month, day)>>5;
write_week(Week);
lcd_datas(8,day,2);
}
//小时加1程序------------------------------------------------------
void inc_hour()
{
hour++;
if(hour > 23)
{
hour = 0;
inc_day();
}
lcd_datas(67,hour,2);
}
//分加1程序-----------------------------------------------
void inc_min()
{
minute++;
if(minute > 59)
{
minute = 0;
inc_hour();
}
lcd_datas(70,minute,2);
}
//秒加1程序-------------------------------------------
void inc_sec()
{
second++;
if(second > 59)
{
second = 0;
inc_min();
}
lcd_datas(73,second,2);
}
//调时闪动程序---------------------------------------------------
void flash()
{
switch(mod)
{
case 1: no_display(0,4); break;
case 2: no_display(5,2); break;
case 3: no_display(8,2); break;
case 4: no_display(67,2); break;
case 5: no_display(70,2); break;
}
}
//中断处理程序---------------------------------------------------------------
timer0() interrupt 1
{
TH0=0xd8;
TL0=0xf0;
sec100++;
if(sec100 == 50 && mod != 0)
flash();
if(sec100 == 92)
{
sec100 = 0;
inc_sec();
display_lcd();
}
}
//闰年调整--------------------------------------------------------------
void incday()
{
day++;
if(month==4||month==6||month==9||month==11)
{
if(day>30)
day=01;
}
else if(month==2)
{
if((year%400==0)||(year%4==0)&&(year%100!=0))
{
if(day>29)
day=1;
}
else if(day>28)
day=1;
}
else
{
if(day>31)
day=01;
}
}
//时间调整程序----------------------------------------------
bit inc_time()
{
bit t;
t=0;
if(setjia==0)
{
delay(10);
if(setjia==0)
{
while(setjia==0);
t=1;
}
}
return t;
}
bit dec_time()
{
bit m;
m=0;
if(setjian==0)
{
delay(10);
if(setjian==0)
{
while(setjian==0);
m=1;
}
}
return m;
}
//*****************主程序*************************************//
void main()
{
TMOD=0x01;
TH0=0xd8;
TL0=0xf0;
led=0;
lcd_init(); //液晶初始化
delay(10);
lcd_sef_chr(); //自定义字符写入液晶
display_lcd(); //调用显示函数开始显示
ET0=1;
TR0=1;
EA=1;
while(1)
{
//----------------------
if(setkey==0)
{
delay(10);
if(setkey==0)
{
while(setkey==0);
mod++;
if(mod>5)
mod=0;
}
}
//--------------------------
if(mod==1)
{
if(inc_time()==1)
{
year++;
if (year==9999)
year=0;
Week= WeekDay20(year, month, day)>>5;
write_week(Week);
lcd_datas(0,year,4);
}
if(dec_time())
{
year--;
Week=WeekDay20(year, month, day)>>5;
write_week(Week);
lcd_datas(0,year,4);
}
}
//----------------------------------
else if(mod==2)
{
if(inc_time()==1)
{
month++;
if(month>12)
month=1;
Week= WeekDay20(year, month, day)>>5;
write_week(Week);
lcd_datas(5,month,2);
}
if(dec_time())
{
month--;
if(month==0)
month=12;
Week= WeekDay20(year, month, day)>>5;
write_week(Week);
lcd_datas(5,month,2);
}
}
//----------------------------------
else if(mod==3)
{
if(inc_time()==1)
{
incday();
Week= WeekDay20(year, month, day)>>5;
write_week(Week);
lcd_datas(8,day,2);
}
if(dec_time())
{
day--;
if(month==4||month==6||month==9||month==11)
{
if(day==0)
day=30;
}
else if(month==2)
{
if((year%400==0)||(year%4==0)&&(year%100!=0))
{
if(day==0)
day=29;
}
else if(day==0)
day=28;
}
else
{
if(day==0)
day=31;
}
Week= WeekDay20(year, month, day)>>5;
write_week(Week);
lcd_datas(8,day,2);
}
}
//------------------------------------------
else if(mod==4)
{
if(inc_time()==1)
{
hour++;
if(hour==24)
hour=0;
lcd_datas(67,hour,2);
}
if(dec_time())
{
hour--;
if(hour>23||hour<0)
hour=23;
lcd_datas(67,hour,2);
}
}
else if(mod==5)
{
if(inc_time()==1)
{
minute++;
if(minute==60)
minute=0;
lcd_datas(70,minute,2);
}
if(dec_time())
{
minute--;
if(minute>60)
minute=59;
lcd_datas(70,minute,2);
}
}
} //while
} //main
void lcd_sef_chr()
{
//第一个自定义字符-年
lcd_wcmd(0x40); //"01 000 000" 第1行地址 (D7D6为地址设定命令形式
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -