專注電子技術(shù)學(xué)習(xí)與研究
當(dāng)前位置:單片機(jī)教程網(wǎng) >> MCU設(shè)計(jì)實(shí)例 >> 瀏覽文章

12864-ST7920液晶繪圖的介紹

作者:佚名   來源:本站原創(chuàng)   點(diǎn)擊數(shù):  更新時(shí)間:2010年09月14日   【字體:

  基于ST7920控制的12864液晶用于字符顯示很方便的,但網(wǎng)友說用它顯示圖形并不合適,原因就是它繪圖時(shí)先要關(guān)


  閉顯示,繪完后又要打開,速度會(huì)較慢。我沒有用過別的液晶,手中只有這一款,擺弄了幾天,掌握了一點(diǎn)東西,

  寫出來共享。


首先,我們知道,圖形都是由像素點(diǎn)組成的,繪圖的基礎(chǔ)其實(shí)就是畫點(diǎn)。只要我們能點(diǎn)亮液晶的任意一個(gè)像素點(diǎn),那么繪圖就不是什么難事了。萬丈高樓平地起嘛,先要做的,當(dāng)然是要打好基礎(chǔ)。

ST7920提供了用于繪圖的GDRAM(graph display RAM)。共 64×32 個(gè)字節(jié)的空間(由擴(kuò)充指令設(shè)定繪圖 RAM 地址),最多可以控制 256×64點(diǎn)陣的二維繪圖緩沖空間。在它的Da

tasheet給出了GDRAM的坐標(biāo)地址對(duì)照表:

 
 

用坐標(biāo)表示,就是這樣:

 

它的橫坐標(biāo)每一個(gè)地址都是16 位的。共16個(gè)地址,256位。
很明顯,它能控制256*64像素的液晶屏,而我們的只是128*64像素液晶屏,顯然只用到它的一部分。
我剛開始以為它對(duì)應(yīng)屏幕的繪圖RAM是這樣分布的(如紅色部分):


結(jié)果栽了

 

大根頭,后來終于弄明白,原來它對(duì)應(yīng)屏幕的GDRAM是這樣分布的:


 

   只要我們清楚了它的GDRAM和屏幕上像素點(diǎn)的映射(對(duì)應(yīng))關(guān)系,點(diǎn)亮對(duì)應(yīng)的像素點(diǎn)就容易多了。要點(diǎn)亮某一個(gè)像素點(diǎn),就是將這個(gè)像素點(diǎn)在GDRAM中對(duì)應(yīng)的位置1,這個(gè)相信沒人會(huì)不知道吧?
我們先討論一下思路,再一步步寫代碼。我覺得,思路要比代碼重要的多,只要你的思路通了,正確了,那么寫出代碼肯定會(huì)很容易。
首先,給你x,y的坐標(biāo),要你點(diǎn)亮一個(gè)點(diǎn),要怎么做呢?從上面的圖我們知道,它是分為兩個(gè)半屏的,首先,我們要確定這個(gè)點(diǎn)是在上半屏還是下半屏,然后確定它是在那一行(縱坐標(biāo)Y),再確定它是在哪一個(gè)字節(jié)的哪一個(gè)位(也就是確定它在那一列,即橫坐標(biāo)X)。這些都確定后我們就定位到某一個(gè)具體的位上了,只就將這個(gè)位置1,就OK了。
下面我們邊寫代碼邊討論。
因?yàn)檫@里僅僅是討論如何在12864上打點(diǎn)的,而不是給12864寫一個(gè)驅(qū)動(dòng),所以對(duì)于基本的數(shù)據(jù)讀寫函數(shù),我們不做討論,這里假設(shè)已經(jīng)有了如下基本函數(shù):

 

1
 voidlcd_write_cmd(unsignedchar);  //lcd 命令寫
 
2
 voidlcd_write_data(unsignedchar); //lcd 數(shù)據(jù)寫
 
3
 unsigendcharlcd_read_data(void);  //lcd 數(shù)據(jù)讀
 


好了,就這些了。
為了方便,我們定義如下宏:



print?

1
 #define  BASIC_SET   0x00          //基本指令集,后面的數(shù)字查數(shù)據(jù)手冊(cè),下同。
 
2
 #define  EXTEND_SET  0x00           //擴(kuò)展指令集
 
3
 #define  DRAW_ON     0x00           //繪圖顯示開
 
4
 #define  DRAW_OFF    0x00           //繪圖顯示關(guān)
 


我們現(xiàn)在開始寫點(diǎn)亮某一個(gè)點(diǎn)的函數(shù):



print?

01
 voidlcd_set_dot(unsignedcharx, unsignedchary)
 
02
 {
 
03
   unsignedcharx_byet, x_bit;       //在橫坐標(biāo)的哪一個(gè)字節(jié),哪一個(gè)位
 
04
   unsignedchary_byte, y_bit;
 
05
   x_byte = x / 16;                   //算出它在哪一個(gè)字節(jié)(地址)
 
06
                                       //注意一個(gè)地址是16位的
 
07
   x_bit = x % 16;                    //算出它在哪一個(gè)位
 
08
   y_byte = y /32;                    //y是沒在哪個(gè)字節(jié)這個(gè)說法
 
09
                                       //這里只是確定它在上半屏還是下半屏
 
10
                                       //0:上半屏 1:下半屏
 
11
   y_bit = y % 32;                    //y_bit確定它是在第幾行
 
12
   lcd_write_cmd(EXTEND_SET);         //擴(kuò)展指令集
 
13
   lcd_write_cmd(DRAW_OFF);           //繪圖顯示關(guān)閉
 
14
   lcd_write_cmd(0x80 + y_bit);       //先寫垂直地址
 
15
                                       //具體參照數(shù)據(jù)手冊(cè)
 
16
   lcd_write_cmd(0x80 + x_byte + 8 * y_byte);  //水平坐標(biāo)
 
17
                                                //下半屏的水平坐標(biāo)起始地址為0x88
 
18
                                                //(+8*y_byte)就是用來確定在上半屏還是下半屏
 
19
   if(x_bit < 8)                              //如果x_bit位數(shù)小于8
 
20
   {
 
21
       lcd_write_data(0x01 << (7 - x_bit));    //寫高字節(jié)。因?yàn)樽鴺?biāo)是從左向右的
 
22
                                                //而GDRAM高位在左,底位在右
 
23
       lcd_write_data(0x00);                   //低字節(jié)全部填0
 
24
   }
 
25
   else
 
26
   {
 
27
       lcd_write_data(0x00);                   //高字節(jié)全部填0
 
28
       lcd_write_data(0x01 << (15 - x_bit));
 
29
   } 
 
30
   lcd_write_cmd(DRAW_ON);                    //打開繪圖顯示
 
31
   lcd_write_cmd(BASIC_SET);                  //回到基本指令集,畢竟ST7920是以字符為主的
 
32
   return;
 
33
 }


   基本畫點(diǎn)函數(shù)算是完成了,但是我們?nèi)绻褂眠@個(gè)函數(shù),就會(huì)發(fā)現(xiàn)問題。你且用它沿橫坐標(biāo)畫幾個(gè)連續(xù)的點(diǎn)試試,肯定不是你想要的結(jié)果。

   出現(xiàn)問題的原因是因?yàn)槲覀儺孅c(diǎn)時(shí)對(duì)其余的位全部填0處理了,造成對(duì)原來的信息的破壞。所以我們要讀出要寫的那個(gè)地址原來的數(shù)據(jù),再進(jìn)行加工,寫回去就可以解決問題了。

 
 畫點(diǎn)函數(shù)到此就完成了,剩下的事情就是對(duì)函數(shù)的優(yōu)化了。例如對(duì)入口參數(shù)的檢查,對(duì)乘除法的優(yōu)化等等。
 

關(guān)閉窗口

相關(guān)文章