#include"LCD1602.h"
#include<reg52.h>
void LCD_display(void);
void keykan(void);
void shezhi(void);
void T0_init();
void delay(uint x);
int num[10]={0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39}; // lcd1602 0~9字码
uchar miao=0, fen=5, shi=12 ; //进位标志位 秒 分 时
uint i=0; //定时器计时标志位
uchar *time[]={&miao , &fen , &shi }; //指针变量time存放进位标志位的地址,由于数组不能存放标量,但是却可以存放标量的地址,采用指针的方式来间接修改变量的值
uchar set = 0 ;
bit kaiguan=0;
uchar SetPlace=0; //功能选择标志
bit mod =0; //设置模式标志位
bit alarmset=0 , alarm=0 ; //时钟设置需要的标志位
sbit key1=P3^1; //定义四个按键 key1选择需要调整的位
sbit key2=P3^0; //key2加
sbit key3=P3^2; //key3减
sbit key4=P3^3; //长按两秒钟进入或退出设置模式,前面三个按键需要进入设置模式才能使用
void main(void) //主函数
{
T0_init(); //定时器初始化
LCD_init(); //lcd1602初始化
while(1) //死循环
{
shezhi();
keykan();
LCD_display(); //lcd1602显示时分秒年月日
}
}
void keykan(void) //按键处理函数
{
if (mod==1) //如果进入设置模式显示一个
{
LCD_disp_char(1,14,'C');
if (SetPlace==0) //功能选择位为0就显示“miao” 为1就显示“fen” 以此类推,
{
LCD_row(2);
LCD_DispString("miao ");
delay(50);
}
switch (SetPlace) //调整位闪烁
{
case 0 : { LCD_disp_char(2,15,' ');
delay(700);} ; break;
case 1 : { LCD_disp_char(2,12,' ');
delay(700);} ; break;
case 2 : { LCD_disp_char(2,9,' ');
delay(700); } ; break;
}
if(key1==0) //检测按键key1是否按下
{
delay(10); //消除抖动
if(key1==0)
{ //按一下功能选择位就+1,加到7就清零
SetPlace++;
if(SetPlace>=6)
SetPlace=0;
}
switch (SetPlace) //调整为显示
{
case 1 : { LCD_row(2);
LCD_DispString(" fen ");
delay(50);} ; break;
case 2 : { LCD_row(2);
LCD_DispString(" shi ");
delay(50); } ; break;
}
while(key1==0) //检测按键是否松开
{
delay(10);
}
}
if(key2==0) //检测按键key2是否按下
{
delay(10); //消除抖动
if(key2==0)
{
(*time[SetPlace])++; //按键按一次 指针数组*time[SetPlace]里对应的地址的数据值就+1,也就是说进位标志位年月日时分秒的值就会+1
if ((((*time[SetPlace]))>=60) && (SetPlace==0))
{
(*time[SetPlace])=0; //秒只能加dao59
}
if ((((*time[SetPlace]))>=60) && (SetPlace==1))
{
(*time[SetPlace])=0; //分只能加到59
}
if ((((*time[SetPlace]))>=24) && (SetPlace==2))
{
(*time[SetPlace])=0; //时只能加到23
}
while(key2==0) //检测按键是否松开
{
delay(10);
}
}
}
if(key3==0) //检测按键key3是否按下
{ //key3与key2按钮基本原理相同,key3表示对应值减1
delay(10); //消除抖动
if(key3==0)
{
if ((((*time[SetPlace]))<=0) && (SetPlace==0))
{
(*time[SetPlace])=60;
}
if ((((*time[SetPlace]))<=0) && (SetPlace==1))
{
(*time[SetPlace])=60;
}
if ((((*time[SetPlace]))<=0) && (SetPlace==2))
{
(*time[SetPlace])=24;
}
(*time[SetPlace])--;
}
while(key3==0) //检测按键是否松开
{
delay(10);
}
}
}
}
void timer0_int() interrupt 1 //定时器中断服务函数
{
TH0 = 0x4c; //高八位赋初值
TL0 = 0x00; //低八位赋初值
i++;
if(i == 20){
i = 0; //满一秒清零
miao++; //i = 100 为一,秒标志位加 1
if(miao == 60){
miao = 0; //满一分清零
fen++;
if(fen == 60){
fen = 0; //满一时清零
shi++;
if(shi == 24){
shi = 0; //24小时制
fen = 0;
miao = 0;
}
}
}
}
}
void LCD_display(void) //lcd1602显示时分秒
{
LCD_disp_char(2,15,num[*time[0]%10]); //显示秒的个位 当miao%10的值为0时即(*time[0])==0, 此时num[0]=0x30 对应1602字符库中的0 ,lcd1602对应第2行第16位显示0
delay(50); //当miao%10的值为1时即(*time[1])==1, 此时num[1]=0x31 对应1602字符库中的1
LCD_disp_char(2,14,num[*time[0]/10]); //秒的十位
delay(50);
LCD_disp_char(2,13,':');
delay(50);
LCD_disp_char(1,3,'1');
LCD_disp_char(1,5,'0');
LCD_disp_char(1,7,'6');
if (alarmset==0) //时钟模式
{
LCD_disp_char(2,12,num[*time[1]%10]); //分的各位
delay(50);
LCD_disp_char(2,11,num[*time[1]/10]); //分的十位
delay(50);
LCD_disp_char(2,10,':'); //字符‘-’
delay(50);
LCD_disp_char(2,9,num[*time[2]%10]); //时的个位
delay(50);
LCD_disp_char(2,8,num[*time[2]/10]); //时的十位
delay(50);
}
}
void shezhi(void) //设置函数
{
if (kaiguan==0)
{
if (key4==0)
{
delay_n40us(50000); //消抖
if (key4==0)
{
set++;
if (set>=2)
{
set=0;
}
while(key4==0) //检测按键是否松开
{
delay(10);
}
}
}
switch (set) //设置模式显示
{
case 0 : { LCD_row(2);
LCD_DispString("TIME ");
delay(50); } ; break;
case 1 : { LCD_row(2);
LCD_DispString("clock");
delay(50); } ; break;
}
if ((set==1) && (key1==0) &&(mod==0))
{
delay(10);
if (key1==0)
{
kaiguan=1;
mod=1; //进入或退出设置 设置时间
TR0=0; //打开或关闭定时器中断
SetPlace=0; //模式选择位清零
}
while(key1==0) //检测按键是否松开
{
delay(10);
}
}
}
if (kaiguan==1)
{
if ((set==1) && (key4==0) )
{
delay(10);
if (key4==0)
{
kaiguan=0;
mod=0; //进入或退出设置 设置时间
TR0=1; //打开或关闭定时器中断
SetPlace=