【嵌入式模块】LCD1602LCD12864
前言
??作為最為常見(jiàn)的顯示模塊LCD1602和LCD12864常常會(huì)被用來(lái)調(diào)試,也曾遇到用LCD作為顯示器顯示傳感器測(cè)量結(jié)果的小項(xiàng)目,這篇博客簡(jiǎn)單總結(jié)一下LCD的使用。
一個(gè)小問(wèn)題
如何判斷自己拿的是不是帶字庫(kù)的LCD?
- 找到型號(hào),看數(shù)據(jù)手冊(cè)
- 如果沒(méi)有找到數(shù)據(jù)手冊(cè),可以看看模塊背后有幾個(gè)芯片,有說(shuō)三個(gè)芯片(三坨黑色的東西)就是帶字庫(kù)的,兩個(gè)芯片就是不帶字庫(kù)的。
- 看引腳:有說(shuō)如果有PSB引腳的為帶字庫(kù)的,不帶字庫(kù)的有兩個(gè)CS1和CS2引腳,用來(lái)選擇左右半屏的。
??我之前一直以為1602和12864是一樣的,只是屏幕大小的區(qū)別,但后來(lái)發(fā)現(xiàn),其實(shí)使用方法上也不一樣,12864具有串行數(shù)據(jù)傳輸?shù)墓δ?#xff0c;而1602只能使用并行數(shù)據(jù)傳輸。
LCD1602
參考鏈接
- LCD1602液晶顯示屏的入門級(jí)應(yīng)用(一)- CSDN
- lcd1602使用手冊(cè),LCD1602的使用詳解 - 電子發(fā)燒友
- LCD1602液晶使用介紹–(完整版)- CSDN
引腳定義
??先來(lái)看看1602的引腳定義,如下圖所示:
??使用時(shí),將VDD、BLA接5V電源,VSS、BLK接地,VL接一個(gè)0-5V的電壓信號(hào),其大小會(huì)影響實(shí)際顯示效果,需要根據(jù)實(shí)際情況調(diào)整。
??信號(hào)方面,RS、R/W、E為控制信號(hào),D0~D7為數(shù)據(jù)傳輸引腳,用來(lái)輸入或輸出指令(狀態(tài))和數(shù)據(jù)。
操作時(shí)序
讀操作時(shí)序
寫操作時(shí)序
時(shí)序參數(shù):
總結(jié)來(lái)說(shuō):
其中,讀取到的狀態(tài)字定義如下:
指令介紹
??除顯示數(shù)據(jù)的傳輸外,LCD1602的使用就是靠寫入不同的指令來(lái)實(shí)現(xiàn),其指令總結(jié)如下:
初始化的順序:
51程序示例
#include<reg52.h> //包含頭文件#define uint unsigned int //預(yù)定義 #define uchar unsigned char sbit rs=P2^6; //1602的數(shù)據(jù)/指令選擇控制線 sbit rw=P2^5; //1602的讀寫控制線 sbit en=P2^7; //1602的使能控制線 /*P0口接1602的D0~D7*/ uchar code table[]="1234"; //要顯示的內(nèi)容放入數(shù)組table void delay(uint n) //延時(shí)函數(shù) { uint x,y; for(x=n;x>0;x--) for(y=110;y>0;y--); } void lcd_wcom(uchar com) //1602寫命令函數(shù) { rs=0; //選擇指令寄存器 rw=0; //選擇寫 P0=com; //把命令字送入P2 delay(5); //延時(shí)一小會(huì)兒,讓1602準(zhǔn)備接收數(shù)據(jù) en=1; //使能線電平變化,命令送入1602的8位數(shù)據(jù)口 en=0; } void lcd_wdat(uchar dat) //1602寫數(shù)據(jù)函數(shù) { rs=1; //選擇數(shù)據(jù)寄存器 rw=0; //選擇寫 P0=dat; //把要顯示的數(shù)據(jù)送入P2 delay(5); //延時(shí)一小會(huì)兒,讓1602準(zhǔn)備接收數(shù)據(jù) en=1; //使能線電平變化,數(shù)據(jù)送入1602的8位數(shù)據(jù)口 en=0; } void lcd_init() //1602初始化函數(shù) { lcd_wcom(0x38); //8位數(shù)據(jù),雙列,5*7字形 lcd_wcom(0x0c); //開(kāi)啟顯示屏,關(guān)光標(biāo),光標(biāo)不閃爍 lcd_wcom(0x06); //顯示地址遞增,即寫一個(gè)數(shù)據(jù)后,顯示位置右移一位 lcd_wcom(0x01); //清屏 } void main() //主函數(shù) { uchar m=0; lcd_init(); //液晶初始化 lcd_wcom(0x80); //顯示地址設(shè)為80H(即00H,)上排第一位 for(m=0;m<4;m++) //將table[]中的數(shù)據(jù)依次寫入1602顯示 {lcd_wdat(table[m]); delay(200); } while(1); //動(dòng)態(tài)停機(jī) }顯示漢字或自定義字符
??根據(jù)上面判斷顯示模塊是否帶字庫(kù)的方法,我們可以發(fā)現(xiàn)1602只有兩個(gè)芯片,即不帶字庫(kù),那有沒(méi)有辦法可以顯示漢字和自定義的字符呢?還真有。
??在LCD1602模塊中,不同位置顯示的字符實(shí)際上是來(lái)自于DDRAM中不同地址的數(shù)據(jù),在某個(gè)位置顯示內(nèi)容即在對(duì)應(yīng)地址的DDRAM中寫入數(shù)據(jù)。因此,這樣顯示出來(lái)的數(shù)據(jù)都是其自帶的數(shù)據(jù),也就是ASCII中的字符。
??除此之外,LCD1602模塊中還有CGRAM和CGROM兩個(gè)儲(chǔ)存位置。其中CGROM可以看作是儲(chǔ)存ASCII字庫(kù)的位置,不能更改,掉電信息不消失。而CGRAM可隨機(jī)讀寫,有8個(gè)字節(jié)的空間,用來(lái)存放自定義字符的代碼。
??仔細(xì)觀察LCD1602的顯示背景可以發(fā)現(xiàn),它所有顯示的內(nèi)容都是在一個(gè)5x8的點(diǎn)陣中顯示的,而且最底下那行沒(méi)有使用,即5x7點(diǎn)陣,這也是關(guān)于LCD顯示的指令中5x7點(diǎn)陣的來(lái)源。
??因此,如果需要顯示自定義的字符,那就需要將設(shè)置5x8點(diǎn)陣的數(shù)據(jù)傳遞給LCD顯示模塊,如下圖就是一個(gè)自定義的°C的符號(hào):
??其中,每一行對(duì)應(yīng)一個(gè)8位的數(shù)據(jù)(高三位沒(méi)有使用,固定為0),一共需要8個(gè)數(shù)據(jù),正好可以放在CGRAM中。因此,顯示自定義字符時(shí),首先要在CGRAM中寫入字符代碼,然后再設(shè)置CGRAM中的數(shù)據(jù)傳輸?shù)紻DRAM的位置。其中,寫入CGRAM的指令如下圖所示:
??注意:上圖為12864的CGRAM指令格式,而1602的CGRAM的地址只有從000~111共8個(gè)地址為有效地址,對(duì)應(yīng)指令為0x40 ~ 0x47。
概況來(lái)說(shuō),這三者之間的關(guān)系大概如下所示
其51程序如下所示:
#include<reg52.h> //包含頭文件#define uint unsigned int //預(yù)定義 #define uchar unsigned char sbit rs=P2^6; //1602的數(shù)據(jù)/指令選擇控制線 sbit rw=P2^5; //1602的讀寫控制線 sbit en=P2^7; //1602的使能控制線 /*P0口接1602的D0~D7*/ uchar code table[]={0x10,0x06,0x09,0x08,0x08,0x09,0x06,0x00}; //要顯示的內(nèi)容放入數(shù)組table void delay(uint n) //延時(shí)函數(shù) { uint x,y; for(x=n;x>0;x--) for(y=110;y>0;y--); } void lcd_wcom(uchar com) //1602寫命令函數(shù) { rs=0; //選擇指令寄存器 rw=0; //選擇寫 P0=com; //把命令字送入P2 delay(5); //延時(shí)一小會(huì)兒,讓1602準(zhǔn)備接收數(shù)據(jù) en=1; //使能線電平變化,命令送入1602的8位數(shù)據(jù)口 en=0; } void lcd_wdat(uchar dat) //1602寫數(shù)據(jù)函數(shù) { rs=1; //選擇數(shù)據(jù)寄存器 rw=0; //選擇寫 P0=dat; //把要顯示的數(shù)據(jù)送入P2 delay(5); //延時(shí)一小會(huì)兒,讓1602準(zhǔn)備接收數(shù)據(jù) en=1; //使能線電平變化,數(shù)據(jù)送入1602的8位數(shù)據(jù)口 en=0; } void lcd_init() //1602初始化函數(shù) { lcd_wcom(0x38); //8位數(shù)據(jù),雙列,5*7字形 lcd_wcom(0x0c); //開(kāi)啟顯示屏,關(guān)光標(biāo),光標(biāo)不閃爍 lcd_wcom(0x06); //顯示地址遞增,即寫一個(gè)數(shù)據(jù)后,顯示位置右移一位 lcd_wcom(0x01); //清屏 } void main() //主函數(shù) { uchar m; lcd_init(); //液晶初始化 lcd_wcom(0x40);//設(shè)定CGRAM地址,把自定義字符存儲(chǔ)進(jìn)去 for(m=0;m<8;m++) //將table[]中的數(shù)據(jù)依次寫入1602顯示 { lcd_wdat(table[m]); delay(200); } lcd_wcom(0x85); //顯示地址設(shè)為85H,上排中間位lcd_wdat(0);while(1); //動(dòng)態(tài)停機(jī) }??需要注意:在最后寫入自定義字符時(shí),還寫入了一個(gè)0,我的理解是,這一步的就是正常的寫入顯示內(nèi)容的指令,但沒(méi)有從D0~D7引腳輸入數(shù)據(jù),模塊就自動(dòng)調(diào)用CGRAM中的數(shù)據(jù),這個(gè)0不能換成其他任何數(shù)據(jù)!
??經(jīng)過(guò)測(cè)試發(fā)現(xiàn),如果要顯示兩個(gè)不同的自定義字符很有可能會(huì)發(fā)生沖突的情況,顯示效果較差。
LCD12864
引腳定義
??對(duì)于LCD12864,有兩種工作模式,串行和并行,當(dāng)PSB引腳為低電平時(shí),其工作在串行模式下,此時(shí)其通信模式類似于SPI,靠三根引腳CS(片選)、SID(數(shù)據(jù)輸入端)、CLK(時(shí)鐘輸入端) 來(lái)進(jìn)行通信,因此其數(shù)據(jù)傳輸端口DB0~DB7無(wú)效;當(dāng)PSB引腳為高電平時(shí),其工作在并行模式下,此時(shí)RS(CS)、R/W(SID)、E(CLK) 為控制信號(hào)輸入端,DB0~DB7為數(shù)據(jù)輸入輸出端。
??因此,串行和并行方式下使用的引腳也不相同,如下圖所示:
??其中,由于并行引腳工作方式與LCD1602十分接近,而且目前串行操作更加流行,因此這里只介紹串行控制方法,并行控制方法可以參考1602
指令集
??在LCD12864中,具有兩套指令:基本指令和擴(kuò)展指令,選擇哪一套指令可以通過(guò)輸入指令來(lái)選擇,指令具體如下所示:
初始化流程
??可以對(duì)照上述指令表根據(jù)自己的需要來(lái)設(shè)置。
串行工作時(shí)序圖
??這張圖需要仔細(xì)看。首先是CS信號(hào),在傳輸數(shù)據(jù)時(shí)必須為高電平,如果不需要考慮那么多的話,可以直接連接VCC,使其始終有效。
??然后是SCLK信號(hào),仔細(xì)觀察可以發(fā)現(xiàn),在SCLK上升沿產(chǎn)生數(shù)據(jù)傳輸,即SCLK上升沿之前要把數(shù)據(jù)準(zhǔn)備好。
??最后是SID信號(hào),從圖中可以看出,每次傳輸一個(gè)字節(jié)的數(shù)據(jù),需要24個(gè)時(shí)鐘,即傳輸3個(gè)字節(jié)。其中第一個(gè)字節(jié)為選擇傳輸數(shù)據(jù)還是傳輸指令,第二個(gè)字節(jié)為數(shù)據(jù)字節(jié)的高4位加4個(gè)0,第三個(gè)字節(jié)為數(shù)據(jù)字節(jié)的低4位加4個(gè)0。
51例程
#include "LCD.h"void delay_us(uint8_t time) {time *= 0.9; //晶振為11.0592MHzwhile(time--); }void delay_ms(uint8_t times) {while(times--){delay_us(1000);} }void send_byte(uint8_t byte) {uint8_t i;for(i=0; i<8; i++){if((byte << i) & 0x80) //從最高位開(kāi)始{LCD_SID = 1;}else{LCD_SID = 0;}LCD_SCK = 0; // delay_us(5);LCD_SCK = 1;} }void write_cmd(unsigned char cmdcode) { // delay_ms(1);send_byte(0xf8); //告訴12864接下來(lái)傳送指令send_byte(cmdcode & 0xf0); //先傳輸高4位send_byte((cmdcode << 4) & 0xf0); //后傳輸?shù)?位 // delay_us(100); //延時(shí)待數(shù)據(jù)寫入 }void write_data(unsigned char Dispdata) { // delay_ms(1);send_byte(0xfa); //告訴12864接下來(lái)傳送數(shù)據(jù)send_byte(Dispdata & 0xf0); //先傳輸高4位send_byte((Dispdata << 4) & 0xf0); //后傳輸?shù)?位 // delay_us(100); //延時(shí)待數(shù)據(jù)寫入 }void LCD_Init(void) {delay_ms(200); //等待液晶自檢,延時(shí)50mswrite_cmd(0x30); //基本指令操作,8bit // delay_us(150); //延時(shí)137us以上write_cmd(0x0c); //顯示開(kāi)關(guān)閉光標(biāo) // delay_us(110); //延時(shí)100us以上write_cmd(0x01); //清屏delay_ms(100); //清屏后等待一段時(shí)間實(shí)現(xiàn)穩(wěn)定 // write_cmd(0x06); }void write_str(char *s) { // while(*s > 0) // { // write_data(*s); // s++; // delay_ms(5); // }unsigned char i = 0; while(s[i]!='\0') { write_data(s[i]); i++; delay_ms(5); } }void write_title(void) {write_cmd(0x80); //第一行首位write_str("距離為");write_cmd(0x90); //第二行首位write_str("速度為");write_cmd(0x88); //第三行首位write_str("角度為");write_cmd(0x98); //第四行首位write_str("加速度為");delay_ms(50); }??上述例程中有一點(diǎn)需要注意:由于Keil_C51的編譯器太垃圾,經(jīng)過(guò)測(cè)試,傳輸字符串函數(shù)中的指針部分無(wú)法識(shí)別,對(duì)應(yīng)那被注釋掉的部分代碼。
問(wèn)題與解決
??在調(diào)試上面那部分代碼時(shí),發(fā)現(xiàn)一個(gè)很嚴(yán)重的問(wèn)題,那就是LCD12864一旦顯示中文,總是顯示亂碼。
??在網(wǎng)上查找資料時(shí)發(fā)現(xiàn),有說(shuō)Keil缺少某一個(gè)文件的,需要把它添加到根目錄下的bin文件夾中,但我試了并不管用;還有說(shuō)需要把Keil中含有中文字符的代碼文件轉(zhuǎn)換為ASCII編碼格式的文件,這一點(diǎn)我也試了【而且不知道ASCII是個(gè)什么編碼格式】,并不管用。
??但第二種方法啟發(fā)了我,我試著將我的Keil編碼格式改為GB2312【原來(lái)為了更好看的字體改為了UTF-8】,然后通過(guò)Notepads將文件以GB2312編碼格式保存,意外發(fā)現(xiàn)問(wèn)題已經(jīng)解決!
高階應(yīng)用:顯示自定義字符
??和1602一樣,12864中也具備顯示自定義字符的功能,而且使用方法也非常類似,也是向CGRAM中寫入自定義字符的代碼,然后再寫入到DDRAM,從而顯示出來(lái)。
??值得一提的是,12864中的CGRAM有4組16x16的空間,共128個(gè)字節(jié),可以顯示4個(gè)16x16的自定義漢字或符號(hào)。其指令如下圖所示:
??參考指令表可以得出:該四個(gè)漢字的指令地址為0x40~0x4F、0x50 ~ 0x5F、0x60 ~ 0x6F、0x70 ~ 0x7F,配合取模軟件,即可得到自定義的字符,其中,每一行的16位拆分為高8位和低8位,兩個(gè)字節(jié),然后開(kāi)啟下一行。
總結(jié)
以上是生活随笔為你收集整理的【嵌入式模块】LCD1602LCD12864的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 怎样进行文献调研?——与青年朋友谈科研(
- 下一篇: 单片机c语言1602怎么接线,lcd16