lcd1602下在proteus中仿真显示字符,一直出不来 求助了


#include <reg51.h>
#include <intrins.h>
//端口定义
sbit LCDRS = P1^0;  //寄存器选择 1:数据寄存器 0:指令寄存器
sbit  LCDRW = P1^1;  //读写 选择  1:读 0:写
sbit  LCDEN = P1^2;  //使能   1:可读写
sbit LCDBF = P0^7;  //LCD忙标志 Busy Flag
sfr  DBPORT = 0x80;  //数据端口0
//常量定义
#define LCD_DATA 1
#define LCD_COMMAND 0
#define LCD_READ 1
#define LCD_WRITE 0
void lcd_wait()
//等待LCD空闲
{ LCDEN=0;      
DBPORT=0xff;  //读LCD前若单片机输出低电平,而读出LCD为高电平,则冲突,Proteus仿真会有显示逻辑黄色
LCDRS=LCD_COMMAND;   
LCDRW=LCD_READ;
LCDEN=1; _nop_();
while(LCDBF)
{ LCDEN=0; _nop_();
  LCDEN=1; _nop_();
}
LCDEN=0;
}  
void lcd_command(unsigned char command)
//用参数传递写类型,消耗ROM更多,调用也不方便,不如写两个函数
//相同部分没有写成一个函数进行调用,因其本身占用ROM不多,而太多嵌套调用函数占用堆栈
//写入指令
{ lcd_wait();
LCDRS=LCD_COMMAND;
LCDRW=LCD_WRITE;  
DBPORT=command;  //注意写时序,先建立数据,再使能
LCDEN=1; _nop_();   
LCDEN=0;
}
void lcd_putchar(unsigned char character)
//写入数据
{ lcd_wait();     
LCDRS=LCD_DATA;
LCDRW=LCD_WRITE;  
DBPORT=character;  
LCDEN=1; _nop_();   
LCDEN=0;
}
/*  
void lcd_creat(unsigned char *char_code,unsigned char nofc)
//自定义字符
{ lcd_command(0x40);
while(nofc)
{ lcd_putchar(*char_code);
  char_code++;
  nofc--;
}
} */   
void lcd_moveto(unsigned char x, unsigned char y)
//设定要读写的字符 行,列 坐标
{ if(x==0)
  lcd_command(0x80|y);
if(x==1)
  lcd_command(0xc0|y);
}
   
void lcd_print(unsigned char *str)
//显示字符串
{ while(*str!='\0')
{ lcd_putchar(*str);
  str++;
}
}
void delayms(unsigned char ms)
// 延时子程序
{
unsigned char i;
while(ms--)
{
  for(i = 0; i < 100; i++);
}
}
void lcd_init()
//LCD模块电源若不符合内部自动启动电路要求,需使用指令启动
//仿真不需要,只要在程序中执行命令LCD_INIT,LCD_CLRS,并设置需要的显示模式,输入模式
{ unsigned char i;
LCDEN=0;
LCDRS=LCD_COMMAND;
LCDRW=LCD_WRITE;
DBPORT=0x30;
for(i=0;i<3;i++)
{ LCDEN=1; _nop_();  //LCD模块热启动,不检查忙信号
  LCDEN=0;
  delayms(5);
}
lcd_command(0x38);
lcd_command(0x01);
lcd_command(0x0f);
lcd_command(0x06);
lcd_command(0x80+0x01);
}
void main()
{
lcd_init();
lcd_wait();
lcd_putchar('a');

}
      电路图:

电路图.rar
(2008-07-17 16:43:29, Size: 19.5 KB, Downloads: 10)


我也来说两句 查看全部回复

最新回复

  • djh2007 (2008-7-17 16:44:50)

    哪位好心人 看了 指条路吧 这里先谢过了,
  • budhy (2008-7-17 17:00:46)

    QUOTE:

    原帖由 djh2007 于 2008-7-17 16:43 发表
    void lcd_wait()
    //等待LCD空闲
    { LCDEN=0;      
    DBPORT=0xff;  //读LCD前若单片机输出低电平,而读出LCD为高电平,则冲突,Proteus仿真会有显示逻辑黄色
    LCDRS=LCD_COMMAND;   
    LCDRW=LCD_READ;
    LCDEN=1; _nop_();
    while(LCDBF)
    { LCDEN=0; _nop_();
      LCDEN=1; _nop_();
    }
    LCDEN=0;
    }   ...
    问题好像处于以上程序。试一试用延时来等待 LCD 的反映。
  • djh2007 (2008-7-18 13:08:28)

    连接lcd的电平是有变化,不过还是不行啊!! 看了下资料 时序应该是没错的,怎么会没显示,哎~~~~
  • budhy (2008-7-18 14:36:10)

    QUOTE:

    原帖由 djh2007 于 2008-7-18 13:08 发表
    连接lcd的电平是有变化,不过还是不行啊!! 看了下资料 时序应该是没错的,怎么会没显示,哎~~~~
    楼主是在反应我在楼3#的意见吗?用延时代替等待LCD空闲,应该对电平没有影响的。
  • djh2007 (2008-7-18 15:41:33)

    哦,没仔细看,我还以为是在等待中再加几个延时
  • 绝处逢生 (2008-7-18 19:37:34)

    #include <reg51.h>
    #include <intrins.h>
    //端口定义
    sbit LCDRS = P1^0;  //寄存器选择 1:数据寄存器 0:指令寄存器
    sbit  LCDRW = P1^1;  //读写 选择  1:读 0:写
    sbit  LCDEN = P1^2;  //使能   1:可读写
    sbit LCDBF = P0^7;  //LCD忙标志 Busy Flag
    sfr  DBPORT = 0x80;  //数据端口0
    //常量定义
    #define LCD_DATA 1
    #define LCD_COMMAND 0
    #define LCD_READ 1
    #define LCD_WRITE 0
    void lcd_wait()
    //等待LCD空闲
    { LCDEN=0;      
    DBPORT=0xff;  //读LCD前若单片机输出低电平,而读出LCD为高电平,则冲突,Proteus仿真会有显示逻辑黄色
    LCDRS=LCD_COMMAND;   
    LCDRW=LCD_READ;
    LCDEN=1; _nop_();
    while(LCDBF)
    { LCDEN=0; _nop_();
      LCDEN=1; _nop_();
    }
    LCDEN=0;
    }  
    void lcd_command(unsigned char command)
    //用参数传递写类型,消耗ROM更多,调用也不方便,不如写两个函数
    //相同部分没有写成一个函数进行调用,因其本身占用ROM不多,而太多嵌套调用函数占用堆栈
    //写入指令
    { lcd_wait();
    LCDRS=LCD_COMMAND;
    LCDRW=LCD_WRITE;  
    DBPORT=command;  //注意写时序,先建立数据,再使能
    LCDEN=1; _nop_();   
    LCDEN=0;
    }
    void lcd_putchar(unsigned char character)
    //写入数据
    { lcd_wait();     
    LCDRS=LCD_DATA;
    LCDRW=LCD_WRITE;  
    DBPORT=character;  
    LCDEN=1; _nop_();   
    LCDEN=0;
    }
    /*  
    void lcd_creat(unsigned char *char_code,unsigned char nofc)
    //自定义字符
    { lcd_command(0x40);
    while(nofc)
    { lcd_putchar(*char_code);
      char_code++;
      nofc--;
    }
    } */   
    void lcd_moveto(unsigned char x, unsigned char y)
    //设定要读写的字符 行,列 坐标
    { if(x==0)
      lcd_command(0x80|y);
    if(x==1)
      lcd_command(0xc0|y);
    }
       
    void lcd_print(unsigned char *str)
    //显示字符串
    { while(*str!='\0')
    { lcd_putchar(*str);
      str++;
    }
    }
    void delayms(unsigned char ms)
    // 延时子程序
    {
    unsigned char i;
    while(ms--)
    {
      for(i = 0; i < 100; i++);
    }
    }
    void lcd_init()
    //LCD模块电源若不符合内部自动启动电路要求,需使用指令启动
    //仿真不需要,只要在程序中执行命令LCD_INIT,LCD_CLRS,并设置需要的显示模式,输入模式
    { unsigned char i;
    LCDEN=0;
    LCDRS=LCD_COMMAND;
    LCDRW=LCD_WRITE;
    DBPORT=0x30;
    for(i=0;i<3;i++)
    { LCDEN=1; _nop_();  //LCD模块热启动,不检查忙信号
      LCDEN=0;
      delayms(5);
    }
    lcd_command(0x38);    //8bit数据传送,2行显示,5*7字型,检测忙信号
    lcd_command(0x08);    //关闭显示,检测忙信号
    lcd_command(0x01);    //清屏,检测忙信号
    lcd_command(0x06);    //显示光标右移设置,检测忙信号
    lcd_command(0x0c);    //显示屏打开,光标不显示,不闪烁,检测忙信号
    }
    void main()
    {


    lcd_init();
    lcd_wait();
    while(1)
    {
    lcd_command(0x80);
    lcd_putchar('a');
      }
    }
  • budhy (2008-7-18 19:56:21)

    恭喜你,能写一下你的经历,让大家会得到新见试
  • 绝处逢生 (2008-7-18 20:43:38)

    我感觉对1602编程显示字符,在main函数中一定要有while(1)的无限循环语句,否则在lcd上所显示的字符是闪动的、不清晰的,也许在仿真的时候看不出来,但是我在硬件上操作的时候发现有闪动现象。楼主的程序没有无限循环语句。另外,就是对1602的初始化部分,我没打看明白楼主的“lcd_command(0x0f);    lcd_command(0x80+0x01); ”这两个语句,lcd_command(0x80+0x01)好像是确定字符显示的位置的,我不知道楼主放在初始化里面干什么,最好放在主函数里面,也好随时变化。
    搞1602显示已经好几天了,也遇到不少难点,其中汉字显示部分我还没攻下,另外,通过4*4键盘向1602输入一串英文字符也没完全实现。希望在1602的学习过程中能与楼主和budhy多交流。
  • djh2007 (2008-7-18 21:54:45)

    我自己也调好了,呵呵
    我也发上来给大家看下
    #include <reg51.h>
    #include <intrins.h>
    //端口定义
    sbit        LCDRS=P2^1;                //寄存器选择        1:数据寄存器 0:指令寄存器
    sbit         LCDRW=P2^0;                //读写 选择                1:读 0:写
    sbit         LCDEN=P2^2;                //使能                        1:可读写
    sbit        LCDBF=P1^7;                //LCD忙标志 Busy Flag
    sfr                DBPORT=0x90;                //数据端口1
    unsigned char code ch[]="djh";
    void delayms(unsigned char);
    void lcd_wait()
    //等待LCD空闲
    {
            while(1)
            {
          LCDEN=0;
          LCDRS=0;
          LCDRW=1;
          DBPORT=0xff;
          LCDEN=1;
          if(!LCDBF)break;
            }

            LCDEN=0;
    }  

    void lcd_command(unsigned char command)
    //用参数传递写类型,消耗ROM更多,调用也不方便,不如写两个函数
    //相同部分没有写成一个函数进行调用,因其本身占用ROM不多,而太多嵌套调用函数占用堆栈
    //写入指令
    {        lcd_wait();
            LCDRS=0;
            LCDRW=0;       
            DBPORT=command;        //注意写时序,先建立数据,再使能       
            LCDEN=1;                                               
            LCDEN=0;
    }

    void lcd_putchar(unsigned char character)
    //写入数据
    {       
            lcd_wait();                                 
            LCDRS=1;
            LCDRW=0;                       
            DBPORT=character;       
            LCDEN=1;                               
            LCDEN=0;
    }       

    void delayms(unsigned char ms)
    // 延时子程序
    {
            unsigned char x,y;
            for(x=ms;x>0;x--)
                    for(y=110;y>0;y--);

    }

    void lcd_init()
    //LCD模块电源若不符合内部自动启动电路要求,需使用指令启动
    //仿真不需要,只要在程序中执行命令LCD_INIT,LCD_CLRS,并设置需要的显示模式,输入模式
    {          unsigned char i;
            LCDEN=0;
            LCDRS=0;
            LCDRW=0;
            DBPORT=0x38;
            for(i=0;i<3;i++)
            {        LCDEN=1;        _nop_();                //LCD模块热启动,不检查忙信号
                    LCDEN=0;
                    delayms(10);
            }
        lcd_command(0x06);
            lcd_command(0x0f);       
        lcd_command(0x38); //设置显示两行
            lcd_command(0x01);
    }

    void main()
    {
            unsigned char num;
            lcd_init();
            lcd_command(0x80+0x01);
            lcd_putchar('a');
            lcd_command(0x80+0x40);
            for(num=0;num<3;num++)
            {
            lcd_putchar(ch[num]);
        delayms(5);
            }       
            while(1);
           
    }

    我改得半死 所有有可能的我都改 包够换了电路
    哎 不知道楼上的已经改好了,要不我就不用那么辛苦了
  • djh2007 (2008-7-18 21:56:48)

    还是感谢两位大哥啊,谢谢了 这lcd1602搞了我两天了
  • liaoguobao00 (2008-8-03 09:52:53)

    1602一般不能显示汉字,它的字符输入模式只有2种:5*7点阵和5*10,而以这2种点阵显示汉字是很模糊的,汉字取模软件对汉字取模最低也是16*16点阵,所以1602液晶只用在不需要显示汉字的场合,如果要显示汉字还得用宽屏液晶,如12864等