|
|
要學(xué)習(xí)LCD12864的可以參考一下。
12864液晶學(xué)習(xí)筆記
這是我對(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)略一些。
其 中的不管串行模式還是并行模式,對(duì)液晶的寫指令,寫數(shù)據(jù),讀操作等這些基本的操作都是一些比較固定的,基礎(chǔ)的東西。我認(rèn)為只要能夠看懂,并且能夠在不同的 處理器上移植就夠了,沒(méi)有必要非要自己對(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)行開(kāi)發(fā)應(yīng)用的研究。我們不必一定要從底層開(kāi)始把別人已經(jīng)做的很成熟的東西 再做一遍,這樣不但效率不高,而且我們一般人的精力也不允許。
好了,不說(shuō)廢話了,下面就開(kāi)始介紹,當(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)。可與CPU 直接接口,提供兩種界面來(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的其中兩行拆分開(kāi)成四行,然后在lcd上顯示,也即是DDRAM只用到了一半。
lcd的顯示字符的坐標(biāo)地址如下表:
漢字顯示坐標(biāo)
Line1 80H 81H 82H 83H 84H 85H 86H 87H
Line2 90H 91H 92H 93H 94H 95H 96H 97H
Line3 88H 89H 8AH 8BH 8CH 8DH 8EH 8FH
Line4 98H 99H 9AH 9BH 9CH 9DH 9EH 9FH
從上表不難看出,其中第一行和第三行是DDRAM中的同一行拆分來(lái)的,同理2 4 行也是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是打開(kāi)的,控制液晶顯示。GDRAM默認(rèn)不打開(kāi),它里面的數(shù)據(jù)是隨機(jī)的,如果此時(shí)打開(kāi)了GDRAM的話,lcd會(huì)同時(shí)受到DDRAM和GDRAM的控制,由于GDRAM中的數(shù)據(jù)是隨機(jī)的,所以會(huì)顯示亂碼。所以在使用GDRAM之前要先清除里面的隨機(jī)數(shù)據(jù)。
清除GDRAM的函數(shù)如下:
void Clear_GDRAM(void) //清除GDRAM中的的隨機(jī)數(shù)據(jù)。因?yàn)樯想姾驡DRAM中的數(shù)據(jù)是隨機(jī)的,如果不清除而直接打開(kāi)GDRAM顯示時(shí),會(huì)顯示亂碼
//所以在局部使用GDRAM顯示圖形時(shí),要先清除隨機(jī)數(shù)據(jù)。如果是全局使用GDRAM,即整個(gè)lcd屏全部設(shè)置顯示數(shù)據(jù),則可以
//不必清除,因?yàn)樾聰?shù)據(jù)會(huì)把隨機(jī)數(shù)據(jù)給覆蓋掉
{
uchar i,j,k;
wr_lcd(comm,0x34); //打開(kāi)擴(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ù)如下:
void Write_Cmd(uchar cmd)
{
uchar lcdtemp = 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;
}
void Write_Data(uchar dat)
{
uchar lcdtemp = 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),串行模式只用到了兩根線WR EN于單片機(jī)進(jìn)行通信。這種方式可以大大減少單片機(jī)IO口的開(kāi)銷,適用于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;
}
}
}
void Draw_TX(uchar Yaddr,uchar Xaddr,const uchar * dp)
{
uchar j;
uchar k=0;
// wr_lcd(comm,0x01); //清屏,只能清除DDRAM
wr_lcd(comm,0x34); //使用擴(kuò)展指令集,關(guān)閉繪圖顯示 打開(kāi)擴(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); //打開(kāi)繪圖顯示
// wr_lcd(comm,0x30); //回到基本指令集模式
}
5,向液晶全屏寫圖像的函數(shù)如下:
void Draw_PM(const uchar *ptr) //整屏顯示圖形
{
uchar i,j,k;
wr_lcd(comm,0x34); //打開(kāi)擴(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); //打開(kāi)繪圖顯示
wr_lcd(comm,0x30); //回到基本指令集
}
6,下面我就貼上一個(gè)對(duì)液晶功能測(cè)試的函數(shù),其中用到了液晶的很多功能,可以有實(shí)現(xiàn)現(xiàn)象觀察得到,注釋的也較詳細(xì),代碼如下:
#include "msp430g2553.h"
#include "ser_12864.h"
void main( void )
{
uint i;
uchar laba[]= //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的1 3行和2 4行分別由控制器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); //整體顯示開(kāi),游標(biāo)關(guān),游標(biāo)位置關(guān)
wr_lcd(comm,0x0e); //整體顯示開(kāi),游標(biāo)開(kāi),游標(biāo)位置關(guān)
wr_lcd(comm,0x0f); //整體顯示開(kāi),游標(biāo)開(kāi),游標(biāo)位置開(kāi) 游標(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); //打開(kāi)擴(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.打開(kāi)GDRAM顯示 //這樣打開(kāi)GDRAM顯示,液晶的GDRAM和DDRAM會(huì)同時(shí)控制液晶的顯示
wr_lcd(comm,0x36); //打開(kāi)擴(kuò)展功能模式,打開(kāi)繪圖顯示 由于上電后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); //打開(kāi)擴(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;
}
以上全部資料51hei下載地址:
12864學(xué)習(xí)筆記及常用指令.zip
(28.44 KB, 下載次數(shù): 66)
2020-3-30 00:02 上傳
點(diǎn)擊文件名下載附件
|
評(píng)分
-
查看全部評(píng)分
|