51单片机lcd1602的问题,急



#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);
     } 
  }
}

这是我自己在keil5上敲的代码,现在的情况是只显示一位数据,我想让他显示出11位数据后无论怎么按键都没法显示出数据,且按一下按键显示出一位数据

首先需要清楚你使用的是什么类型的LCD屏幕,以及它的显示模式。根据你的代码,应该是16x2字符型LCD屏幕,数据传输方式为8位并行传输。

在程序执行过程中,当检测到按键时,你使用了write_command(0xc0)命令将光标移动到第二行开始的位置,并写入数据。每次按键都会重新写入一位数值,因此只显示一位数据。

如果想要实现输入11位数据后停止显示,可以设置一个计数器,每输入一位数据计数器加1,当计数器累加到11时,停止显示并等待新的输入。在此之前,也需要清空LCD屏幕上的显示内容,可以使用write_command(0x01)命令清屏。

另外,你的程序中keyval变量的初值为11,不适合作为按键扫描函数的返回值。建议将keyval初值设置为255或其他不可能出现的值。在按键扫描函数中,如果没有检测到按键值,则返回该初值。

最后,按键检测函数的时间延迟可以设置得更短,例如5ms,以提高响应速度

  • 你可以参考下这个问题的回答, 看看是否对你有帮助, 链接: https://ask.csdn.net/questions/7689209
  • 除此之外, 这篇博客: 基于51单片机下通过蓝牙串口控制LCD1602屏幕显示步进电机正反转以及转速中的 5.main.c 部分也许能够解决你的问题, 你可以仔细阅读以下内容或跳转源博客中阅读:
  • #include "123.h"
    
    main()
    {
    	L1602_init();
        Delay(100);
        UartInit();
        while(1)
        {
        	panduan();
        }
    }
    
    void panduan()
    {
    	if(flag == 0)		//判断正转
    	{
    		led = 0;	//状态灯灭
    					
    		forward(speed);		//电机执行正转且返回速度送给下面进行判断
    					
    		if(speed == 1)			//如果为1	则速度显示为快速
    		{
    			LCD_display("Mo Dir: Goto","Mo Spd: Fast ^_^");
    		}
    					
    		else if(speed == 3)		//如果为3	则速度显示为中速
    		{
    			LCD_display("Mo Dir: Goto","Mo Spd: Norl ^_^");
    		}
    					
    		else if(speed == 5)		//如果为5	则速度显示为慢速
    		{
    			LCD_display("Mo Dir: Goto","Mo Spd: Slow ^_^");
    		}
    	}
    
    
    	if(flag == 1)			//判断反转
    	{
      	  led = 1;			//状态灯亮
              
    		back(speed);
    		  
    		if(speed == 1)			//电机执行正转且返回速度送给下面进行判断
    		{
    			LCD_display("Mo Dir: Back","Mo Spd: Fast ^_^");
    		}
    		else if(speed == 3)
    		{
    		 	LCD_display("Mo Dir: Back","Mo Spd: Norl ^_^");
    		}
    		else if(speed == 5)
    		{
    		 	LCD_display("Mo Dir: Back","Mo Spd: Slow ^_^");
    		}
    	}
    }
    
    void Usart() interrupt 4			//中断服务函数
    {
        uchar n; //定义临时变量
    //	led = 1;
        if(RI) //判断是接收中断产生
        {
            RI = 0; //标志位清零
            n = SBUF; //读入缓冲区的值
            switch(n)
            {
            case'0':		//控制正转
            	flag = 0;
            break;
    				
            case'1':		//控制反转
            	flag = 1;
            break;
    				
    		case'2':		//控制速度为慢
    			speed = 5;
    		break;
    				
    		case'3':		//控制速度为中等
    			speed = 3;
    		break;
    				
    		case'4':		//控制速度为快
    			speed = 1;
    		break;
    				
            }
            TI = 1;
            SBUF = n; //把接收到的值再发回
        }
       		if(TI) //如果是发送标志位,清零
            TI = 0;
    }