1602lcd 的显示问题

eeworldcom   2009-8-26 22:38 楼主
程序时自己写的 ,但是液晶不显示字符,请高手指点
/************************************************************
* 公司名称:
* 创 建 人:匡 伟    创建日期:2009-8-25
* 修 改 人:         修改日期:
* 模 块 名:                  开发板型号:
* 芯片型号:STC89c52
* 函 数 名:
* 功能描述:液晶显示程序
* 其他说明:
* stc80c52的晶振频率为12MHz
************************************************************/
#include"stc89.h"
#include"mDelay.h"
#include"intrins.h"
#define uchar                unsigned char
#define DPORT       P0

sbit    RS = P3^7 ;      //P3_7
sbit    RW = P3^6 ;
sbit    E  = P3^5 ;      //p3_5     WR   P3_6

#define NODISP      0                 
#define NOCUR              1
#define CURNOFLASH        2
#define CURFLASH    3

#define CLEARSCREEN 0x01    //清屏控制字

uchar Xpos,Ypos;
//#define NOP         _nop_
/**************Lcd驱动部分函数声明**************************/
void SetCur(uchar c);
void ClearLcd(void);
void ReadStatus(void);
void LcdWriteData(uchar c);
void LcdWriteCommand(uchar c,uchar Busy);
//void LcdPos();
void LcdInit( );
void DispOneChar(uchar x, uchar y,uchar Data);
void DispListChar(uchar x, uchar y,uchar code *Data);

/**************光标(cur)设置命令***************************/
void SetCur( uchar cur )
{
        switch( cur )
        {
                case 0x00:
                {
                        LcdWriteCommand(0x08,1);   //LCD关显示
                        break;
                }
                case 0x01:
                {
                        LcdWriteCommand(0x0c,1);   //LCD开显示但是无光标
                        break;
                }
                case 0x02:
                {
                        LcdWriteCommand(0x0e,1);   //LCD显示有光标但光标不闪烁
                        break;
                }
                case 0x03:
                {
                        LcdWriteCommand(0x0f,1);   //LCD开显示光标闪烁
                        break;
                }
                default:break;
        }       
}
/************************************************************/

/**************清屏命令**************************************/
void ClearLcd()
{
        LcdWriteCommand(CLEARSCREEN,1);
}
/************************************************************/

/************正常读写前检测LCD控制器处于忙状态?*************/
void ReadStatus()
{
        uchar temp;       
        DPORT=0xff;
        RS=0;
        RW=1;
        /**/
        E=0;
        E=0;
        /**/                                   //读状态       
        E=1;
        _nop_();
        for(;;)
        {
                temp=DPORT;                  //读状态控制字
                temp&=0x80;              //if the station of control word--DPORT^7=0;enable;
                if(temp==0)
                break;       
        }
        E=0;
}
/************************************************************/

/**************不带忙检测的写字符(数据)子程序****************/
void  LcdWriteData(uchar c)
{               
        DPORT=c;
        RS=1;                         //写数据
        RW=0;                                                                                                                  
        E=0;                     //下降沿表示enable端有效
        _nop_();
        E=1;
        _nop_();
        E=0;
}
/************************************************************/


/**************不带忙检测的送控制字子程序********************/
void LcdWriteCommand(uchar c, uchar Busy)
{
        if(Busy)
        {
                ReadStatus();
        }
        DPORT=c;
        RS=0;                         //写数据
        RW=0;                                                                                                                          
        E=0;                     //下降沿表示enable端有效
        _nop_();
        E=1;
        _nop_();
        E=0;
}
/************************************************************/



/**************LcdPos************************************
void LcdPos()
{
        uchar temp;
        Xpos&=0x0f;
        Ypos&=0x01;
        temp=Xpos;
        if(Ypos==1)
        {
                temp+=0x40;
        }
        temp|=0x80;            //80h+地址码(2-27h 或者40-67h)
        LcdWriteCommand(temp,1);  //读写操作
}
************************************************************/


/*************Lcd复位程序************************************/
void LcdInit()
{
        mDelay(15);
        LcdWriteCommand(0x38,0);
        mDelay(5);
        LcdWriteCommand(0x38,0);
        mDelay(5);
        LcdWriteCommand(0x38,0);
        LcdWriteCommand(0x38,1);
        LcdWriteCommand(0x08,1);
        LcdWriteCommand(0x01,1);
        LcdWriteCommand(0x06,1);
        LcdWriteCommand(0x0c,1);
}
/************************************************************/

/**************LcdDispOneChar(在制定的行和列*******************/
void DispOneChar(uchar x, uchar y, uchar Data)
{
        x&=0x0f;
        y&=0x01;
        if(y==0x01)
        {
                x|=0x40;
        }
        x|=0x80;            //80h+地址码(2-27h 或者40-67h)
        LcdWriteCommand(x,0);  //忽略忙信号检测       读写操作
        LcdWriteData(Data);
}
/************************************************************/

/**************DispOneChar***********************************/
voidDispListChar(uchar x, uchar y,uchar code *Data)
{
        uchar ListLength=0;
        x&=0x0f;
        y&=0x01;
        while(x<16)
        {
                if(Data[ListLength]==0)
            {
                        break;
            }
                DispOneChar(x,y,Data[ListLength]);
                ListLength++;               
                x++;
        }
}
/************************************************************/

/**************main函数**************************************/
void main(void)
{

        uchar code s1[]={"hello world"};
       
//        uchar m;
        P2=0x00;
        P2=P2|0x60;
        mDelay(500);
        LcdInit();
        ClearLcd();
        SetCur(CURFLASH);
        while(1)
        {
                 DispListChar(1,0,s1);
        }




}
/************************************************************/

回复评论 (13)


这个楼主先要检查硬件有没有问题,然后再检查时序
点赞  2009-8-27 02:08
各位大侠如果用到液晶屏,我可以给大家提供一套比较好的方案,不用编写底层程序,并且稳定安全。可以      dwin99@live.cn
点赞  2009-8-29 19:36
1602的使用很成熟了
你先确定硬件连接是否正常,
检查时序是否过快。

你这程序太长了...弄个简单的先测试好了在写完整的。
点赞  2009-8-29 23:15
楼主把硬件图先发来看一下
点赞  2009-8-30 18:52
关键是你时序对不  不同的液晶驱动芯片时序不同
点赞  2009-8-30 20:29
这是我验证过的,可以参考下啊
#include
#include
#define nop _nop_()
typedef  unsigned char    uint8;
typedef  signed char      int8;
typedef  unsigned int     uint16;
typedef  signed int       int16;
typedef  unsigned long    uint32;
typedef  signed long      int32;
sbit a0 = ACC^0;
sbit a1 = ACC^1;
sbit a2 = ACC^2;
sbit a3 = ACC^3;
sbit a4 = ACC^4;
sbit a5 = ACC^5;
sbit a6 = ACC^6;
sbit a7 = ACC^7;


#define LCD1602_DATA P0 //8位数据并行口
#define LCD1602_RS P2_0 //指令OR数据寄存器选择
#define LCD1602_RW P2_1 //读写控制
#define LCD1602_EN P2_5 //使能控制
#define LCD1602_CLR 0x01    //清屏
#define LCD1602_MODE 0x38   //8位数据,双列显示,5*7字形
#define LCD1602_ON 0x0c //开显示,关光标,光标不闪烁
#define LCD1602_ADDR_MODE 0x06      //地址递增



uint8 code self_table1[]={
                        0x08,0x0f,0x12,0x0f,0x0a,0x1f,0x02,0x02,//  年
                        0x1f,0x11,0x1f,0x11,0x1f,0x11,0x15,0x17,//月
                        0x00,0x1f,0x11,0x1f,0x11,0x11,0x1f,0x00,//  日
                        0x01,0x0c,0x17,0x14,0x17,0x0c,0x01,0x00,//闹钟标志
                        0x10,0x18,0x1c,0x1e,0x1f,0x1c,0x18,0x10 };//三角形符号  
                        
                          


/**********************************************************
蜂鸣器
************************************************************/
void delay_ms(uint16 count)        // 延时时间count*1ms
{   uint16 i;
    for(;count>0;count--)
    {
        for(i=0;i<110;i++)
        {
            nop;
        }
    }
}

/***********************************************************
忙检测
************************************************************/
void LCD1602_check_busy(void)
{
    LCD1602_DATA = 0xff;
    LCD1602_RS = 0 ;   
    LCD1602_RW = 1 ;   
    LCD1602_EN = 1 ;   
    while(LCD1602_DATA & 0x80) ;   
    LCD1602_EN = 0 ;            
}

/**********************************************************
写指令
************************************************************/

void LCD1602_write_cmd(uint8 cmd)
{
    LCD1602_check_busy();   
    LCD1602_RS = 0 ;   
    LCD1602_RW = 0 ;   
    LCD1602_DATA = cmd ;   
    LCD1602_EN = 1 ;   
    LCD1602_EN = 0 ;
}

/***********************************************************
写数据
*************************************************************/
void LCD1602_write_data(uint8 dat)
{
    LCD1602_check_busy();   
    LCD1602_RS = 1 ;   
    LCD1602_RW = 0 ;   
    LCD1602_DATA = dat ;   
    LCD1602_EN = 1 ;   
    LCD1602_EN = 0 ;
}


/***********************************************************
1602初始化
************************************************************/
void LCD1602_init(void)
{
    uint8 i  ;
    LCD1602_write_cmd(0x40);//CGRAM起始地址
    for(i=0;i<40;i++)
        LCD1602_write_data(self_table1);//写入自定义字符
    LCD1602_write_cmd(LCD1602_MODE) ;
    LCD1602_write_cmd(LCD1602_ON) ;
    LCD1602_write_cmd(LCD1602_ADDR_MODE) ;
    LCD1602_write_cmd(LCD1602_CLR) ;
}

/************************************************************
设置显示坐标
************************************************************/
void LCD1602_set_postion(uint8 x , uint8 y)
{
    if(y<2)
        {
            y &= 0x01 ; //y值限定在0~1之间
            x &= 0x0f ; //x值限定在0~15之间
            if(y == 0)
                x |= 0x40 ; //如果显示是在第二行,则x的值加0x40
            x |= 0x80 ;     //获得x的值
            LCD1602_write_cmd(x) ;//写入坐标值到LCD
        }
}

/************************************************************
指定位置写字符
*************************************************************/
void LCD1602_write_char(uint8 x , uint8 y , uint8 chardata)
{
    LCD1602_set_postion(x,y) ;
    LCD1602_write_data(chardata) ;
}

/************************************************************
指定位置写字符串
*************************************************************/
void LCD1602_write_string(uint8 x , uint8 y , uint8 *string)
{
    LCD1602_set_postion(x,y) ;
    while((*string) != '\0')
    {   
        LCD1602_write_data(*string) ;
        string++ ;
    }
}

main()
{LCD1602_init();  //初始化
   LCD1602_write_string(0,0,"hello");   //在第一行第一列显示hello
   LCD1602_write_char(1,1,'f');//在第二行第二列显示f
   }
点赞  2009-9-2 23:16
我用的的是一个开发板,电路该没有问题的,而且我自己也看了很多电路,举得硬件问题不是很大,1602液晶的型号是ym1602,时序是按照手册上写的,但是不知道是不是不同型号的1602有不同的时序??
点赞  2009-9-6 10:52
还有我的程序时参照1602的手册写的,不知道哪里出毛病了
点赞  2009-9-6 10:55
自己参照时序图写的难免有错的,你先拿我那段程序试试看,把相应的口线定义改了就行
点赞  2009-9-6 11:00
我还有汇编的程序,也能运行,你要不呀
点赞  2009-9-6 11:01
谢谢大家,我现在已经调试好了,谢谢大家的帮助和支持
点赞  2009-11-14 23:13
你怎么调试好的,拿出来大家分享一下啊
点赞  2010-1-21 11:08
#include
#include
#define uchar unsigned char
#define DPORT P0  

sbit RS = P3^7 ; //P3_7
sbit RW = P3^6 ;
sbit E = P3^5 ; //p3_5 WR P3_6

#define NODISP 0   
#define NOCUR 1
#define CURNOFLASH 2
#define CURFLASH 3

#define CLEARSCREEN 0x01 //清屏控制字

uchar Xpos,Ypos;i;j;
//#define NOP _nop_
/**************Lcd驱动部分函数声明**************************/
void SetCur(uchar c);
void ClearLcd(void);
void ReadStatus(void);
void LcdWriteData(uchar c);
void LcdWriteCommand(uchar c,uchar Busy);
//void LcdPos();
void LcdInit( );
void DispOneChar(uchar x, uchar y,uchar Data);
void DispListChar(uchar x, uchar y,uchar code *Data);

/**************光标(cur)设置命令***************************/
void delay(uchar z)
{
   for (i=0;i            for(j=110;j>0;j--);
}
void SetCur( uchar cur )
{
switch( cur )
{
case 0x00:
{
LcdWriteCommand(0x08,1); //LCD关显示
break;
}
case 0x01:
{
LcdWriteCommand(0x0c,1); //LCD开显示但是无光标
break;
}
case 0x02:
{
LcdWriteCommand(0x0e,1); //LCD显示有光标但光标不闪烁
break;
}
case 0x03:
{
LcdWriteCommand(0x0f,1); //LCD开显示光标闪烁
break;
}
default:break;
}
}
/************************************************************/

/**************清屏命令**************************************/
void ClearLcd()
{
LcdWriteCommand(CLEARSCREEN,1);
}
/************************************************************/

/************正常读写前检测LCD控制器处于忙状态?*************/
void ReadStatus()
{
uchar temp;
DPORT=0xff;
RS=0;
RW=1;
/**/
E=0;
E=0;
/**/ //读状态
E=1;
_nop_();
for(;;)
{
temp=DPORT; //读状态控制字
temp&=0x80; //if the station of control word--DPORT^7=0;enable;
if(temp==0)
break;
}
E=0;
}
/************************************************************/

/**************不带忙检测的写字符(数据)子程序****************/
void LcdWriteData(uchar c)
{
DPORT=c;
RS=1; //写数据
RW=0;   
E=0; //下降沿表示enable端有效
_nop_();
E=1;
_nop_();
E=0;
}
/************************************************************/


/**************不带忙检测的送控制字子程序********************/
void LcdWriteCommand(uchar c, uchar Busy)
{
if(Busy)
{
ReadStatus();
}
DPORT=c;
RS=0; //写数据
RW=0;   
E=0; //下降沿表示enable端有效
_nop_();
E=1;
_nop_();
E=0;
}
/************************************************************/



/**************LcdPos************************************
void LcdPos()
{
uchar temp;
Xpos&=0x0f;
Ypos&=0x01;
temp=Xpos;
if(Ypos==1)
{
temp+=0x40;
}
temp|=0x80; //80h+地址码(2-27h 或者40-67h)
LcdWriteCommand(temp,1); //读写操作
}
************************************************************/


/*************Lcd复位程序************************************/
void LcdInit()
{
delay(15);
LcdWriteCommand(0x38,0);
delay(5);
LcdWriteCommand(0x38,0);
delay(5);
LcdWriteCommand(0x38,0);
LcdWriteCommand(0x38,1);
LcdWriteCommand(0x08,1);
LcdWriteCommand(0x01,1);
LcdWriteCommand(0x06,1);
LcdWriteCommand(0x0c,1);
}
/************************************************************/

/**************LcdDispOneChar(在制定的行和列*******************/
void DispOneChar(uchar x, uchar y, uchar Data)
{
x&=0x0f;
y&=0x01;
if(y==0x01)
{
x|=0x40;
}
x|=0x80; //80h+地址码(2-27h 或者40-67h)
LcdWriteCommand(x,0); //忽略忙信号检测 读写操作
LcdWriteData(Data);
}
/************************************************************/

/**************DispOneChar***********************************/
voidDispListChar(uchar x, uchar y,uchar code *Data)
{
uchar ListLength=0;
x&=0x0f;
y&=0x01;
while(x<16)
{
if(Data[ListLength]==0)
{
break;
}
DispOneChar(x,y,Data[ListLength]);
ListLength++;
x++;
}
}
/************************************************************/

/**************main函数**************************************/
void main(void)
{

uchar code s1[]={"hello world"};

// uchar m;
P2=0x00;
P2=P2|0x60;
delay(500);
LcdInit();
ClearLcd();
SetCur(CURFLASH);
while(1)
{
DispListChar(1,0,s1);
}




}
点赞  2010-4-22 14:41
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复