LCD1602

    技术2022-05-20  44

     

    今天我心情不错,一方面是昨天我的LCD1602调出来了,另外一方面是今天外加信号控制触发任意函数发生器AFG3102产生指定信号有了不错的方法。哈哈,高兴喔!

    LCD1602是我遇到的又一个难题,算算调试1602花了我四天的时间。昨天终于调成功了,对我这样的菜鸟来说,真的不容易呀。

    1602的调试过程介绍如下:

    11602的原理、接口设计

    这个网上一大把,就找个可信的方法,按照自己的要求设计好电路接口(具体的自己找找吧)。从中,我得到的一些启发是:1602的原理、单片机与1602的接口设计等资料,最好多参照几份。

    我的接口是按照下图来接的。

    2、万用板的焊制

    这个得多动手,多练,注意合理布局,焊完最好用万用表测试一下,焊线是否导通。对初学者来说,这也非常容易出错喔。有时候,就是焊线有问题就能让你郁闷两三天啊。

    3、驱动程序的编写与调试

    1602作为一个成熟的产品,其接口已经非常简单,但程序的编写与调试却最容易出问题。

    一开始,我把程序看了个大概,就开始烧写到单片机上。但调了将近两天也没结果。LCD只能显示LCD1602第一行全黑的效果(如图2)。

    我查资料发现,这个问题的原因是接线错误或1602初始化程序未运行。

    当时我很高兴,就重新焊了一块板子。结果新板子效果仍旧,因为当时我认为程序应该没问题,就一直没找到问题的解决方法(很郁闷)。

    正当我要放弃调1602时,伟大的转机出现啦。我找了个同学给看看,他结合时序图看过程序后说,程序是有点小问题呀。我们调了一个多小时,但问题仍未解决。这时,我感到一定要从细节上读懂程序才行。于是,我稍加了初始化程序的延时,就出来了一个让人兴奋的结果。哈哈哈哈哈……这次我的1602出现了两行全黑块(如图3)。

    因为我的16023VL是接地了。所以,我马上把3脚用10K电位器接地,从全黑调至刚刚变白即可。这时就1602就能正常显示了(我在程序里让LCD1602第一行显示89S52,第二行则是HELLO,图暂缺)。

    调试的几点小经验:

    1、连线,焊线一定要小心,细心。

    2、设计很重要,但调试也非常重要,而且非常费时间和精力。这时,我原来没有想到的。以前我就认为设计一定费更多时间很精力,其实不然,调试才最费时间和精力,因此调试很重要很重要。

    3、调试中,很容易头脑麻木,得注意劳逸结合,多和他人交流学习。

    4、硬件的时序图很重要,对驱动程序的编写很有帮助,我一开始就没注意它,结果找不到错误。所以以后,我一定硬下头皮来也要学会读时序图。

                                                            作者:飞燕

                                                                2011.2.11

    //先定义接口

    # include <AT89x51.h>

    /*****************************************

            P1------DB0DB7          P2.0------RS

                                 P2.1------RW

                                 P2.2------E

    *****************************************/

    # define LCD_DB       P1

           sbit        LCD_RS=P2^0;  //P2^0p2.0的意思;LCD_RSP2.0等效起来,对LCD_RS读写,就是对P2.0读写 好处在于LCD_RS含义直接明了,写程序多了就会知道有必要de

           sbit        LCD_RW=P2^1;  //P2^1p2.1的意思

           sbit        LCD_E=P2^2;   //P2^2p2.2的意思

    /******定义函数****************/

    # define uchar unsigned char

    # define uint unsigned int

    void LCD_init(void);//初始化函数

    void LCD_write_command(uchar command);//写指令函数

    void LCD_write_data(uchar dat);//写数据函数

    void LCD_disp_char(uchar x,uchar y,uchar dat);//在某个屏幕位置上显示一个字符,X0-16),y(1-2)

    //void LCD_check_busy(void);//检查忙函数。我没用到此函数,因为通过率极低。

    void delay_n40us(uint n);//延时函数

    //********************************

    //*******初始化函数***************

    void LCD_init(void)

    {

    delay_n40us(10);

    LCD_write_command(0x38);//设置8位格式,2行,5x7

    delay_n40us(10);

    LCD_write_command(0x0c);//整体显示,关光标,不闪烁

    delay_n40us(10);

    LCD_write_command(0x06);//设定输入方式,增量不移位

    delay_n40us(10);

    LCD_write_command(0x01);//清除屏幕显示

    delay_n40us(100);//实践证明,我的LCD1602上,用for循环200次就能可靠完成清屏指令。

    }

    //********************************

    //********写指令函数************

    void LCD_write_command(uchar dat)

    {

    delay_n40us(10);

    LCD_RS=0;//指令

    LCD_RW=0;//写入

    LCD_E=1;//允许

    LCD_DB=dat;

    delay_n40us(10);//实践证明,我的LCD1602上,用for循环1次就能完成普通写指令。

    LCD_E=0;

    delay_n40us(10);//实践证明,我的LCD1602上,用for循环1次就能完成普通写指令。

    }

    //*******************************

    //********写数据函数*************

    void LCD_write_data(uchar dat)

    {

    delay_n40us(10);

    LCD_RS=1;//数据

    LCD_RW=0;//写入

    LCD_E=1;//允许

    LCD_DB=dat;

    delay_n40us(10);

    LCD_E=0;

    delay_n40us(10);

    }

    //********************************

    //*******显示一个字符函数*********

    void LCD_disp_char(uchar x,uchar y,uchar dat)

    {

    uchar address;

    if(y==1)

            address=0x80+x;

    else

            address=0xc0+x;

    LCD_write_command(address);

    LCD_write_data(dat);

    }

    //********************************

    /*******检查忙函数*************

    void LCD_check_busy()     //实践证明,在我的LCD1602上,检查忙指令通过率极低,以

    {                                         //至于不能正常使用LCD。因此我没有再用检查忙函数。而使

    do                                      //用了延时的方法,延时还是非常好用的。我试了一下,用

           { LCD_E=0;                  //for循环作延时,普通指令只要1次循就可完成。清屏指令

             LCD_RS=0;                //要用200次循环便能完成。  

             LCD_RW=1;

             LCD_DB=0xff;

             LCD_E=1;

           }while(LCD_DB^7==1);

    ******************************/

    //********延时函数***************

    void delay_n40us(uint n)

    { uint i;

         uchar j;          

           for(i=n;i>0;i--)

              for(j=0;j<2;j++);         //在这个延时循环函数中我只做了2次循环,

    }                                        //实践证明我的LCD1602上普通的指令只需1次循环就能可靠完成。

    //*******************************

    //*********主函数*****************

    void main(void)

    {

           LCD_init();

           LCD_disp_char(0,1,0x38);//89S52

           LCD_disp_char(1,1,0x39);

           LCD_disp_char(2,1,0x53);

           LCD_disp_char(3,1,0x35);

           LCD_disp_char(4,1,0x32);

           LCD_disp_char(0,2,0x48);//HELLO

           LCD_disp_char(1,2,0x45);

           LCD_disp_char(2,2,0x4C);

           LCD_disp_char(3,2,0x4C);

           LCD_disp_char(4,2,0x4F);

           while(1);

    }

     

     


    最新回复(0)