51单片机矩形按键与lcd1602相关问题

在lcd1602上显示出按键的按值,就是显示出手机号码,下面是我在keil5上自己敲的代码,现在问题是只能显示出一位数字,有没有人教一下?


#include <reg51.h>
#include <intrins.h>
#include <string.h>
#define uchar unsigned char
#define uint unsigned int
sbit RS=P1^7;                 
sbit RW=P1^6;                
sbit E=P1^5; 
uchar code str1[]={0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39};
uchar code str2[]={0x4e,0x65,0x77,0xfe,0x54,0x65,0x6c,0x4e,0x75,0x6d,0x2e,0x2e,0x2e,0xfe,0xfe,0xfe};
uchar code str3[]={0x49,0x6e,0x70,0x75,0x74,0xfe,0x54,0x65,0x6c,0x4e,0x75,0x6d,0x2e,0x2e,0x2e,0xfe};
uchar keyval=11;
void delayms(uint n)            
{
    uchar i;
    while(n--)
      for(i=0;i<113;i++);
}
void check_busy(void)     
{
    uchar dt;
    do
    {
        dt=0xff;
        E=0;
        RS=0;    
        RW=1;
        E=1;
        dt=P0;
        
    }while(dt&0x80);
    E=0;
}

void write_command(uchar com)      
{
    check_busy();
    E=0;
    RS=0;
    RW=0;
    P0=com;
    E=1;
    _nop_( );
    E=0;
    delayms(1);
}

void write_data(uchar dat)        
{
    check_busy();
    E=0;
    RS=1;
    RW=0;
    P0=dat;
    E=1;
    _nop_();
    E=0;
    delayms(1);    
}
void LCD_initial(void)     
{
    write_command(0x38);    
    _nop_( );  
    write_command(0x0C);    
    _nop_( );
    write_command(0x06);    
    _nop_( );
    write_command(0x01);     
    delayms(2);
}

void write_string(uchar addr,uchar str[])
{
   uchar i;
   write_command(0x80+addr);
   for(i=0;i<strlen(str);i++)
   {
     write_data(str[i]);
   }
}
uchar keyscan()
{
  uint row,rol;
    P2=0xf0;
    if((P2&0xf0)!=0xf0)
    {
      delayms(20);
        if((P2&0xf0)!=0xf0)
        {
        switch(P2&0xf0)
        {
            case 0x70:rol=0;break;
          case 0xb0:rol=1;break;
            case 0xd0:rol=2;break;
            case 0xe0:rol=3;break;
        }
        P2=0x0f;
        if((P2&0x0f)!=0x0f)
        {
        switch(P2&0x0f)
        {
            case 0x07:row=0;break;
      case 0x0b:row=1;break;
            case 0x0d:row=2;break;
            case 0x0e:row=3;break;
        }
        while((P2&0x0f)!=0x0f);
        keyval=rol*4+row;
        }
    }
 }
    return keyval;
}
void main()
{
 LCD_initial();
    write_string(0x00,str3);
 while(1)
 {
  keyscan();
     if(keyval<=9)
     {
     write_command(0xc0);
       write_data(str1[keyval]);
         }
     if(keyval==10)
     {
         write_string(0x00,str2);
         write_command(0xc0);
       write_data(0xfe);
     } 
  }
}

参考GPT和自己的思路:你可以尝试在keyscan函数中添加一个判断,如果当前已经按下了一个数字键,再次按下数字键时,可以将当前的数字与新的数字拼接起来,组成一个手机号码。例如:

void main()
{
    LCD_initial();
    write_string(0x00,str3);
    uchar phone[12]=""; // 定义一个字符串,存储手机号码
    while(1)
    {
        keyscan();
        if(keyval<=9)
        {
            write_command(0xc0);
            write_data(str1[keyval]);
            if(strlen(phone)<11) // 手机号码最多只能11位
            {
                phone[strlen(phone)] = str1[keyval]; // 将当前按下的数字加入手机号码中
            }
        }
        if(keyval==10)
        {
            write_string(0x00,str2);
            write_command(0xc0);
            write_data(0xfe);
            memset(phone, 0, sizeof(phone)); // 清空手机号码
        } 
        if(strlen(phone)==11) // 如果手机号码已经11位,显示手机号码
        {
            write_string(0x00, phone);
        }
    }
}

参考GPT和自己的思路:你的代码中只显示一位数字是因为在keyscan()函数中,当按键按下后keyval的值被记录,但没有重置,所以当下一次循环中keyval的值还是上一次按下的值,导致只显示一位数字。解决方法是在处理完keyval后要将其重置为一个不可能的值,比如keyval=11,即可避免此问题。另外,你在显示手机号码时,只有10个数字键和1个特殊键(#键),如果按下的键值超过这个范围,代码中并没有对keyval进行处理,这也需要注意。

  • 你可以参考下这个问题的回答, 看看是否对你有帮助, 链接: https://ask.csdn.net/questions/7485763
  • 这篇博客你也可以参考下:【51单片机】在LCD1602上显示时间:包含按键进行校准时间+闹钟功能:按键设置闹钟响铃时间,以及响铃的时间长度
  • 除此之外, 这篇博客: 51单片机LCD1602电子时钟中的 八.有关错误的查找 部分也许能够解决你的问题, 你可以仔细阅读以下内容或跳转源博客中阅读:
  • 有些错误不一定会显示,如内存溢出这种就不会显示,这些还需要自己去了解,通过上网搜索等方式寻找解决方法

    #include <reg51.h>
    #include <math.h>
    
    sbit RS=P2^4;
    sbit RW=P2^5;
    sbit E=P2^6;
    sbit BUZ=P1^0;
    sbit IN=P2^0;
    sbit DE=P2^1;
    sbit BA=P2^2;
    
    unsigned char code mod1[]=" workmod1:clock ";
    unsigned char code mod2[]=" workmod2:setup ";
    unsigned char code mod3[]=" workmod3:alarm ";
    unsigned char code mod4[]=" workmod4:timer ";
    unsigned int code timenumber[]={0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39};//0,1,2,3,4,5,6,7,8,9
    
    unsigned int o,p;
    unsigned char bs,i;
    unsigned int c1,c2,c3,c4,c5,c6,z,i3;//mod1
    unsigned int s;//mod2
    long int a;
    long int kk,k2;//mod4
    long int t,k,i1,i2;//timer
    
    void delay(int t)//50us
    {
    	unsigned int x;
        for(;t>0;t--)
        for(x=19;x>0;x--);
    }
    
    void writecom(unsigned char com)
    {
        E=0;
        RS=0;
        RW=0;
        P0=com;
        delay(10);
        E=1;
        delay(20);
        E=0;
    }
    
    void writedate(unsigned char dat)
    {
    	E=0;
    	RS=1;
    	RW=0;
    	P0=dat;
    	delay(10);
    	E=1;
    	delay(20);
    	E=0;
    }
    
    void innit()
    {
    	delay(30);
    	writecom(0x38);
        delay(10);
        writecom(0x38);
        delay(10);
        writecom(0x38);
        writecom(0x38);
        writecom(0x08);
        writecom(0x01);
        writecom(0x06);
        writecom(0x0c);
    }
    
    void workmod1()
    {
    innit();
    s=0;
    while(bs==0)
    {
    	writecom(0x80);
    	for(i=0;i<16;i++)
    	{
    		writedate(mod1[i]);
    	}
    	writecom(0x80+0x40);
    	if(s==0)writedate('O'),writedate('F'),writedate('F');
    	if(s==1)writedate('O'),writedate('N'),writedate(' ');
    	c1=i1%10,c2=i1/10,c3=i2%60%10,c4=i2%60/10,c5=i2/60%24%10,c6=i2/60%24/10;
    	writecom(0x80+0x45);
    	writedate(timenumber[c6]);writedate(timenumber[c5]);
    	writedate(':');
    	writedate(timenumber[c4]);writedate(timenumber[c3]);
    	writedate(':');
    	writedate(timenumber[c2]);writedate(timenumber[c1]);
    	i3=i2/60;
    	if(i3!=z)//strike
    	{
    		o=1;	
    		z=i3;
    	}
    	if(s==1&&a==i2)o=1;//alarm
        }
    }
    
    void workmod2()
    {
    innit();
    s=0;
    writecom(0x80);
    for(i=0;i<16;i++)
    {
    	writedate(mod2[i]);
    }
      while(bs==1)
    {
    	i1=0;
    	writecom(0x80+0x4a);
    	writedate(':');writedate('0');writedate('0');
    	writecom(0x80+0x40);
    	switch(s)
    		{
    			case 0:
    				{
    					writedate('M');
    					if(IN==0)
    						{
    							delay(500);
    							i2++;
    							delay(500);
    						}
    						else if(DE==0)
    							{
    								delay(500);
    								i2--;
    								delay(500);
    							}
    				}break;
    			case 1:
    				{
    					writedate('H');
    					if(IN==0)
    						{
    							delay(500);
    							i2=i2+60;
    							delay(500);
    						}
    						else if(DE==0)
    							{
    								delay(500);
    								i2=i2-60;
    								delay(500);
    							}
    				}break;
    		}
    		c1=i1%10,c2=i1/10,c3=i2%60%10,c4=i2%60/10,c5=i2/60%24%10,c6=i2/60%24/10;
    		writecom(0x80+0x45);
    		writedate(timenumber[c6]);writedate(timenumber[c5]);
    		writedate(':');
    		writedate(timenumber[c4]);writedate(timenumber[c3]);
    }
    }
    
    void workmod3()
    {
    innit();
    s=0;
    writecom(0x80);
    for(i=0;i<16;i++)
    {
    	writedate(mod3[i]);
    }
    while(bs==2)
    	{
    		if(a==1440)a=0;
    		writecom(0x80+0x40);
    		switch(s)
    			{
    			case 0:
    				{
    					writedate('M');
    					if(IN==0)
    						{
    							delay(500);
    							a++;
    							delay(500);
    						}
    						else if(DE==0)
    							{
    								delay(500);
    								a--;
    								delay(500);
    							}
    				}break;
    			case 1:
    				{
    					writedate('H');
    					if(IN==0)
    						{
    							delay(500);
    							a=a+60;
    							delay(500);
    						}
    						else if(DE==0)
    							{
    								delay(500);
    								a=a+60;
    								delay(500);
    							}
    				}break;
    			}
    			writecom(0x80+0x45);
    			c3=a%60%10,c4=a%60/10,c5=a/60%10,c6=a/60/10;
    			writedate(timenumber[c6]);writedate(timenumber[c5]);
    			writedate(':');
    			writedate(timenumber[c4]);writedate(timenumber[c3]);
    	}
    }
    
    void workmod4()
    {
    innit();
    kk=0;
    writecom(0x80);
    for(i=0;i<16;i++)
    {
    	writedate(mod4[i]);
    }
    while(bs==3)
    	{
    		k2=0;
    		if(s==0)
    			{
    				writecom(0x80+0x45);
    				writedate('R');
    				writedate('E');
    				writedate('A');
    				writedate('D');
    				writedate('Y');
    			}
    			else if(s==1)
    				{
    					writecom(0x80+0x45);
    					for(i=0;i<5;i++)
    					writedate(' ');
    				while(kk!=60&&bs==3&&s==1)
    					{
    						kk=k2/20;
    						writecom(0x80+0x47);
    						writedate(timenumber[(60-kk)/10]);writedate(timenumber[(60-kk)%10]);
    					}
    					if(kk==60)o=1,s=0,kk=0;
    				}
    	}
    }
    
    void main()
    {
    innit();
    TMOD=0x01;TH0=(65536-50000)/256;TL0=(65536-50000)%256;
    EA=1;EX0=1;EX1=1;
    IT0=1;IT1=1;
    ET0=1;TR0=1;
    k=0;bs=0;s=0;z=0;k2=0;i1=0;i2=0;kk=0;a=0;o=0;p=0;
    while(1)
    {
    	switch(bs)
    	{
    		case 0:workmod1();break;
    		case 1:workmod2();break;
    		case 2:workmod3();break;
    		case 3:workmod4();break;
    	}
    }
    }
    
    void int0 () interrupt 0//buttion:affirm
    {
    s++;s=s%2;
    BUZ=1;
    }
    
    void timer0 () interrupt 1
    {
    for(t=0;t<20;t++)
    {
    	TH0=(65536-50000)/256;
    	TL0=(65536-50000)%256;
    }
    k++;
    if(k==20) i1++,k=0;
    if(i1==60) i2++,i1=0;
    if(i2==1440) i2=0;
    k2++;//only mod4
    if(o)BUZ=0,p++;
    if(p==40)BUZ=1,o=0,p=0;
    }
    
    void int2 () interrupt 2//buttion:set up
    {
    kk=0;BUZ=1;
    bs++;
    bs=bs%4;
    }
    
  • 您还可以看一下 朱有鹏老师的LCD1602和12864显示器-第1季第17部分课程中的 1.17.5.LCD1602控制器的低层时序2小节, 巩固相关知识点