[51 single-chip microcomputer] display time on LCD1602: including buttons to calibrate the time + alarm clock function: buttons to set the alarm clock ringing time and the duration of the ringing

Implemented on the 51 development board, the crystal oscillator is: 11.0592Mhz

The circuit is as follows:

LCD1602

Buzzer part:

 

 

 

Show time interface:

Change time page:

Set trigger alarm clock time page:

Set the alarm clock ringing duration page: (O bubble time length is 3 seconds)

k1 button

Press the 1st time to calibrate the hour
Press the second time to calibrate the minutes
Press the third time to calibrate the seconds
Press the 4th time, the time starts to move

k2 button

add

 k3 button

reduce

k4 button

Press the first time to set the hour to trigger the alarm
Press a second time to change the minute that triggers the alarm
Press the third time to set the ringing duration of the alarm in seconds
Press the fourth time to return to the display time page

Implementation code:

#include <REGX52.H>
typedef unsigned char uchar;
sbit LCD_RS=P2^6;
sbit LCD_RW=P2^5;
sbit LCD_E=P2^7;
char hour=23,minute=59,second=58;//时钟变量
char S=3,M=0,H=0;//闹钟初值,S代表闹钟要打铃 的秒数(时长)
uchar mode=0,T0_flag=0;

void Delay(unsigned int xms)
{//延时函数
	uchar i, j;
	while(xms--){
		i = 2;
		j = 239;
		do{
			while (--j);
		} while (--i);
	}
}
void LCD_WriteCmd(uchar Command)
{//写命令函数
	LCD_RS=0;
	LCD_RW=0;
	P0=Command;
	LCD_E=1;
	Delay(1);
	LCD_E=0;
	Delay(1);
}
void LCD_WriteData(uchar Data)
{//写数据函数
	LCD_RS=1;
	LCD_RW=0;
	P0=Data;
	LCD_E=1;
	Delay(1);
	LCD_E=0;
	Delay(1);
}

void LCD_Init(void)
{//初始化lcd1602
	LCD_WriteCmd(0x38);
	LCD_WriteCmd(0x0C);
	LCD_WriteCmd(0x06);
	LCD_WriteCmd(0x01);
}
void LCD_SetCursor(uchar Line,uchar Column)
{//选择显示的行和列,参数1:行,参数2:列
    LCD_WriteCmd(Column-1|(Line==1?0x80:0xC0));
}

void LCD_ShowString(uchar Line,uchar Column,char *String)
{//选择要显示的字字符串,参数1:行,参数2:列参数3:字符串
	unsigned char i;
	LCD_SetCursor(Line,Column);
	for(i=0;String[i]!='\0';i++)
		LCD_WriteData(String[i]);
}
void LCD_ShowTime(char h,char m,char s)
{ //在LCD1602上面 显示时间界面
        LCD_SetCursor(2,5);   
		LCD_WriteData(h/10+0x30);
        LCD_WriteData(h%10+0x30);
        LCD_WriteData(':');
        LCD_WriteData(m/10+0x30);
        LCD_WriteData(m%10+0x30);
        LCD_WriteData(':');
        LCD_WriteData(s/10+0x30);
        LCD_WriteData(s%10+0x30);             
}

void LCD_ShowSetSlarm()
{//显示 设置闹铃时间界面    
        LCD_ShowString(2,1,"hour:");                 
		LCD_WriteData(H/10+0x30);
        LCD_WriteData(H%10+0x30);
        LCD_ShowString(2,10,"min:");        
        LCD_WriteData(M/10+0x30);
        LCD_WriteData(M%10+0x30);        
}
void LCD_ShowSetDuration()
{//显示 设置闹铃时长界面
    LCD_ShowString(2,1,"duration:");
    LCD_WriteData(S/10+0x30);
    LCD_WriteData(S%10+0x30); 
     LCD_ShowString(2,12,"s");
}
void key_scan()
{//按键扫描,进行模式和档位的更改 
    static uchar flag=0;
    if(P3_1==0){   //档位选择
        Delay(20);
        while(P3_1==0);
        Delay(20);
        TR0=0;//关闭T0中断请求
        flag++;
        if(flag==4){
            flag=0;
            LCD_WriteCmd(0x01);//清屏
            TR0=1;
            }
    }
    if(P3_3==0){//模式切换按键
        Delay(20);
        while(P3_3==0);
        Delay(20);
        LCD_WriteCmd(0x01);
        mode++; 
        if(mode==4)//模式切换成时钟模式 
            mode=0;       
    }
    if(mode==0){    //时钟模式  
        if(flag!=0){
            LCD_ShowString(1,2,"Change Time");
            switch(flag){
                case 1:if(P3_0==0){ Delay(20);while(P3_0==0);Delay(20);hour++; if(hour>23) hour=0;}break;
                case 2:if(P3_0==0){ Delay(20);while(P3_0==0);Delay(20);minute++; if(minute>59) minute=0;}break;
                case 3:if(P3_0==0){ Delay(20);while(P3_0==0);Delay(20);second++; if(second>59) second=0;}break;
                default:break;
            }
            switch(flag){
                case 1:if(P3_2==0){ Delay(20);while(P3_2==0);Delay(20);hour--; if(hour<0) hour=23;}break;
                case 2:if(P3_2==0){ Delay(20);while(P3_2==0);Delay(20);minute--; if(minute<0) minute=59;}break;
                case 3:if(P3_2==0){ Delay (20);while(P3_2==0);Delay(20);second--; if(second<0) second=59;}break;
                default:break;
            }
        }else{
            LCD_ShowString(1,7,"Time");
        }
    }else if(mode==1){//闹钟时 设置
        LCD_ShowString(1,4,"Set alarm");
        if(P3_0==0){ Delay(20);while(P3_0==0);Delay(20);H++;if(H>23) H=0;}
        if(P3_2==0){ Delay(20);while(P3_2==0);Delay(20);H--;if(H<0) H=23;}        
    }else if(mode==2){//闹钟分 设置
        LCD_ShowString(1,4,"Set alarm");
        if(P3_0==0){ Delay(20);while(P3_0==0);Delay(20);M++;if(M>59) M=0;}
        if(P3_2==0){ Delay(20);while(P3_2==0);Delay(20);M--;if(M<0)  M=59;}        
    }else if(mode==3){//设置响铃时长,单位为秒
        LCD_ShowString(1,4,"O pao Time");       //O泡时间到
        if(P3_0==0){ Delay(20);while(P3_0==0);Delay(20);S++;if(S>59) S=0;}
        if(P3_2==0){ Delay(20);while(P3_2==0);Delay(20);S--;if(S<0)  S=59;}        
    }       
}
void Timer0Init()
{//定时器0初始化函数,定时:50毫秒  晶振为:11.0592MHz
	TMOD &= 0xF0;		//设置定时器模式
	TMOD |= 0x01;		//设置定时器模式
	TL0 = 0x00;		    //设置定时初值
	TH0 = 0x4C;		    //设置定时初值
	TF0 = 0;		    //清除TF0标志
	TR0 = 1;		    //定时器0开始计时
    ET0=1;              //打开定时器T0中断小开关
	EA=1;               //打开总开关   
}

void main()
{
    Timer0Init();   
	LCD_Init();					    
    while(1){
        key_scan();
        if(hour==H&&minute==M&&second<S)
            P1_5=~P1_5;           
        switch(mode){
           case 0:LCD_ShowTime(hour,minute,second);break; 
           case 1:case 2:LCD_ShowSetSlarm();break;
           case 3: LCD_ShowSetDuration();                 
        }  
    }
}

void interrupt_T0()interrupt 1
{//定时器0中断函数
    TL0 = 0x00;		    //重新设置定时初值
	TH0 = 0x4C;		    //重新设置定时初值
    T0_flag++;
    if(T0_flag==20){
        T0_flag=0;     
        second++;
        if(second==60){
            second=0;
            minute++;
            if(minute==60){
                minute=0;
                hour++;
                if(hour==24)
                    hour=0;               
           }
        }
    }
}

Guess you like

Origin blog.csdn.net/yvge669/article/details/125258385