[51 single-chip microcomputer] LCD1602 display string, time, time + key calibration, function code of stopwatch timing.

LCD1602 displaying characters and time is the most basic experiment. After synthesizing the previous knowledge and combining the c language programming, you can use independent buttons to calibrate the time, timing and other functions, or input through the buttons of the matrix keyboard, and then Let the LCD screen display the content and effect we want. In response to the requirements of the experiment, 4 codes were written.

This experiment uses a 51 development board with a 12.000MHz crystal oscillator.

8bf54d691c4a4ca080c60b810f1a66e8.png

LCD1602 circuit connection diagram

 Code 1: (Display "Welcome to Baise University" on the LCD -> (Welcome to Baise University) )

#include <REGX52.H>
typedef unsigned char uchar;
sbit LCD_RS=P2^6;
sbit LCD_RW=P2^5;
sbit LCD_E=P2^7;
 char count=0,hour=23,minute=59,second=55;

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)
{//初始化
	LCD_WriteCmd(0x38);
	LCD_WriteCmd(0x0C);
	LCD_WriteCmd(0x06);
	LCD_WriteCmd(0x01);
}
void LCD_SetCursor(uchar Line,uchar Column)
{//设置显示的行数和列数
	 LCD_WriteCmd(Line==1?0x80+(Column-1):0xC0+(Column-1));
}

void LCD_ShowString(uchar Line,uchar Column,char *String)
{//在指定的行数和列数显示对应的字符串
	uchar i;
	LCD_SetCursor(Line,Column);
	for(i=0;String[i]!='\0';i++)
		LCD_WriteData(String[i]);	
}

void main(){ 
	LCD_Init();

	LCD_ShowString(1,1,"Welcome to Baise");		
    LCD_ShowString(2,1,"University!");		
    while(1);
}

bb0aaa7f46e340d6925107bb42042b9a.jpeg

Display: Welcome to Baise College

 Code 2: (LCD display time)

#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=55;//时间变量:时、分、秒
uchar T0_flag=0;
void Delay(unsigned int xms)
{//延时函数
	unsigned char 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)
{//选择显示的行和列:参数一代表行,参数二代表列
	 LCD_WriteCmd(Line==1?0x80+(Column-1):0xC0+(Column-1));
}

void LCD_ShowString(uchar Line,uchar Column,char *String)
{//选择要显示的字字符串,参数一代表行,参数二代表列,参数三要传一个字符串进来,或者字符型的指针
	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上面显示时间 ,用定时器1 
        LCD_ShowString(1,7,"Time");
        LCD_SetCursor(2,5);   
		LCD_WriteData(h/10+0x30);
        LCD_WriteData(h%10+0x30);
        LCD_WriteData(0x3a);
        LCD_WriteData(m/10+0x30);
        LCD_WriteData(m%10+0x30);
        LCD_WriteData(0x3a);
        LCD_WriteData(s/10+0x30);
        LCD_WriteData(s%10+0x30);             
}

void Timer0Init()		//50毫秒@12.000MHz
{
	TMOD &= 0xF0;		//设置定时器模式
	TMOD |= 0x01;		//设置定时器模式
	TL0 = 0xB0;		    //设置定时初值
	TH0 = 0x3C;		    //设置定时初值
	TF0 = 0;		    //清除TF0标志
	TR0 = 1;		    //定时器0开始计时
    ET0=1;              //打开小开关
	EA=1;               //打开总开关   
}


void main(){
    Timer0Init();
	LCD_Init();					
    while(1)
        LCD_ShowTime(hour,minute,second);      
}

void interrupt_T0()interrupt 1
{//定时器0中断函数
    TL0 = 0xB0;		
	TH0 = 0x3C;		
    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;               
           }
        }
    }
}
1627250ab80f4642a9c1e5ba8fb8cd6f.jpeg

Time display renderings

 Simply display variable time on LCD1602

Note: If you feel that the time is not accurate, it may be a problem with different crystal oscillators. Here my crystal oscillator is 12MHZ. If the crystal oscillator frequency is 11.0592MHZ, you must initialize and interrupt TL1 in the code = 0xB0; and TH1 = 0x3C; Change to TL1 == 0x00; TH1 = 0x4C;

Code 3: (display time + button scan)

#include <REGX52.H>
typedef unsigned char uchar;
sbit LCD_RS=P2^6;
sbit LCD_RW=P2^5;
sbit LCD_E=P2^7;
 char T0_flag=0,hour=23,minute=59,second=55;

void Delay(unsigned int xms)
{//延时函数
	unsigned char 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)
{//选择显示的行和列:参数一代表行,参数二代表列
	 LCD_WriteCmd(Line==1?0x80+(Column-1):0xC0+(Column-1));
}

void LCD_ShowString(uchar Line,uchar Column,char *String)
{//选择要显示的字字符串,参数一代表行,参数二代表列,参数三要传一个字符串进来,或者字符型的指针
	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上面显示时间 ,用定时器1            
        LCD_SetCursor(2,5);   
		LCD_WriteData(h/10+0x30);
        LCD_WriteData(h%10+0x30);
        LCD_WriteData(0x3a);
        LCD_WriteData(m/10+0x30);
        LCD_WriteData(m%10+0x30);
        LCD_WriteData(0x3a);
        LCD_WriteData(s/10+0x30);
        LCD_WriteData(s%10+0x30);            
}

void key_scan(){
   static uchar flag=0;
    if(P3_1==0){
        Delay(20);
        while(P3_1==0);
        Delay(20);
        TR0=0;//关闭中断请求
        flag++;
        
        if(flag==4){
           flag=0;
            TR0=1;
            LCD_WriteCmd(0x01);
            }
    }
        
    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");
    }
}
void Timer0Init()		//50毫秒@12.000MHz
{
	TMOD &= 0xF0;		//设置定时器模式
	TMOD |= 0x01;		//设置定时器模式
	TL0 = 0xB0;		    //设置定时初值
	TH0 = 0x3C;		    //设置定时初值
	TF0 = 0;		    //清除TF0标志
	TR0 = 1;		    //定时器0开始计时
    ET0=1;              //打开小开关
	EA=1;               //打开总开关   
}


void main(){
    Timer0Init();
	LCD_Init();					
    while(1){
        key_scan();
        LCD_ShowTime(hour,minute,second);  
    }
}

void interrupt_T0()interrupt 1
{//定时器0中断函数
    TL0 = 0xB0;		
	TH0 = 0x3C;		
    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;               
           }
        }
    }
}

67a45bf6f3a5414db6ac5802da99f60b.jpeg

Button change time rendering

Function: Calibrate the time through independent buttons.

k1 Press once to pause the clock, to change the hour gear, to change the minute gear for the second time, to change the second gear for the third time, to start the clock for the fourth time
k2 Hour/minute/second value plus one
k3 Hour/minute/second value minus one

The independent button circuit is as follows:

f5dacf41f5924a8592be6860bbdb4f89.png

Independent button circuit connection diagram

 Code 4: (display time + button scan + stopwatch timing)

#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=55;//时钟变量
char S=0,M=0,H=0;//秒表变量
uchar mode=0,T0_flag=0,T1_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)
{//选择显示的行和列:参数一代表行,参数二代表列
	 LCD_WriteCmd(Line==1?0x80+(Column-1):0xC0+(Column-1));
}

void LCD_ShowString(uchar Line,uchar Column,char *String)
{//选择要显示的字字符串,参数一代表行,参数二代表列,参数三要传一个字符串进来,或者字符型的指针
	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上面显示时间 ,用定时器1     
        LCD_SetCursor(2,5);   
		LCD_WriteData(h/10+0x30);
        LCD_WriteData(h%10+0x30);
        LCD_WriteData(0x3a);
        LCD_WriteData(m/10+0x30);
        LCD_WriteData(m%10+0x30);
        LCD_WriteData(0x3a);
        LCD_WriteData(s/10+0x30);
        LCD_WriteData(s%10+0x30);             
}

void LCD_ShowStopwatch()
{//在lcd1602上面显示秒表 ,用定时器2     ,       
        LCD_SetCursor(2,5);   
		LCD_WriteData(H/10+0x30);
        LCD_WriteData(H%10+0x30);
        LCD_WriteData(0x3a);
        LCD_WriteData(M/10+0x30);
        LCD_WriteData(M%10+0x30);
        LCD_WriteData(0x3a);
        LCD_WriteData(S/10+0x30);
        LCD_WriteData(S%10+0x30);           
}

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==2)//模式切换成时钟模式 
            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 {//秒表模式
        LCD_ShowString(1,4,"Stopwatch");
        if(P3_2==0){ Delay(20);while(P3_2==0);Delay(20);S=0,H=0,M=0;}/*秒表清零*/
        if(P3_0==0){ Delay(20);while(P3_0==0);Delay(20);TR1=~TR1;}/*秒表 暂停/启动*/
    }
}
void Timer0Init()
{//定时器0初始化函数,定时:50毫秒  晶振为:12.000MHz

	TMOD &= 0xF0;		//设置定时器模式
	TMOD |= 0x01;		//设置定时器模式
	TL0 = 0xB0;		    //设置定时初值
	TH0 = 0x3C;		    //设置定时初值
	TF0 = 0;		    //清除TF0标志
	TR0 = 1;		    //定时器0开始计时
    ET0=1;              //打开定时器T0中断小开关
	EA=1;               //打开总开关   
}

void Timer1Init(void)		
{//定时器1初始化函数,定时:50毫秒  晶振为:12.000MHz

	TMOD &= 0x0F;		//设置定时器模式
	TMOD |= 0x10;		//设置定时器模式	
    TL1 = 0xB0;		//设置定时初值
	TH1 = 0x3C;		//设置定时初值
	TF1 = 0;		//清除TF1标志	
    ET1=1;          //打开定时器T1中断小开关
    EA=1;           //打开总开关     
}
void main()
{
    Timer0Init();
    Timer1Init();
	LCD_Init();					    
    while(1){
        key_scan();
        switch(mode){
           case 0:LCD_ShowTime(hour,minute,second);break; 
           case 1:LCD_ShowStopwatch();break;     
        }  
    }
}

void interrupt_T0()interrupt 1
{//定时器0中断函数
    TL0 = 0xB0;		    //重新设置定时初值
	TH0 = 0x3C;		    //重新设置定时初值
    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;               
           }
        }
    }
}

void interrupt_T1() interrupt 3
{//定时器1中断函数 
    TL1 = 0xB0;		//重新设置定时初值
	TH1 = 0x3C;		//重新设置定时初值
    T1_flag++;
    if(T1_flag==20){
        T1_flag=0;     
        S++;
        if(S==60){
            S=0;
           M++;
            if(M==60){
                M=0;
                H++;
                if(H==24)
                    H=0;               
           }
        }
    }
}

da6e6366532b47d1b0f7d1767984a21f.jpeg

Effect drawing of stopwatch timing

Instructions for use: 

independent button
k4 Mode switching (clock/stopwatch)


In clock mode:

k1 Press once to pause the clock, to change the hour gear, to change the minute gear for the second time, to change the second gear for the third time, to start the clock for the fourth time
k2 Hour/minute/second value plus one
k3 Hour/minute/second value minus one

In stopwatch mode:

k1 none
k2 Stopwatch Pause/Start
k3 Stopwatch reset

Experience: To write to the LCD, you must first understand the LCD data manual. To display the content, you must have a display function. Before that, you must have a function to write commands and write data. You must understand the timing diagram for writing commands and writing data. To code code.

Stay up all night and make some study notes. 

Guess you like

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