這是我對(duì)12864的學(xué)習(xí)筆記,12864液晶功能很全面,使用起來(lái)也很方便,能夠滿足一般的研究和工程應(yīng)用的需求。下面我就對(duì)幾個(gè)方面講述一下我對(duì)它學(xué)習(xí)過(guò)程中的一些體會(huì)。我會(huì)盡量全面的介紹,并且會(huì)主要針對(duì)一些特殊的應(yīng)用和一些我認(rèn)為要特別注意的地方進(jìn)行較為詳細(xì)的說(shuō)明。而對(duì)于那些較為固定的,常用的方面會(huì)簡(jiǎn)略一些。
本文引用地址:http://m.butianyuan.cn/article/201611/316301.htm其中的不管串行模式還是并行模式,對(duì)液晶的寫指令,寫數(shù)據(jù),讀操作等這些基本的操作都是一些比較固定的,基礎(chǔ)的東西。我認(rèn)為只要能夠看懂,并且能夠在不同的處理器上移植就夠了,沒有必要非要自己對(duì)著手冊(cè)時(shí)序圖寫出來(lái)。因?yàn)橛腥艘呀?jīng)寫好了,而且工作穩(wěn)定,我們只要在它的基礎(chǔ)上學(xué)會(huì)應(yīng)用就可以了。現(xiàn)在是知識(shí)爆炸時(shí)期,知識(shí),信息迅速膨脹,我們要學(xué)會(huì)使用已有的成果,然后在這個(gè)基礎(chǔ)上自己再進(jìn)行開發(fā)應(yīng)用的研究。我們不必一定要從底層開始把別人已經(jīng)做的很成熟的東西再做一遍,這樣不但效率不高,而且我們一般人的精力也不允許。
好了,不說(shuō)廢話了,下面就開始介紹,當(dāng)然,那些基礎(chǔ)層面的東西我也會(huì)介紹的。
下面所涉及到的程序,是針對(duì)msp430g2553的,都是我已經(jīng)調(diào)通的,可以直接應(yīng)用。
一,12864的介紹
1,液晶顯示模塊是128×64點(diǎn)陣的漢字圖形型液晶顯示模塊,可顯示漢字及圖形,內(nèi)置國(guó)標(biāo)GB2312碼簡(jiǎn)體中文字庫(kù)(16X16點(diǎn)陣)、128個(gè)字符(8X16點(diǎn)陣)及64X256點(diǎn)陣顯示RAM(GDRAM)??膳cCPU直接接口,提供兩種界面來(lái)連接微處理機(jī):8-位并行及串行兩種連接方式。具有多種功能:光標(biāo)顯示、畫面移位、睡眠模式等。
2,常用的12864液晶內(nèi)部都是使用ST7920控制器。
1),ST7920提供8位元,4位元及串行三種微處理器控制方式,大陸常用的是8位元和串行控制方式。
2),ST7920可以控制顯示字母,數(shù)字符號(hào),中文字型和自定義的圖畫。可以用來(lái)顯示圖形,演示動(dòng)畫,繪制曲線等。
3),字符顯示RAM(DDRAM)
ST7920的字符顯示RAM(DDRAM)最多可以控制16字元*4行,LCD的顯示范圍為16字元*2行。
這里要注意,其實(shí)ST7920的DDRAM每一行可以控制16個(gè)漢字的,共有4行。但是LCD的每行只能顯示8個(gè)字符,為了顯示觀察的方便,在lcd制作的過(guò)程中,是將DDRAM的其中兩行拆分開成四行,然后在lcd上顯示,也即是DDRAM只用到了一半。
lcd的顯示字符的坐標(biāo)地址如下表:
漢字顯示坐標(biāo)
Line180H81H82H83H84H85H86H87H
Line290H91H92H93H94H95H96H97H
Line388H89H8AH8BH8CH8DH8EH8FH
Line498H99H9AH9BH9CH9DH9EH9FH
從上表不難看出,其中第一行和第三行是DDRAM中的同一行拆分來(lái)的,同理24行也是DDRAM中的同一行拆分而來(lái)的。
了解了這一點(diǎn)就不難理解下面程序中在換行顯示時(shí),要認(rèn)為手動(dòng)地指定下一行的地址。例如:如果第一行顯示完了,下面的數(shù)據(jù)我要接著顯示在第二行,這樣才符合人觀察的習(xí)慣,那么我就要在換第二行顯示之前要手動(dòng)地把顯示地址切換到第二行。要不然的話,第一行顯示完了,地址會(huì)自動(dòng)增加,就會(huì)顯示到第三行上去,這樣的話我們觀察起來(lái)就不自然了。程序?qū)嵗龝?huì)在下面涉及到的。
4),中文字庫(kù)ROM(CGROM)
內(nèi)置的是GB2312碼簡(jiǎn)體中文字庫(kù),共提供了8192個(gè)16*16點(diǎn)的中文字型。
5),半寬字型ROM(HCGROM)
提供126個(gè)16*8點(diǎn)半字寬的字母符號(hào)字型。
6),圖畫顯示RAM(GDRAM)
提供64*256位元的GDRAM
其中我們常用的RAM就是上面所提到的,還有一些CGRAM,IRAM這些我們不經(jīng)常使用,就不再介紹了。
上面介紹的DDRAM控制顯示漢字,字符。GDRAM控制顯示圖畫,上電后,默認(rèn)DDRAM是打開的,控制液晶顯示。GDRAM默認(rèn)不打開,它里面的數(shù)據(jù)是隨機(jī)的,如果此時(shí)打開了GDRAM的話,lcd會(huì)同時(shí)受到DDRAM和GDRAM的控制,由于GDRAM中的數(shù)據(jù)是隨機(jī)的,所以會(huì)顯示亂碼。所以在使用GDRAM之前要先清除里面的隨機(jī)數(shù)據(jù)。
清除GDRAM的函數(shù)如下:
voidClear_GDRAM(void)//清除GDRAM中的的隨機(jī)數(shù)據(jù)。因?yàn)樯想姾驡DRAM中的數(shù)據(jù)是隨機(jī)的,如果不清除而直接打開GDRAM顯示時(shí),會(huì)顯示亂碼
//所以在局部使用GDRAM顯示圖形時(shí),要先清除隨機(jī)數(shù)據(jù)。如果是全局使用GDRAM,即整個(gè)lcd屏全部設(shè)置顯示數(shù)據(jù),則可以
//不必清除,因?yàn)樾聰?shù)據(jù)會(huì)把隨機(jī)數(shù)據(jù)給覆蓋掉
{
uchari,j,k;
wr_lcd(comm,0x34);//打開擴(kuò)展指令集操作GDRAM是擴(kuò)展指令集
i=0x80;
for(j=0;j<32;j++)
{
wr_lcd(comm,i++);
wr_lcd(comm,0x80);
for(k=0;k<16;k++)
{
wr_lcd(dat,0x00);//寫入空字符,就相當(dāng)于清零
}
}
i=0x80;
for(j=0;j<32;j++)
{
wr_lcd(comm,i++);
wr_lcd(dat,0x88);
for(k=0;k<16;k++)
{
wr_lcd(dat,0x00);
}
}
wr_lcd(comm,0x30);//回到基本指令集
}
3,12864有兩種工作模式
1),并行模式和串行模式。并行模式就是常用的8位數(shù)據(jù)線,4為控制線。這種方式雖然占用的IO口較多,但是向液晶收發(fā)數(shù)據(jù)較容易實(shí)現(xiàn),數(shù)據(jù)傳輸速度較快。所以在一些連續(xù)顯示多幅圖畫,演示動(dòng)畫或?qū)︼@示的實(shí)時(shí)性要求較高的場(chǎng)合應(yīng)該考慮這種方式。其中在并行模式中,在向液晶寫數(shù)據(jù)或命令前,要進(jìn)行液晶忙標(biāo)志判斷BF,要確定液晶顯示不忙了,才能進(jìn)行操作。
其中并行模式的液晶的讀寫數(shù)據(jù),命令函數(shù)如下:
voidWrite_Cmd(ucharcmd)
{
ucharlcdtemp=0;
LCD_RS_L;
LCD_RW_H;
LCD_DataIn;//數(shù)據(jù)輸入單片機(jī)
do//判忙
{
LCD_EN_H;
_NOP();
lcdtemp=LCD2MCU_Data;
LCD_EN_L;
}
while(lcdtemp&0x80);//判斷忙標(biāo)志等待忙
LCD_DataOut;//數(shù)據(jù)輸出到lcd
LCD_RW_L;
MCU2LCD_Data=cmd;//單片機(jī)向lcd輸入命令
LCD_EN_H;
_NOP();
LCD_EN_L;
}
voidWrite_Data(uchardat)
{
ucharlcdtemp=0;
LCD_RS_L;
LCD_RW_H;
LCD_DataIn;
do//判忙
{
LCD_EN_H;
_NOP();
lcdtemp=LCD2MCU_Data;
LCD_EN_L;
}
while(lcdtemp&0x80);//等待忙
LCD_DataOut;
LCD_RS_H;
LCD_RW_L;
MCU2LCD_Data=dat;//單片機(jī)向lcd中輸入數(shù)據(jù)
LCD_EN_H;
_NOP();
LCD_EN_L;
}
2),串行模式只用到了兩根線WREN于單片機(jī)進(jìn)行通信。這種方式可以大大減少單片機(jī)IO口的開銷,適用于IO口資源有限的單片機(jī)(如msp430g2553)。但是這種方式實(shí)現(xiàn)起來(lái)較麻煩,數(shù)據(jù)的傳輸效率不高。對(duì)于一般的文字,簡(jiǎn)單圖形的顯示還是可以的。(有可能是因?yàn)閙sp430g2553的處理能力較強(qiáng),我現(xiàn)在用串行連接方式,顯示下面的幾幅圖畫,顯示效果很好,看不出有什么數(shù)據(jù)傳輸速度慢的問(wèn)題)。
由于我用的是msp430g2553,所以我一直都是使用串行的控制模式。
//下面重點(diǎn)講一下串行的時(shí)序
//SCLK:串行同步時(shí)鐘線,每操作一位數(shù)據(jù)都要有一個(gè)SCLK跳變沿,而且在這里是上升沿有效。也即是說(shuō),每次SCLK由低電平變?yōu)楦唠娖降乃查g,液晶控
//制器將SID上的數(shù)據(jù)讀入或輸出。
//SID:串行數(shù)據(jù),每一次操作都由三個(gè)字節(jié)數(shù)據(jù)組成,第一個(gè)字節(jié)向控制器發(fā)送命令控制字,告訴控制器接下來(lái)是什么操作,若為寫指令則發(fā)送11111000
//(0xf8),若為若為寫數(shù)據(jù)則發(fā)送11111010(0xfa),若為讀狀態(tài)則發(fā)送11111100(0xfc),若為讀數(shù)據(jù)則發(fā)送11111110(0xfe)。
//第二個(gè)字節(jié)的高4位為發(fā)送指令或數(shù)據(jù)的高4位,第二個(gè)字節(jié)的低4位補(bǔ)0.
//第三個(gè)字節(jié)的高4位為發(fā)送指令或數(shù)據(jù)的低4位,第三個(gè)字節(jié)的低4位補(bǔ)0
//具體的可以觀察時(shí)序進(jìn)行理解
其中數(shù)據(jù)的傳輸?shù)暮瘮?shù)如下:
//12864串行連接寫數(shù)據(jù),寫命令函數(shù)按照手冊(cè)上的時(shí)序進(jìn)行編程
void wr_lcd(uchar dat_comm,uchar content)//
{//要寫的數(shù)據(jù)
uchar a,i,j;
delay_us(50);
a=content;
LCD_SCLK0; //en=0;
LCD_SID1;//wr=1
for(i=0;i<5;i++) //數(shù)據(jù)時(shí)序*****************8前5個(gè)高電平的同步碼
{
LCD_SCLK1;
LCD_SCLK0;
}
LCD_SID0;//wr=0寫操作
LCD_SCLK1;//en=1來(lái)一個(gè)時(shí)鐘
LCD_SCLK0;//en=0
if(dat_comm)
LCD_SID1;//RS=1寫數(shù)據(jù)
else
LCD_SID0;//RS=0寫指令
LCD_SCLK1; //來(lái)一個(gè)時(shí)鐘
LCD_SCLK0;
LCD_SID0;//控制字的最后一位為0
LCD_SCLK1;//來(lái)一個(gè)時(shí)鐘
LCD_SCLK0;
for(j=0;j<2;j++)//************一共2*4次循環(huán)寫寫一字節(jié)數(shù)據(jù),第一次大循環(huán)寫高4位,第二次大循環(huán)寫低4位
{
for(i=0;i<4;i++)
{
if(a&0x80)
LCD_SID1;
else
LCD_SID0;
a=a<<1;
LCD_SCLK1;
LCD_SCLK0;
}
LCD_SID0;
for(i=0;i<4;i++)//時(shí)鐘下面來(lái)4個(gè)時(shí)鐘脈沖
{
LCD_SCLK1;
LCD_SCLK0;
}
}
}
voidDraw_TX(ucharYaddr,ucharXaddr,constuchar*dp)
{
ucharj;
uchark=0;
//wr_lcd(comm,0x01);//清屏,只能清除DDRAM
wr_lcd(comm,0x34);//使用擴(kuò)展指令集,關(guān)閉繪圖顯示打開擴(kuò)展指令集
for(j=0;j<16;j++)
{
wr_lcd(comm,Yaddr++);//Y地址
wr_lcd(comm,Xaddr);//X地址
wr_lcd(dat,dp[k++]);//寫入數(shù)據(jù)
wr_lcd(dat,dp[k++]);
}
wr_lcd(comm,0x36);//打開繪圖顯示
//wr_lcd(comm,0x30);//回到基本指令集模式
}
5,向液晶全屏寫圖像的函數(shù)如下:
voidDraw_PM(constuchar*ptr)//整屏顯示圖形
{
uchari,j,k;
wr_lcd(comm,0x34);//打開擴(kuò)展指令集
i=0x80;
for(j=0;j<32;j++)
{
wr_lcd(comm,i++);
wr_lcd(comm,0x80);
for(k=0;k<16;k++)
{
wr_lcd(dat,*ptr++);//先寫入32*16個(gè)數(shù)據(jù)
}
}
i=0x80;
for(j=0;j<32;j++)
{
wr_lcd(comm,i++);
wr_lcd(comm,0x88);
for(k=0;k<16;k++)
{
wr_lcd(dat,*ptr++);//再寫入32*16個(gè)數(shù)據(jù)
}
}
wr_lcd(comm,0x36);//打開繪圖顯示
wr_lcd(comm,0x30);//回到基本指令集
}
6,下面我就貼上一個(gè)對(duì)液晶功能測(cè)試的函數(shù),其中用到了液晶的很多功能,可以有實(shí)現(xiàn)現(xiàn)象觀察得到,注釋的也較詳細(xì),代碼如下:
#include"msp430g2553.h"
#include"ser_12864.h"
voidmain(void)
{
uinti;
ucharlaba[]=//16*16大小圖形數(shù)據(jù)
{0x00,0x00,0x00,0xC0,0x01,0x48,0x02,0x44,0x04,0x52,0xF8,0x49,0x88,0x49,0x88,0x49,
0x88,0x49,0x88,0x49,0xF8,0x49,0x04,0x52,0x02,0x44,0x01,0x48,0x00,0xC0,0x00,0x00};
WDTCTL=WDTPW+WDTHOLD;//關(guān)狗
BCSCTL1=CALBC1_12MHZ;//設(shè)定cpu時(shí)鐘DCO頻率為12MHz
DCOCTL=CALDCO_12MHZ;
P2DIR|=BIT5+BIT4;//液晶的兩條線
init_lcd();//初始化液晶
//下面是顯示液晶字符表中的字符
wr_lcd(comm,0x80);//寫第一行的顯示地址寫命令0x80
for(i=0;i<16;i++)//每一行可以顯示16個(gè)字符
wr_lcd(dat,0x00+i);//顯示0x00~0x0f對(duì)應(yīng)的字符寫數(shù)據(jù)
wr_lcd(comm,0x90);//寫第二行的顯示地址因?yàn)?2864的13行和24行分別由控制器ST7920的兩行切割來(lái)的,為了看起來(lái)方便
//這里要手動(dòng)把地址切換到第二行。要不然的話,顯示完了第一行,液晶會(huì)自動(dòng)切換顯示到第三行上去
for(i=0;i<16;i++)
wr_lcd(dat,0x10+i);//顯示0x10~0x1f對(duì)應(yīng)的字符
wr_lcd(comm,0x88);//寫第三行的顯示地址
for(i=0;i<16;i++)
wr_lcd(dat,0x20+i);//顯示0x20~0x2f對(duì)應(yīng)的字符
wr_lcd(comm,0x98);//寫第四行的顯示地址
for(i=0;i<16;i++)
wr_lcd(dat,0x30+i);//顯示0x30~0x3f對(duì)應(yīng)的字符
//delay_ms(1000);//延遲1s,觀察效果
//調(diào)試時(shí),可以在此處設(shè)置斷點(diǎn),單步執(zhí)行下面的指令,觀察結(jié)果
//在顯示時(shí)DDAM和GDRAM是同時(shí)顯示的,也就是它們的顯示結(jié)果是疊加在一起的
//1.設(shè)定DDRAM地址命令
wr_lcd(comm,0x90);//設(shè)定DDRAM地址,因?yàn)榇藭r(shí)DDRAM地址已經(jīng)溢出
//2.顯示狀態(tài)命令
wr_lcd(comm,0x08);//整體顯示關(guān),游標(biāo)關(guān),游標(biāo)位置關(guān)
wr_lcd(comm,0x0c);//整體顯示開,游標(biāo)關(guān),游標(biāo)位置關(guān)
wr_lcd(comm,0x0e);//整體顯示開,游標(biāo)開,游標(biāo)位置關(guān)
wr_lcd(comm,0x0f);//整體顯示開,游標(biāo)開,游標(biāo)位置開游標(biāo)閃爍
//3.位址歸位
wr_lcd(comm,0x02);//位址歸位,游標(biāo)回到原點(diǎn)
wr_lcd(comm,0x84);//將DDRAM地址設(shè)為0x88,游標(biāo)在此閃爍
//4.點(diǎn)設(shè)定指令
//(以下四個(gè)命令是控制寫入字符以后光標(biāo)及整屏顯示的移動(dòng))
wr_lcd(comm,0x07);//光標(biāo)右移整體顯示左移
wr_lcd(comm,0x20);//寫入兩個(gè)空格
wr_lcd(dat,0x20);
wr_lcd(comm,0x05);//光標(biāo)左移整體顯示右移
wr_lcd(dat,0x20);//寫入兩個(gè)空格
wr_lcd(dat,0x20);
wr_lcd(comm,0x06);//光標(biāo)右移整體顯示不移動(dòng)
wr_lcd(dat,0x20);//寫入兩個(gè)空格
wr_lcd(dat,0x20);
wr_lcd(comm,0x04);//光標(biāo)左移整體顯示不移動(dòng)
wr_lcd(dat,0x20);//寫入兩個(gè)空格
wr_lcd(dat,0x20);
//5.游標(biāo)和顯示移位控制
//(以下四個(gè)命令無(wú)需寫入顯示數(shù)據(jù),直接控制光標(biāo)和整屏顯示的移動(dòng),上面執(zhí)行的命令是寫入空格實(shí)現(xiàn)光標(biāo)移動(dòng)和整屏的移動(dòng))
wr_lcd(comm,0x10);//光標(biāo)左移
wr_lcd(comm,0x14);//光標(biāo)右移
wr_lcd(comm,0x18);//整體顯示左移,光標(biāo)跟隨
wr_lcd(comm,0x1c);//整體顯示右移,光標(biāo)跟隨
wr_lcd(comm,0x0c);//關(guān)閉光標(biāo)
//6.進(jìn)入擴(kuò)展功能模式命令
wr_lcd(comm,0x34);//打開擴(kuò)展功能模式,繪圖顯示關(guān)閉
//7.反白命令
wr_lcd(comm,0x04);//同時(shí)反白1、3行
wr_lcd(comm,0x04);//再次反白1、3行,相當(dāng)于關(guān)閉1、3行反白
wr_lcd(comm,0x05);//同時(shí)反白2、4行
wr_lcd(comm,0x05);//再次反白2、4行,相當(dāng)于關(guān)閉2、4行反白
//8.睡眠模式命令
wr_lcd(comm,0x08);//進(jìn)入睡眠模式液晶的控制器ST7920關(guān)閉,降低功耗。但是背光還是亮的
wr_lcd(comm,0x0c);//退出睡眠模式繼續(xù)顯示
//9.待命模式命令
wr_lcd(comm,0x01);//進(jìn)入待命模式也是不顯示內(nèi)容的,液晶已經(jīng)準(zhǔn)備好接受數(shù)據(jù)或命令了
//10.打開GDRAM顯示//這樣打開GDRAM顯示,液晶的GDRAM和DDRAM會(huì)同時(shí)控制液晶的顯示
wr_lcd(comm,0x36);//打開擴(kuò)展功能模式,打開繪圖顯示由于上電后GDRAM中的數(shù)據(jù)是隨機(jī)的,所以如果在顯示之前不清除的話,會(huì)顯示亂碼
Draw_TX(0x80,0x84,laba);//顯示16*16大小圖形顯示上面定義的圖像,是一個(gè)小喇叭
Clear_GDRAM();//清除上電復(fù)位后GDRAM中的隨機(jī)數(shù)值,此時(shí)GDRAM顯示空字符,但是DDRAM中還是有數(shù)據(jù),所以此時(shí)會(huì)顯示DDRAM中的數(shù)據(jù)
Draw_TX(0x80,0x84,laba);//重新顯示設(shè)置16*16大小圖形
//11.關(guān)閉GDRAM顯示
wr_lcd(comm,0x34);//打開擴(kuò)展功能模式,關(guān)閉繪圖顯示顯示DDRAM中的數(shù)據(jù)
//12.設(shè)定基本指令集
wr_lcd(comm,0x30);//回到基本指令集
//13.清除顯示命令
wr_lcd(comm,0x01);//清屏只能清除DDRAM此時(shí)液晶就什么都不顯示了
//下面是顯示液晶字符表中的字符
wr_lcd(comm,0x80);//寫第一行的顯示地址
for(i=0;i<16;i++)
wr_lcd(dat,0x40+i);//顯示0x40~0x4f對(duì)應(yīng)的字符
wr_lcd(comm,0x90);//寫第二行的顯示地址
for(i=0;i<16;i++)
wr_lcd(dat,0x50+i);//顯示0x50~0x5f對(duì)應(yīng)的字符
wr_lcd(comm,0x88);//寫第三行的顯示地址
for(i=0;i<16;i++)
wr_lcd(dat,0x60+i);//顯示0x60~0x6f對(duì)應(yīng)的字符
wr_lcd(comm,0x98);//寫第二行的顯示地址
for(i=0;i<16;i++)
wr_lcd(dat,0x70+i);//顯示0x70~0x7f對(duì)應(yīng)的字符
LPM4;
}
評(píng)論