找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 13146|回复: 4
收起左侧

Proteus仿真中的lcd1602为什么只亮不显示?

[复制链接]
ID:515099 发表于 2019-4-17 23:57 | 显示全部楼层 |阅读模式
0.png
sbit LCD_RS = P2^5;    //片选信号输入
sbit LCD_RW = P2^6;   //串行数据输入
sbit LCD_E = P2^7;  //串行时钟输入
sbit D0=P0^0;

void delay_nms(uint t)
{
    uint i;
    uchar j;
    for(i=0;i<t;i++)
      for(j=0;j<110;j++);
}
/*********************************************************
*函数功能:向lcd12864串行输入一个字节
**********************************************************/
void send_byte(uchar Dbyte)
{
    uchar i;
    for(i=0;i<8;i++)
    {
      LCD_E = 0;
      Dbyte = Dbyte<<1;
      LCD_RW = CY;
      LCD_E = 1;
      _nop_();
      LCD_E = 0;
    }   
}
/*********************************************************
*函数功能:接收lcd12864输出的一个有效字节
**********************************************************/
uchar recive_byte()
{
    uchar temp1,temp2,i;
    bit flag;
    temp1 = 0;
    temp2 = 0;
    for(i=0;i<8;i++)//接收有效字节的高四位
    {
        temp1 = temp1<<1;
        LCD_E = 0;
         LCD_E = 1;
        _nop_();
        LCD_E = 0;
        flag = LCD_RW;
        if(flag==1)
          temp1 = temp1&0x01;  
    }
    for(i=0;i<8;i++)//接收有效字节的低四位
    {
        temp2 = temp2<<1;
        LCD_E = 0;
         LCD_E= 1;
        _nop_();
        LCD_E = 0;
        flag = LCD_RW;
        if(flag==1)
          temp2 = temp2&0x01;  
    }   
    return ((temp1&0xf0)|(temp2&0x0f));//返回接收到的有效字节
}
/*********************************************************
*函数功能:检测忙标志位
**********************************************************/
void lcd12864_checkbusy()
{
    do
    {
        send_byte(0xfc);//1111 1【1 RW】【0 RS】0
    }while(recive_byte()&0x80==0x80);  //BF(.7)=1 Busy
}

/*********************************************************
*函数功能:向12864写命令函数
**********************************************************/
void lcd12864_write_com(uchar com)
{
    LCD_RS = 1;
    lcd12864_checkbusy();//检测忙信号
     send_byte(0xf8);//1111 1[0 rw][0 rs]0   写命令起始指令
    send_byte(com&0xf0);   
    send_byte((com<<4)&0xf0);
    LCD_RS = 0;
}
/*********************************************************
*函数功能:向12864写数据函数
**********************************************************/
void lcd12864_write_dat(uchar dat)
{
    LCD_RS = 1;
    lcd12864_checkbusy();//检测忙信号
    send_byte(0xfa);//1111 1[0 rw][1 rs]0  写数据起始指令
    send_byte(dat&0xf0);
    send_byte((dat<<4)&0xf0);
    LCD_RS = 0;
}
/*********************************************************
*函数功能:设置光标位置
**********************************************************/
void lcd12864_set_cursor(uchar x,uchar y)
{
    uchar addr;
    switch(x)//确定行
    {
        case 0x00:addr = 0x80;break;//第一行
        case 0x01:addr = 0x90;break;//第二行
        case 0x02:addr = 0x88;break;//第三行
        case 0x03:addr = 0x98;break;//第四行
        default:break;
    }
    addr += y;                      //确定列
    lcd12864_write_com(addr);       //设置光标
}
/*********************************************************
*函数功能:lcd12864清显示(显示汉字、字符模式下的清屏)
**********************************************************/
void lcd12864_clear0(void)
{
    lcd12864_write_com(0x01);
    delay_nms(10);
}
/*********************************************************
*函数功能:lcd12864清显示(绘图模式下的清屏)
**********************************************************/
void lcd12864_clear1(void)
{
    uchar i, j, k ;
    lcd12864_write_com(0x34);//功能设置:扩充指令集动作
    lcd12864_write_com(0x36);//开绘图显示
    for( i = 0 ; i < 2 ; i++ )//分上下两屏写
    {
        for( j = 0 ; j < 32 ; j++ )
        {
          lcd12864_write_com( 0x80 + j ) ;//写Y坐标(行坐标)
            if( i == 0 )                  //写X坐标(列坐标)
               lcd12864_write_com( 0x80 ) ;
            else
               lcd12864_write_com( 0x88 ) ;
            for( k = 0 ; k < 16 ; k++ )      //写一整行数据
                lcd12864_write_dat(0x00) ;
        }
    }
    lcd12864_write_com( 0x30 ) ;//功能设置:恢复为基本指令集
                                //          关绘图显示
}
/*********************************************************
*函数功能:初始化函数
**********************************************************/
void lcd12864_init()
{
  delay_nms(50);
  //功能设定
  lcd12864_write_com(0x30);   //设置为8位并行口,基本指令集
  delay_nms(1);
  lcd12864_write_com(0x30);   //再次设置为8位并行口,基本指令集
  delay_nms(1);
  lcd12864_write_com(0x0c);   //显示状态设置:整体显示ON 游标OFF
  delay_nms(10);
  lcd12864_write_com(0x01);   //清除显示,并且设定地址指针为00H
  delay_nms(10);
  lcd12864_write_com(0x06);   //设置为游标右移,DDRAM位地址加1,画面不移动
}

/*********************************************************
*函数功能:在指定位置 显示一个字符
**********************************************************/
void lcd12864_write_char(uchar x,uchar y,uchar chr)
{
  lcd12864_set_cursor(x,y);
  lcd12864_write_dat(chr);
}
/*********************************************************
*函数功能:在指定位置 显示一个字符
**********************************************************/
void lcd12864_write_str(uchar x,uchar y,uchar *string)
{
    uchar *str;
    uchar i=x;
    uchar j=y;
    str = string;
    lcd12864_set_cursor(x,y);
    while(*str!='\0')
    {
      lcd12864_write_dat(*str);
      j++;
      if(j>0x0f)
      {
        i++;
        j=0;
        if(i>4)
          i=0;
        lcd12864_set_cursor(i,j);
      }   
      str++;
    }   
}


//********************************************************
//画满屏图片
//参数:dat为填充的数据
//********************************************************
void draw_full_picture (uchar *dat)
{
    uchar i;                 
    uchar j;
    uchar k;
    uchar bGDRAMAddrX = 0x80;        //GDRAM水平地址
    uchar bGDRAMAddrY = 0x80;        //GDRAM垂直地址
    for(i = 0; i < 2; i++)                                                                                                            
    {
        for(j = 0; j < 32; j++)                                                                 
        {
            for(k = 0; k < 8; k++)                                                         
            {
                lcd12864_write_com(0x34);                //设置为8位MPU接口,扩充指令集
                lcd12864_write_com(bGDRAMAddrY+j);        //垂直地址Y                                                                        
                lcd12864_write_com(bGDRAMAddrX+k);        //水平地址X
                lcd12864_write_dat(*dat++);
                lcd12864_write_dat(*dat++);
            }
        }
        bGDRAMAddrX = 0x88;                    //写下半屏幕
    }
    lcd12864_write_com(0x36);                            //打开绘图模式
    lcd12864_write_com(0x30);                            //恢复基本指令集,关闭绘图模式   
}



回复

使用道具 举报

ID:35873 发表于 2019-4-18 00:24 | 显示全部楼层
给你个显示自己看吧
1602.PNG

ds18b20和1602显示.rar

66.31 KB, 下载次数: 254

回复

使用道具 举报

ID:96682 发表于 2019-4-18 00:38 | 显示全部楼层
这文不对题的无解
回复

使用道具 举报

ID:213173 发表于 2019-4-18 05:25 | 显示全部楼层
你的程序用的是12864,仿真用的是1602,让它怎么显示?
回复

使用道具 举报

ID:515099 发表于 2019-4-18 11:29 | 显示全部楼层
wulin 发表于 2019-4-18 05:25
你的程序用的是12864,仿真用的是1602,让它怎么显示?

那换啦LCD12864,要怎么改才能显示数据?

sbit LCD_CS = P0^0;    //片选信号输入
sbit LCD_STD = P0^1;   //串行数据输入
sbit LCD_SCLK = P0^2;  //串行时钟输入

void delay_nms(uint t)
{
    uint i;
    uchar j;
    for(i=0;i<t;i++)
      for(j=0;j<110;j++);
}

/*函数功能:向lcd12864串行输入一个字节*/
void send_byte(uchar Dbyte)
{
    uchar i;
    for(i=0;i<8;i++)
    {
      LCD_SCLK = 0;
      Dbyte = Dbyte<<1;
      LCD_STD = CY;
      LCD_SCLK = 1;
      _nop_();
      LCD_SCLK = 0;
    }   
}
/*函数功能:接收lcd12864输出的一个有效字节*/
uchar recive_byte()
{
    uchar temp1,temp2,i;
    bit flag;
    temp1 = 0;
    temp2 = 0;
    for(i=0;i<8;i++)//接收有效字节的高四位
    {
        temp1 = temp1<<1;
        LCD_SCLK = 0;
         LCD_SCLK = 1;
        _nop_();
        LCD_SCLK = 0;
        flag = LCD_STD;
        if(flag==1)
          temp1 = temp1&0x01;  
    }
    for(i=0;i<8;i++)//接收有效字节的低四位
    {
        temp2 = temp2<<1;
        LCD_SCLK = 0;
         LCD_SCLK = 1;
        _nop_();
        LCD_SCLK = 0;
        flag = LCD_STD;
        if(flag==1)
          temp2 = temp2&0x01;  
    }   
    return ((temp1&0xf0)|(temp2&0x0f));//返回接收到的有效字节
}
/*函数功能:检测忙标志位*/
void lcd12864_checkbusy()
{
    do
    {
        send_byte(0xfc);//1111 1【1 RW】【0 RS】0
    }while(recive_byte()&0x80==0x80);  //BF(.7)=1 Busy
}

/*函数功能:向12864写命令函数*/
void lcd12864_write_com(uchar com)
{
    LCD_CS = 1;
    lcd12864_checkbusy();//检测忙信号
     send_byte(0xf8);//1111 1[0 rw][0 rs]0   写命令起始指令
    send_byte(com&0xf0);   
    send_byte((com<<4)&0xf0);
    LCD_CS = 0;
}
/*函数功能:向12864写数据函数*/
void lcd12864_write_dat(uchar dat)
{
    LCD_CS = 1;
    lcd12864_checkbusy();//检测忙信号
    send_byte(0xfa);//1111 1[0 rw][1 rs]0  写数据起始指令
    send_byte(dat&0xf0);
    send_byte((dat<<4)&0xf0);
    LCD_CS = 0;
}

void lcd12864_set_cursor(uchar x,uchar y)
{
    uchar addr;
    switch(x)//确定行
    {
        case 0x00:addr = 0x80;break;//第一行
        case 0x01:addr = 0x90;break;//第二行
        case 0x02:addr = 0x88;break;//第三行
        case 0x03:addr = 0x98;break;//第四行
        default:break;
    }
    addr += y;                      //确定列
    lcd12864_write_com(addr);       //设置光标
}
/*函数功能:lcd12864清显示(显示汉字、字符模式下的清屏)*/
void lcd12864_clear0(void)
{
    lcd12864_write_com(0x01);
    delay_nms(10);
}
/*函数功能:lcd12864清显示(绘图模式下的清屏)*/
void lcd12864_clear1(void)
{
    uchar i, j, k ;
    lcd12864_write_com(0x34);//功能设置:扩充指令集动作
    lcd12864_write_com(0x36);//开绘图显示
    for( i = 0 ; i < 2 ; i++ )//分上下两屏写
    {
        for( j = 0 ; j < 32 ; j++ )
        {
          lcd12864_write_com( 0x80 + j ) ;//写Y坐标(行坐标)
            if( i == 0 )                  //写X坐标(列坐标)
               lcd12864_write_com( 0x80 ) ;
            else
               lcd12864_write_com( 0x88 ) ;
            for( k = 0 ; k < 16 ; k++ )      //写一整行数据
                lcd12864_write_dat(0x00) ;
        }
    }
    lcd12864_write_com( 0x30 ) ;//功能设置:恢复为基本指令集
                                //          关绘图显示
}
/*函数功能:初始化函数*/
void lcd12864_init()
{
  delay_nms(50);
  //功能设定
  lcd12864_write_com(0x30);   //设置为8位并行口,基本指令集
  delay_nms(1);
  lcd12864_write_com(0x30);   //再次设置为8位并行口,基本指令集
  delay_nms(1);
  lcd12864_write_com(0x0c);   //显示状态设置:整体显示ON 游标OFF
  delay_nms(10);
  lcd12864_write_com(0x01);   //清除显示,并且设定地址指针为00H
  delay_nms(10);
  lcd12864_write_com(0x06);   //设置为游标右移,DDRAM位地址加1,画面不移动
}

/*函数功能:在指定位置 显示一个字符*/
void lcd12864_write_char(uchar x,uchar y,uchar chr)
{
  lcd12864_set_cursor(x,y);
  lcd12864_write_dat(chr);
}
/*函数功能:在指定位置 显示一个字符*/
void lcd12864_write_str(uchar x,uchar y,uchar *string)
{
    uchar *str;
    uchar i=x;
    uchar j=y;
    str = string;
    lcd12864_set_cursor(x,y);
    while(*str!='\0')
    {
      lcd12864_write_dat(*str);
      j++;
      if(j>0x0f)
      {
        i++;
        j=0;
        if(i>4)
          i=0;
        lcd12864_set_cursor(i,j);
      }   
      str++;
    }   
}


//画满屏图片
//参数:dat为填充的数据
void draw_full_picture (uchar *dat)
{
    uchar i;                 
    uchar j;
    uchar k;
    uchar bGDRAMAddrX = 0x80;        //GDRAM水平地址
    uchar bGDRAMAddrY = 0x80;        //GDRAM垂直地址
    for(i = 0; i < 2; i++)                                                                                                            
    {
        for(j = 0; j < 32; j++)                                                                 
        {
            for(k = 0; k < 8; k++)                                                         
            {
                lcd12864_write_com(0x34);                //设置为8位MPU接口,扩充指令集
                lcd12864_write_com(bGDRAMAddrY+j);        //垂直地址Y                                                                        
                lcd12864_write_com(bGDRAMAddrX+k);        //水平地址X
                lcd12864_write_dat(*dat++);
                lcd12864_write_dat(*dat++);
            }
        }
        bGDRAMAddrX = 0x88;                    //写下半屏幕
    }
    lcd12864_write_com(0x36);                            //打开绘图模式
    lcd12864_write_com(0x30);                            //恢复基本指令集,关闭绘图模式   
}


回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表