LCD 1602 穩定顯示
LCD1602可顯示兩行,每行16個字符,不能顯示漢字。16腳的LCD 1602帶背光,14腳的不帶背光。
本文引用地址:http://www.104case.com/article/201611/318599.htm2LCD1602 端口引腳
不一一記錄手冊上面是咋個描述LCD 1602的了。記錄一下操作過程,下圖是LCD 1602在51單片機上面的連線。
圖1 LCD 與單片機接線圖
D0-D7引腳連接在單片機的P0端口。
LCD_RS = P1^0;LCD_RW = P1^1;LCD_EN = P2^5;
查看LCD 1602手冊,得到LCD引腳組合的含義如下:
表格1:LCD操作模式
模式 | 輸入 | 輸出 |
讀狀態 | RS=0,RW=H,EN為高變低脈沖 | 輸出:D0~D7個狀態值 |
讀數據 | RS=1,RW=1,EN為高變低脈沖 | 輸出:無 |
寫指令 | RS=0,RW=0,D0--D7=數據,EN由高脈沖變為低脈沖 | 輸出D0--D7狀態值 |
寫數據 | RS=1, RW=0, D0--D7=數據,EN由高脈沖變為低脈沖 | 輸出D0--D7狀態值 |
可以參照圖1的接線圖對這些模式和輸入輸出做出相應的理解。模式、輸入都是跟單片機I/O端口相連的端口。輸出是使LCD顯示的內容。在編寫程序時,可以先設置LCD顯示內容的格式(初始化LCD),然后再對LCD進行讀寫操作。這些過程由LCD跟單片機相連的I/O端口來完成。
3LCD 1602的操作時序
查看LCD 1602手冊,以LCD寫操作時序為例記錄在對LCD操作的過程中需要注意到的延遲語句的編寫,否則可能導致對LCD的操作失敗。
圖2 LCD的寫操作時序
根據表一LCD的操作時序可知,在RS,RW,E(N),DB7.0(D0-D7)滿足一定時序的高低電平條件時就可以對LCD進行寫操作。變化都不是瞬間的,在對RS等置高置低時,RS等變高變低有一個下劃的過度時間,如果這種過渡的時間超過單片機內一條或幾條指令的執行時間,則這種時序就有可能會被錯開。如現在對LCD進行寫操作,將RS置高,RW置低,準備好DB7.0數據,E由高變低等操作由以下代碼完成:
LCD_RS = 1;LCD_RW = 0;DB7_0 = ‘A’;LCD_EN = 1;LCD_EN = 0;
RS在高電平時選擇數據寄存器,在低電平時選擇指令寄存器。
RW在高電平時進行讀操作,在低電平時進行寫操作。
E(N)為使能端,當E(N)端由高電平跳變為低電平時,LCD模塊執行命令。
DB7.0為8位雙向數據。
其中LCD_RS等都是單片機控制LCD RS等端口的引腳,如果(^-^)只有RS端徹底變為1的時間超過以上的所有代碼執行時間,則在E低脈沖到來之時,RS還是低電平,所以由于RS的電平不滿足條件對LCD的寫操作將會失敗。當然,傳說LCD的電平變化時間比指令執行時間快,但是為了可靠穩定,在程序中肯定需要等待對應的端口徹底變為需要電平時再寫其它端口的值。就這么等待太長時間肯定是會為程序的執行結果帶來影響,只需要等待端口的電平能完全變化的時間即可。手冊中有說明的:
圖3 LCD初始化圖
雖然需要等待的時間對于人類來說實在是可以忽略不計,但在LCD類中來說卻是必須的。如果沒有這些等待,那么就有可能遇不到LCD與你寫入內容的邂逅或者出現偶爾成功偶爾失敗的場景。
在每次讀/寫指令后都應該等待一段時間來等待LCD 端口電平的徹底變化,可用keil軟件模擬一段時間,用5ms(等待時間小于5ms者)等時間代替需要等待的時間都是可以的。
4 LCD1602的指令集 相關
4.1 LCD指令集筆記
在LCD 1602指令集中,對LCD來說有四種意思:
(1)RS和RW都為0時表示對LCD寫指令操作,包括寫入LCD的顯示模式和設定LCD地址的指令。.顯示模式包括清屏、地址歸為、顯示狀態、進入點設定、功能設定、游標顯示模式操作;關于地址的操作包括設定CGRAM地址、設定DDRAM地址。
(2)當RS=0,RW=1時,表示讀LCD狀態,此時可以讀取LCD忙信號,同時可以讀取地址計數器的值。忙信號的狀態用來確定LCD內部動作是否完成,若在LCD內部出于忙狀態時對LCD進行讀寫操作將會失敗。
(3)當RS=1時,若RW=0表示寫數據操作,若RW=1表示讀數據操作。
4.2 CGRAM
CGRAM為LCD模塊內部的字符發生存儲器,里面存了不同的點陣字符圖形,包括阿拉伯數字,英文大小寫字符等。每個字符都有一個固定的代碼,如‘A’的代碼是01000001,(41H),需要顯示‘A’時只需要將地址為41H中的點陣圖形顯示出來就可以看見‘A’了。具體字符點陣圖查看手冊為全宜。
4.3 LCD1602顯示屏內部顯示地址表
輸入顯示字符地址,也就是告訴LCD在哪里顯示字符。LCD供兩行,第一行可立即顯示字符的地址為00H—0FH,第二行可立即顯示字符的地址為40H—67H,如果在其它地址中顯示字符,需要通過移屏指令[00011000:整屏左移光標跟著移動; 00011100:整屏右移光標跟著移動]將它們移入可顯示區域方可正確顯示。當要在00H處顯示字符時,寫入的地址應為00H + 80H(因為置LCD顯示位置時要求D7位始終為1,手冊中‘置數據存儲器地址’指令)
5 LCD 1602程序編寫
5.1 LCD初始化
//----------------------- ---------//寫命令,初始化端口設置LCD顯示模式//----------------------- ---- ----void LCD_mode_init(){LCD_EN = L;//等待LCD電路完全接通delay_ms( DELAY_TIME_FOR_INIT );//P0= 00111000設置16x2顯示,5x7點庫,8位數據端口write_command( 0x38 );delay_ms( DELAY_TIME );//LCD開顯示,顯示光標,光標閃爍write_command( 0x0f );//讀寫字符后地址指針、光標加1,整屏顯示不移動write_command( 0x06 );//清顯示,便對LCD寫入write_command( 0x01 );}
根據圖3,當LCD電路接通之時,需要用約15ms的時間來讓LCD VDD電壓達4.5V,雖然在開啟單片機電源的時候程序還未執行到初始化程序就已經過了15ms讓LCD VDD電源達4.5V。但也有可能程序中只包含了LCD程序,初始化被放在了最前面,15ms的時間足以讓單片機運行很多指令了(可以由單片機的機器周期和一條指令執行的機器周期數比較一下),為了防止在LCDVDD電源未達4.5V時單片機程序已經執行到設置LCD顯示模式的指令,就在進入LCD初始化程序時等待15ms的時間,讓LCD電源初始化完畢。
5.2 寫指令
//-------- -----//寫命令//--------- ----void write_command( uchar command ){while( lcd_busy() );LCD_RS = L;LCD_RW = L;delay_ms(DELAY_TIME); P0 = command;//等待數據穩定delay_ms(DELAY_TIME);LCD_EN = H;//讓使能位保持到一,負脈沖跳變delay_ms( DELAY_TIME );LCD_EN = L;delay_ms( DELAY_TIME );}
寫指令前首先要檢查LCD內部操作是否已經完成,LCD的BF位(D7)為高電平表示忙,為低電平表示空閑。同理,在對每一個端口設置高低電平后,同樣需要一段時間來等待電平的徹底變化。
5.3 寫數據
//-----------------------//寫數據,寫LCD顯示內容//-----------------------void write_data( uchar wdata ){while( lcd_busy() );LCD_RS = H;LCD_RW = L;LCD_EN = L;P0 = wdata;//等待DB0-DB7數據穩定delay_ms( DELAY_TIME );LCD_EN = H;//讓使能位充分達到1delay_ms( DELAY_TIME );LCD_EN = L;delay_ms( DELAY_TIME );}
5.4 檢測LCD忙信號
//--------------------//檢測LCD的忙信號//--------------------bit lcd_busy(){ bit result;LCD_RS = 0;LCD_RW = 1;LCD_EN = 1;delay_ms( DELAY_TIME );result = (bit)(P0&0x80);LCD_EN = 0;return result; }
在檢測LCD忙信號的同時,還可以設置一下原本該低或該高的位的狀態。P0端口是連接到D0—D6端口的I/O引腳,0x80就是用來檢測D7位狀態的數據。
5.5 延遲函數
//-------- -----//延遲函數//--------- ----void delay_ms( uint ms ){ uint i, j;for(i = ms; i > 0; i--){for(j = 110; j > 0; j--){;}}}
根據單片機的晶振和keil執行指令的時間計算,以上延遲函數約延遲ms 毫秒的時間。DELAY_TIME的宏值為5,表示延遲5毫秒的時間。LCD有的端口不需要延遲這么長的時間,這個可以調試到適合相應端口最適合的延遲時間即可。借助手冊和枚舉調試法。
5.6 運行結果
將初始化函數放置在main函數中后,將LCD的顯示地址設置在第一行第一列(此指令在寫指令集中,可調用write_command(0x80)來完成),然后寫字符到LCD第一行中。再將顯示地址跳到第二行,地址后移需要顯示字符傳長度個單位,寫入顯示的字符傳,對整個屏幕移位(由寫指令集中指令完成,移字符傳長度那么多位,移完一個停留的時間需要長點,如200ms左右的時間)。
然后讓程序等待,只為LCD操作演示^-^。
程序的效果為:首先在第一行顯示了指定的字符串。當移入第二行字符串時,由于是整個屏幕的移動,所以第一行字符串也隨之移入了屏幕的左邊。
現將兩行的字符串顯示在LCD屏幕之上,不采取移動的操作。
6 總結
電平變化時不是瞬間的,需要用延遲函數來等待相應位徹底的編程預期的電平。這是跟寫其它程序的一個區別。每逢遇到對硬件引腳電平的置位時,都需要結合手冊看看對應引腳的靈敏度,若高出指令執行時間徐許多數量級就不用延遲語句,否則應當考慮用延遲語句來等待。應該走進硬件的操作時序世界中去才能編寫好它們的程序。
此次筆記記錄完畢。
評論