51單片機LCD1602程序詳解

LCD1602
工業字符型液晶。1602是指LCD顯示的內容爲16X2,即可以顯示兩行,每行16個字符.

特殊接口說明
RS:寄存器選擇輸入端
RS=1:指向數據寄存器
RS=0:指向指令寄存器

RW:讀寫控制輸入端
RW=0:寫操作 RW=1:讀操作

E:使能信號輸入端
讀操作時,高電平有效;
寫操作時,下降沿有效;

程序編寫:

    #include<reg51.h>
    #include<intrins.h>  //其中有nop函數的定義

    /*對於延時很短的,要求在us級的,採用“_nop_”函數,這個函數相當彙編NOP指令,延時幾微秒。NOP指令爲單週期指令,可由晶振頻率算出延時時間,對於12M晶振,延時1uS。*/

    #define uchar unsigned char
    #define uint unsigned int

    sbit RS=P2^6;  //定義數據命令選擇端
    sbit RW=P2^5;  //定義讀寫選擇端
    sbit E=P2^7;   //定義使能端
    //注意:具體爲哪一個IO口由你自己的接線來定,並不是一定要這樣寫!

    uchar text1[]="Welcome to";   //第一行要顯示的字符
    uchar text2[]="Lime House";   //第二行要顯示的字符

    void delay_ms(uint z)  //毫秒級延時函數
    {
       uint i,j;
       for(i=z;i>0;i--)
          for(j=110;j>0;j--);
    }

    //爲什麼要判忙?
    /*因爲LCD1602控制芯片也是一個CPU,它在處理上位機發來的某些指令的時候,耗時較長。如復位命令,全屏清除命令等。另外,LCD1602的CPU速度較慢,上位機較快時,LCD1602CPU來不及完成上條命令,會對後續命令不予理睬,這樣就造成了命令序列不能正確完整地到達LCD1602CPU,以至於顯示不正常。*/

    uchar Lcd1602_ReadBusy()   //判斷lcd1602是否處於忙的狀態,即讀忙
    {
       uchar temp;
       RS=0;
       RW=1;
       _nop_();
       P0=0xff;     //讀某IO口數據前,先將該口置爲1            

    /*原因:電路中存在的一個普遍的現象:高電平很容易被低電平拉低,而低電平一般不可能被高電平拉高。所以在讀數據之前將單片機IO口拉高纔不會影響原來數據線上的數據!*/

       _nop_();
       E=1;
       _nop_();
       temp=P0;   //讀取此時lcd1602的狀態字
       _nop_();
       E=0;
       return (temp&0x80);  //如果忙

       /*狀態字爲temp(8位2進制數)的最高位,最高位爲1表示禁止讀寫,爲0表示允許讀寫,即temp&0x80得1表示忙,得0表示不忙*/

    }

    /*在lcd1602的資料中,讀寫操作都有對應的時序圖,想要理解lcd1602的具體工作流程還得認真研究時序圖!*/

    void Lcd1602_WriteCom(uchar com)  //寫命令
    {
       while(Lcd1602_ReadBusy());  //判忙
       RS=0;   //命令
       RW=0;   //寫
       _nop_();
       P0=com;   //準備發送命令
       _nop_();
       E=1;      //由時序圖知,使能端爲高電平時才允許數據交換
       _nop_();
       _nop_();
       E=0;      //由時序圖知,使能端在完成數據交換後要拉低
       _nop_();
       _nop_();   
    }

    void Lcd1602_WriteData(uchar dat)  //寫數據
    {
       while(Lcd1602_ReadBusy());   //判忙
       RS=1;   //數據
       RW=0;   //寫
       _nop_();
       P0=dat;
       _nop_();
       E=1;
       _nop_();
       _nop_();
       E=0;
       _nop_();
       _nop_();   
    }

    void Lcd1602_init()   //初始化函數
    {
       delay_ms(15);
       write_com(0x38);   //顯示模式設置
       delay_ms(5);
       write_com(0x38);
       delay_ms(5);
       write_com(0x38);
       write_com(0x0c);  //顯示開
       write_com(0x01);  //顯示清屏
       write_com(0x06);  //顯示光標
    }

    void main()
    {
       uchar i,j;
       Lcd1602_init();
       Lcd1602_WriteCom(0x80);   //0x80是第一行的第一個字符的地址
       for(i=0;i<10;i++)  
          Lcd1602_WriteData(text1[i]);   
       Lcd1602_WriteCom(0x80+0x40);   //0xc0是第二行的第一個字符的地址

       /*表示的方法有很多,可以用0xc0,0x80+0x40,0x80|0x40等等*/

       for(j=0;j<10;j++)
          Lcd1602_WriteData(text2[j]);
    }

其實,LCD1602還有很多很好玩的指令,比如讓字符左移右移,大家可以好好看一看lcd1602資料中的相關指令,自己動手去實踐一下,纔會有更深刻的體會。

發佈了39 篇原創文章 · 獲贊 303 · 訪問量 40萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章