bv001 发表于 2010-11-3 10:39:42

请问一下液晶EL1602第2行不能显示的问题

主要想看一下第二行的地址是多少

现在试了0xc0,0x40,0x90等都没有第2行显示

bv001 发表于 2010-11-3 16:47:24

现在只显示1行

而且通电后第2行没有背景黑框

bv001 发表于 2010-11-4 08:37:38

up

easywater 发表于 2010-11-4 14:05:16

你是不是没有设置成两行的工作模式?

8bit 总线要写指令 0x38, 4bit 总线要写指令 0x2, 0x8

bv001 发表于 2010-11-4 17:00:25

thanks

bv001 发表于 2010-11-4 18:17:08

第2行好像还是没有显示

相关初始化如下:

void LCD_Init(void)
{

   LCD_WriteCmd(0x01);    // LCD清屏
   LCD_WriteCmd(0x06);    //数据读、写操作后,光标右移动,AC自动增一
   LCD_WriteCmd(0x0C);    //开显示;关光标;关闪烁
   LCD_WriteCmd(0x38);    //8位数据接口;两行显示;5x8点阵字符
}

bv001 发表于 2010-11-4 18:42:26

还是只显示一行16个字符"12345abcde12345a"

完整的程序如下

//******** EL1602 test *********

#include <iom16v.h>
#include <macros.h>

//LCD数据端口PC0-PC7
#define LCD_DATA_PORTPORTC
#define LCD_DATA_DDR   DDRC
#define LCD_DATA_PIN   PINC

//LCD控制端口PA5,PA7
#define LCD_CONTROL_PORT    PORTA
#define LCD_CONTROL_DDR   DDRA
#define        RS       5
#define        E       7

#define LINEWIDTH 16//行宽   
#define LINES 2       //行数

//--------------------------------------------------------------------------------------------------
//Public function prototypes
//--------------------------------------------------------------------------------------------------
void Delay_1us(void);
void Delay_1ms(void);
void Delay_nus(unsigned int n);
void Delay_nms(unsigned int n);

#define        SETBIT(x,y) (x|=(1<<y))      //set bit y in byte x
#define        CLRBIT(x,y) (x&=(~(1<<y)))   //clear bit y in byte x
#define        CHKBIT(x,y) (x&(1<<y))       //check bit y in byte x

#define uchar unsigned char // 0~255
#define uint unsigned int   // 0~65535

void LCD_Init(void);   //LCD初始化
void LCD_Clear(void);    //LCD清屏
void LCD_CheckState(void);   //--保留
void LCD_WriteCmd(unsigned char scmd);    //写一个命令到LCD
void LCD_WriteData(unsigned char DData);//写一个数据到LCD
void LCD_Set_xy(unsigned char Y, unsigned char X); //设置光标位置
void LCD_WriteChar(unsigned char X,unsigned char Y,unsigned char c1);   //写一个字符到LCD
void LCD_WriteStr(unsigned char Y,unsigned char X,unsigned char *pstr); //写字符串到LCD显示
void LCD_WriteStrAuto(unsigned char *pstr);   //从显示屏的初始位置写入数据,自动换行


void LCD_Init(void)
{
   Delay_nms(100);
       
   LCD_WriteCmd(0x01);    // LCD清屏
   LCD_WriteCmd(0x06);    //数据读、写操作后,鼠标右移动,AC自动增一
   LCD_WriteCmd(0x0C);    //开显示;关光标;关闪烁
   LCD_WriteCmd(0x38);    //8位数据接口;两行显示;5x8点阵字符
}


//LCD清屏
voidLCD_Clear(void)
{
   LCD_WriteCmd(0x01);
   Delay_nms(1);      
}


void LCD_WriteCmd(unsigned char scmd)   //send command
{
        CLRBIT(LCD_CONTROL_PORT,E);
        CLRBIT(LCD_CONTROL_PORT,RS);

        LCD_DATA_DDR=0xFF;
        LCD_DATA_PORT=scmd;
               
        NOP();
        SETBIT(LCD_CONTROL_PORT,E);
        NOP();
        CLRBIT(LCD_CONTROL_PORT,E);

        Delay_nus(20);       
}

void LCD_WriteData(unsigned char DData)
{
        CLRBIT(LCD_CONTROL_PORT,E);
        SETBIT(LCD_CONTROL_PORT,RS);
       
        LCD_DATA_DDR=0xFF;
        LCD_DATA_PORT=DData;
       
        NOP();
        SETBIT(LCD_CONTROL_PORT,E);
        NOP();
        CLRBIT(LCD_CONTROL_PORT,E);

        Delay_nus(20);       
}

//设置光标位置,先Y坐标后X坐标
void LCD_Set_xy(unsigned char Y, unsigned char X)
{
    unsigned char i=0x00;
    switch(Y & 0x0f)   //确定行号
    {
        case 0x00:
                i=0x80;//0x80
                break;
        case 0x01:
                i=0xC0; //0x90;
                break;

        default :
                break;
    }
    i = (X & 0x0f)|i; //确定列号
   LCD_WriteCmd(i);
       
}

//从显示屏指定的行(Y),列(X)的位置写入字符
void LCD_WriteChar(unsigned char X,unsigned char Y,unsigned char c1)
{
   LCD_WriteCmd(0x38);      // 8bit I/F, basic command, graphic off
   
   LCD_Set_xy(X,Y);   
   LCD_WriteData(c1);
   
   Delay_nms(1); //2006.11.19
}

//从显示屏指定的行(Y),列(X)的位置写入字符串
void LCD_WriteStr(unsigned char X,unsigned char Y,unsigned char *pstr1)   //英文LCD
{
   unsigned char j;
   unsigned char *pstr = pstr1;

   LCD_WriteCmd(0x38);      // 8bit I/F, basic command, graphic off

   LCD_Set_xy(Y,X);
       
   j=Y * LINEWIDTH + X;
   while (*pstr && j< (LINEWIDTH * LINES))
   {
      if (j%LINEWIDTH==0)         //判断是否换行
      {
         LCD_Set_xy(j/LINEWIDTH,0);   //如换行, 则光标移动到行首
               Delay_nms(1);
      }
               
      LCD_WriteData(*pstr++);
      j++;
          Delay_nms(1);

   }
       
   Delay_nms(1); //2006.11.19
}

//从显示屏的初始位置写入字符串,自动换行
void LCD_WriteStrAuto(unsigned char *pstr1)//英文LCD
{
   unsigned char i;
   unsigned char j;
   unsigned char *pstr = pstr1;

   LCD_WriteCmd(0x38);      // 8bit I/F, basic command, graphic off
   
   LCD_Clear();
   LCD_Set_xy(0,0);
   Delay_nms(1);
               
   j=0;
   while (*pstr && j<LINEWIDTH*LINES)
   {
      if (j%LINEWIDTH==0)         //判断是否换行
      {
         LCD_Set_xy(j/LINEWIDTH,0);   //如换行, 则光标移动到行首
               Delay_nms(1);
      }          

      LCD_WriteData(*pstr++);
      j++;
          Delay_nms(1);
   }
       
   Delay_nms(1);
}



void main(void)
{
   CLI();               // disable interrupts

   Delay_nms(1000);

   //LCD端口初始化
   LCD_DATA_DDR=0xFF;
   LCD_CONTROL_DDR|=(1<<RS|1<<E); //置位RS,E等
   CLRBIT(LCD_CONTROL_PORT,E);
   CLRBIT(LCD_CONTROL_PORT,RS);
   LCD_DATA_PORT|=0xFF;

   //LCD功能初始化
   LCD_Init();       
   Delay_nms(10);
       
   while(1)
   {
       
      LCD_WriteStrAuto("12345abcde12345abcde");
      Delay_nms(2000);
       
   }
       
}

/*-----------------------------------------------------------------------
延时函数
系统时钟:8M
-----------------------------------------------------------------------*/
void Delay_1us(void)               //1us延时函数
{
   asm("nop");
}

void Delay_nus(unsigned int n)       //N us延时函数
{
   unsigned int i=0;
   for (i=0;i<n;i++)
   Delay_1us();
}

void Delay_1ms(void)               //1ms延时函数
{
   unsigned int i;
   for (i=0;i<1140;i++);
}

void Delay_nms(unsigned int n)       //N ms延时函数
{
   unsigned int i=0;
   for (i=0;i<n;i++)
   Delay_1ms();
}

easywater 发表于 2010-11-4 21:15:32

C51 我也只是初学,也没有 AVR 的编译环境。所以你 AVR C 的程序我也没法帮你试,但是有几点建议:

1,初始化的指令序列,和控制 IC 手册上要求的不一样,如果你是 8bit 接法,要按时序写 3 次 0x38。然后才开始设置。当然,我也有不完全按照手册要求进行初始化成功的。应该是 LCM 内部初始化 OK,不需要外部指令做初始化了。

2,建议你先用一套简单的指令来试验。直接用一个循环写两行的内容。下面是我程序里的做法。避免因为其他逻辑出错,导致误认为 LCM 工作不正常。这样可以快速地缩小问题的范围。下面的循环在我的系统上,是可以正常显示一行大写 "ABCD...." ,第二行小写"abcd..."的。当然,其他的程序段我省略了。

        for (i; i < 16; i++) {
                        w_CMD_LCM1602(0x80 + i);        //定位第一行左一位置,并逐个向右
                        delay_ms_0(1);
                        w_DAT_LCM1602(0x41 + i);        //从 'A' 开始写大写字符
                        delay_ms_0(1);
                        w_CMD_LCM1602(0xC0 + i);        //定位第二行左一位置,并逐个向右
                        delay_ms_0(1);
                        w_DAT_LCM1602(0x61 + i);        //从 'a' 开始写小写字符
                        delay_ms_0(1);
        }

3,建议你对你设置光标位置的 LCD_Set_xy(Y,X) 当中 LCD_WriteCmd(i);这行下个中断,看看写进去的命令值是多少,第一行应该是从 0x80 开始。第二行应该是从 0xC0 开始。

(修改错字)

easywater 发表于 2010-11-4 21:19:41

还有可以看一下论坛里其他的帖子,1602 讨论还挺多的。8bit 的例子也很多。我之前也有发一个帖子,其中有关于初始化的文档。你可以参考一下。

http://ourdev.cn/bbs/bbs_content.jsp?bbs_sn=4344053&bbs_page_no=3&bbs_id=1006

bv001 发表于 2010-11-4 22:22:48

谢谢,明天连写3次初始化,并直接写第2行试试; 以前用其他液晶好像很容易调通的

bv001 发表于 2010-11-5 08:53:30

已解决,感谢【3楼】 easywater 的提示

LCD_WriteChar,LCD_WriteStr,LCD_WriteStrAuto 中也修改成0x38就ok了

zlj2008 发表于 2013-4-8 15:32:51

我也遇到这个问题了.
页: [1]
查看完整版本: 请问一下液晶EL1602第2行不能显示的问题