久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 9702|回復(fù): 1
打印 上一主題 下一主題
收起左側(cè)

教你在12864上打點(基于ST7920控制器)

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:68618 發(fā)表于 2014-11-22 15:30 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
轉(zhuǎn)者注:AIHHLI 咚冬兄寫得比較生動,值得一讀;對其他的點陣屏的研究有很大的參考價值。
基于ST7920控制的12864液晶用于字符顯示很方便的,但網(wǎng)友說用它顯示圖形并不合適,原因就是它繪圖時先要關(guān)閉顯示,繪完后又要打開,速度會較慢。我沒有用過別的液晶,手中只有這一款,擺弄了幾天,掌握了一點東西,寫出來共享。
首先,我們知道,圖形都是由像素點組成的,繪圖的基礎(chǔ)其實就是畫點。只要我們能點亮液晶的任意一個像素點,那么繪圖就不是什么難事了。萬丈高樓平地起嘛,先要做的,當(dāng)然是要打好基礎(chǔ)。
ST7920提供了用于繪圖的GDRAM(graph display RAM)。共 64×32 個字節(jié)的空間(由擴充指令設(shè)定繪圖 RAM 地址),最多可以控制 256×64點陣的二維繪圖緩沖空間。在它的Datasheet給出了GDRAM的坐標(biāo)地址對照表:
用坐標(biāo)表示,就是這樣:
它的橫坐標(biāo)每一個地址都是16 位的。共16個地址,256位。
很明顯,它能控制256*64像素的液晶屏,而我們的只是128*64像素液晶屏,顯然只用到它的一部分。
我剛開始以為它對應(yīng)屏幕的繪圖RAM是這樣分布的(如紅色部分):
結(jié)果栽了大根頭,后來終于弄明白,原來它對應(yīng)屏幕的GDRAM是這樣分布的:
只要我們清楚了它的GDRAM和屏幕上像素點的映射(對應(yīng))關(guān)系,點亮對應(yīng)的像素點就容易多了。要點亮某一個像素點,就是將這個像素點在GDRAM中對應(yīng)的位置1,這個相信沒人會不知道吧?
我們先討論一下思路,再一步步寫代碼。我覺得,思路要比代碼重要的多,只要你的思路通了,正確了,那么寫出代碼肯定會很容易。
首先,給你x,y的坐標(biāo),要你點亮一個點,要怎么做呢?從上面的圖我們知道,它是分為兩個半屏的,首先,我們要確定這個點是在上半屏還是下半屏,然后確定它是在那一行(縱坐標(biāo)Y),再確定它是在哪一個字節(jié)的哪一個位(也就是確定它在那一列,即橫坐標(biāo)X)。這些都確定后我們就定位到某一個具體的位上了,只就將這個位置1,就OK了。
下面我們邊寫代碼邊討論。
因為這里僅僅是討論如何在12864上打點的,而不是給12864寫一個驅(qū)動,所以對于基本的數(shù)據(jù)讀寫函數(shù),我們不做討論,這里假設(shè)已經(jīng)有了如下基本函數(shù):
?
1
2
3
void lcd_write_cmd(unsigned char);   //lcd 命令寫
void lcd_write_data(unsigned char);  //lcd 數(shù)據(jù)寫
unsigend char lcd_read_data(void);   //lcd 數(shù)據(jù)讀

好了,就這些了。
為了方便,我們定義如下宏:
?
1
2
3
4
#define  BASIC_SET   0x00          //基本指令集,后面的數(shù)字查數(shù)據(jù)手冊,下同。
#define  EXTEND_SET  0x00           //擴展指令集
#define  DRAW_ON     0x00           //繪圖顯示開
#define  DRAW_OFF    0x00           //繪圖顯示關(guān)

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


基本畫點函數(shù)算是完成了,但是我們?nèi)绻褂眠@個函數(shù),就會發(fā)現(xiàn)問題。你且用它沿橫坐標(biāo)畫幾個連續(xù)的點試試,肯定不是你想要的結(jié)果。
出現(xiàn)問題的原因是因為我們畫點時對其余的位全部填0處理了,造成對原來的信息的破壞。所以我們要讀出要寫的那個地址原來的數(shù)據(jù),再進行加工,寫回去就可以解決問題了。
改進后的代碼:
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
void lcd_set_dot(unsigned char x, unsigned char y)
{
  unsigned char x_byet, x_bit;        //在橫坐標(biāo)的哪一個字節(jié),哪一個位
  unsigned char y_byte, y_bit;
  unsigned char tmph, tmpl;           //定義兩個臨時變量,用于存放讀出來的數(shù)據(jù)
  x &= 0x7F;
  y &= 0x3F;
  x_byte = x / 16;                    //算出它在哪一個字節(jié)(地址)
                                      //注意一個地址是16位的
  x_bit = x&0x0F;                     //算出它在哪一個位
  y_byte = y /32;                     //y是沒在哪個字節(jié)這個說法
                                      //這里只是確定它在上半屏還是下半屏
                                      //0:上半屏 1:下半屏
  y_bit = y&0x3F;                     //y_bit確定它是在第幾行
  lcd_write_cmd(EXTEND_SET);          //擴展指令集
  lcd_write_cmd(DRAW_OFF);            //繪圖顯示關(guān)閉
  lcd_write_cmd(0x80 + y_bit);        //先寫垂直地址(最高位必須為1)
                                      //具體參照數(shù)據(jù)手冊
  lcd_write_cmd(0x80 + x_byte + 8 * y_byte);   //水平坐標(biāo)
                                               //下半屏的水平坐標(biāo)起始地址為0x88
                                               //(+8*y_byte)就是用來確定
                                               //在上半屏還是下半屏
  lcd_read_data();                  //先空讀一次
  tmph = lcd_read_data();           //讀高位
  tmpl = lcd_read_data();
  lcd_write_cmd(0x80 + y_bit);       //讀操作會改變AC,所以重新設(shè)置一次
  lcd_write_cmd(0x80 + x_byte + 8 * y_byte);
  if (x_bit < 8)                             //如果x_bit位數(shù)小于8
  {
     lcd_write_data(tmph | (0x01 << (7 - x_bit)));  //寫高字節(jié)。因為坐標(biāo)是從左向右的
                                                    //而GDRAM高位在左,底位在右
      lcd_write_data(tmpl);                         //原數(shù)據(jù)送回
  }
  else
  {
      lcd_write_data(tmph);                         //原數(shù)據(jù)送回
      lcd_write_data(tmpl | (0x01 << (15 - x_bit)));
  }
  lcd_write_cmd(DRAW_ON);       //打開繪圖顯示
  lcd_write_cmd(BASIC_SET);     //回到基本指令集,畢竟ST7920是以字符為主的
  return ;
}


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

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏6 分享淘帖 頂1 踩
回復(fù)

使用道具 舉報

沙發(fā)
ID:71013 發(fā)表于 2014-12-24 14:33 | 只看該作者
謝謝分享
回復(fù)

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機教程網(wǎng)

快速回復(fù) 返回頂部 返回列表
主站蜘蛛池模板: 亚洲网站在线播放 | 成人视屏在线观看 | av大片在线| 久久久精品一区 | 99re| av中文字幕在线观看 | 亚洲精品综合 | 国产羞羞视频在线观看 | 日韩一区二区三区av | 综合久久国产 | 国产麻豆乱码精品一区二区三区 | 国产精品无码永久免费888 | 91高清在线观看 | 国产你懂的在线观看 | 亚洲一区在线日韩在线深爱 | 97色在线观看免费视频 | 国产最新网址 | 日韩有码一区 | 精品日韩一区二区 | 一区二区在线免费观看 | 久久久久久国产精品 | 成人在线 | 手机av在线 | 国产清纯白嫩初高生在线播放视频 | 欧美性猛交一区二区三区精品 | 97国产精品视频人人做人人爱 | 欧美日高清 | 免费在线国产视频 | 国产精品久久久久久久久久久久冷 | 91精品国产综合久久久久久丝袜 | 成人国产精品久久 | 精品一区二区三区四区五区 | 中文字幕av一区二区三区 | 天天干视频 | 6080亚洲精品一区二区 | 欧美簧片| 日韩精品久久 | 91视频导航 | 国产精品久久久久久久久大全 | 在线日韩中文字幕 | 狠狠综合久久av一区二区小说 |