產(chǎn)品動態(tài)
- G270QAN01.4 友達27寸 400 cd/m2 分辨率25
- G190ETT01.1 友達19寸 分辨率1280*1024 常白
- 18.5寸G185HAT01.1 友達 對比度1000:1 分辨
- 友達G101EAT02.6 10.1寸 分辨率1280*800 對比
- G156HAN02.303 友達15.6寸 對比度1000:1 霧面
- G057QAN01.1 友達5.7寸 常黑顯示 1000:1 分
- G238HAN04.0 友達23.8寸 常黑顯示 分辨率
- 友達8.4寸 G084SAN01.0 常黑顯示 分辨率
- G057QAN01.0 友達 5.7寸 500 cd/m2 常黑顯示
- G057QAN01.0 友達 5.7寸 500 cd/m2 常黑顯示

全國統(tǒng)一服務(wù)熱線:
15382323032
客服QQ:3234659108
手機:15382323032
地址:浙江省杭州市余杭區(qū)五常街道西溪軟件園金牛座B2座4層4118-4119
在點陣屏上面繪圖—LCD12864控制的詳解
怎樣在點陣屏上繪圖——基于LCD12864
LCD12864:
— 預(yù)備知識 —
其實,本文應(yīng)該算是計算機圖形學中的一個具體分支,所以,計算機圖形學的最基本要求就是本文的基本要求了,由于考慮到各位大兄弟的胃口,我就多啰嗦下。
1、位操作
像LCD12864這一種二值屏幕,我們往往習慣于使用1個字節(jié)表示連續(xù)的8個點,1對應(yīng)的對應(yīng)位被點亮,0則表示不亮,所以對于圖形的操作最基本的手段那就是位操作了。
復(fù)習一下常用的位操作,假設(shè)Dis表示是某一個現(xiàn)存地址的內(nèi)容
Dis = Dis~ 黑白顛倒
Dis &= ~(1<<n) 第n處被擦去,
Dis |= (1<<n) 第n處被畫了一個點
Dis ^= (1<<n) 如果n處是亮的,就變被擦掉;如果n處是空白的,就被點亮了……
…… 差不多也就是這些
2、作圖的原理
點是一切光柵顯示設(shè)備最基本的要素,所有的操作也都是以點為基礎(chǔ)的,所以要學會如何去利用點構(gòu)成線、圓、填充就是必須要掌握的——幾何不能夠太差。
還有,結(jié)合屏幕硬件的特點,對于算法進行優(yōu)化的一些方法也是需要去掌握的。比方說:如何填充之類的……后面還會針對于LCD12864來作詳細的介紹。
3、人機交互學
雖然說很多的人都沒有去實實在在的學過這門功課,但是多多少少還是對于界面應(yīng)該都有些許了解。如何去利用手中的基本操作函數(shù)來做出一些特效?如何安排窗體?如何繪制圖形界面的一些基本元素,例如按鈕,
甚至如何的顯示漢字,都是人際交互學需要教會你的——總而言之,如果你是沒有學過這一門課程,你的產(chǎn)品 只有你自己一個人用的話——那就跟著感覺走,沒錯的。
4、最最重要的物質(zhì)基礎(chǔ)
你需要掌握一種單片機,掌握到一種點陣屏幕。
怎樣在點陣屏上繪圖——基于LCD12864
Chapter One
— 從點滴開始 —
前面就已經(jīng)說過了,對于柵格的顯示設(shè)備來說,點是一切圖形的基礎(chǔ),說白了,不會在液晶屏幕的任意位置隨心所欲的畫點就不能夠說你已經(jīng)掌握了某一種液晶屏幕的使用了。事實上,根據(jù)筆者的一些經(jīng)驗,嘗試畫點
往往就能暴露出很多的問題。就拿LCD12864來說,一段時間,筆者經(jīng)常發(fā)現(xiàn),在片切換的地方就會有一點點錯誤……
在說明如何畫點之前我先說明一個概念:顯示緩沖區(qū)。
所謂的顯示緩沖區(qū),顧名思義,它就是顯示數(shù)據(jù)的一個緩沖地帶罷了。在一般情況下,我們繪圖也是直接的對
這塊緩沖區(qū)域進行操作。
很多朋友現(xiàn)在就要提問了:我們?yōu)槭裁床恢苯拥膶ζ聊贿M行操作呢?
事實上,LCD本身就存在著一塊顯示存儲器,也可以被認為是一個顯示緩存,直接寫在這個存儲器上的數(shù)據(jù)并非是直接顯示出來的,而多半是需要一個顯示指令來影射一下。我們有的時候也會通過這種類似的技術(shù)來實現(xiàn)很大的圖片顯示——先畫好,然后再拿給大家看,讓人以為你是一下就畫好了的,當然如果你刻意的需要那種圖片被“畫”出來的效果,則不在討論之列了。問題就在于,LCD是片外的資源,對其存儲器的訪問可以被認為是對片外存儲器的訪問,其速度顯然是沒有對片內(nèi)SRAM的操作速度快。如果我們使用的是那種常用的串行方式來作圖(所謂串行方式作圖,就是繪圖指令的執(zhí)行和系統(tǒng)的其他操作是串行的,指令不完成,其它的操作就不會被執(zhí)行),那么對于一些實時性要求比較高的系統(tǒng)來說就會造成一些重大的隱患——甚至是不符合要求的;如果開辟一段片內(nèi)存儲空間和LCD的存儲器一一對應(yīng),在相同的時間段之內(nèi),花費相同的資源來保持這兩個存儲空間的一致性,那么就可以保證實時系統(tǒng)的穩(wěn)定和可靠了,保證畫面顯示的正常(因為允許跳幀嘛^_^ )。這就是我們?yōu)槭裁催€需要另外在片內(nèi)選取一個顯示緩沖區(qū)的原因了。
以后,我們的操作都是針對于顯示緩沖區(qū)的。顯示緩沖區(qū)將會成為一個概念,無論這個緩沖區(qū)位于SRAM內(nèi)還是LCD的內(nèi)部。比方說,我們現(xiàn)在需要一個低成本的游戲機 ——比如做一個貪食蛇游戲機送給老師作為課程設(shè)計,或者是送給小侄子,那么,M8甚至是M48將會成為首選,問題是,M8是絕對無法開辟出一個8 * 128 = 1K大小的數(shù)組,所以,在這個時候,認定LCD的片內(nèi)存儲器作為顯示緩沖區(qū)就是不二的選擇——好在貪食蛇的速度太快了也沒有辦法玩哈。
繞了這么多的彎子,究竟如何去畫點呢?我還想多補充一個原因,關(guān)于,為什么需要顯示緩沖區(qū),由于點陣屏使用的是1個字節(jié)來表示8個點的,如果你想使得其中一個字節(jié)中的某一個點被操作而不影響到別的點,你起碼要知道原來這個位置是顯示的什么內(nèi)容,對于有一些使用595級聯(lián)的LCD設(shè)備來說,無法直接從LCD讀取現(xiàn)存的數(shù)據(jù),所以開辟了一個緩沖區(qū),從中獲得信息加以加工以后再放回去,是這種設(shè)備處理顯示圖形的唯一方法——當然我們還沒有那么慘,但是從LCD中獲取所需點所在字節(jié)的內(nèi)容還是必須的,不然你畫一個點就會破壞其一條線上所有的數(shù)據(jù)。
好的,那么我們實際上已經(jīng)明確了如何去畫一個點。
首先,根據(jù)用戶給出的坐標計算出所要畫的點所在現(xiàn)存內(nèi)的地址偏移量;
然后,我們讀出該地址內(nèi)的數(shù)據(jù);
再次,根據(jù)用戶所需畫點的類型(擦除、畫點、反相點)來進行相應(yīng)的操作獲得一個新的數(shù)據(jù);
最后,將該數(shù)據(jù)寫回原來的地址。
不是很難吧?
---------------------------------------------
LCD12864補充知識
1、關(guān)于坐標系。很多人,包括筆者,一開始都看不懂LCD12864的內(nèi)存影射方式,感覺X、Y似乎不是那么回事。后來才發(fā)現(xiàn),只要把屏幕豎著放一切就好懂了。X還是橫軸,Y還是豎軸……但是這顯然不符合我們的習慣,我們習慣于長的那個邊作為橫軸,所以需要一點點坐標之間的轉(zhuǎn)換。
假設(shè)輸入的是正常習慣的坐標 X,Y DX DY就是LCD上的坐標,那么轉(zhuǎn)換關(guān)系是
char DX = (Y >> 3); //計算出屬于哪個字節(jié)
char BX = Y - (DX << 3); //屬于該字節(jié)的哪個位
char DY = X;
2、讀取12864的數(shù)據(jù)的時候,一定要注意,E信號要在一個下降延之后持續(xù)拉高,然后才能正常獨處數(shù)據(jù);假設(shè)直接拉高,的確也能讀出數(shù)據(jù),但是,等著抓頭皮,發(fā)帖子“[跪求]大俠幫忙關(guān)于12864——請使用明確的大標題……”^_^
---------------------------------------------
廢話少說(說的不少了),看源代碼:
# define LCD12864_Graphic_Draw 0x01
# define LCD12864_Graphic_Clear 0x00
# define LCD12864_Graphic_Not 0x02
……
void LCD12864Draw(char X,char Y,char Type)
{
char DX = (Y >> 3); //計算出屬于哪個字節(jié)
char BX = Y - (DX << 3); //計算出屬于字節(jié)哪一位
char TempData = 0;
LCD12864_ChooseBoth;
setX(DX);
if (X > 63)
{
LCD12864_ChooseCS2;
X -= 64;
}
else
{
LCD12864_ChooseCS1;
}
setY(X);
TempData = getLCD12864Data();
switch (Type)
{
case LCD12864_Graphic_Clear:
TempData &= ~(1<<BX);
break;
case LCD12864_Graphic_Not:
TempData ^= (1 << BX);
break;
default:
TempData |= (1 << BX);
}
setY(X);
sendDataToLCD(TempData);
}
怎樣在點陣屏上繪圖——基于LCD12864
特別說明一下,關(guān)于貪食蛇范例的問題,這篇文章里面只會簡單得提及一下。
作為嵌入式系統(tǒng)開發(fā)的一個范例,我會另外開一個帖子詳細說明開發(fā)過程。
這個范例將作為介紹嵌入式系統(tǒng)開發(fā)方法的一個很好的例子,用于解釋一個系統(tǒng)和一段表示您調(diào)通了某一個功能的代碼之間有什么區(qū)別,同時也將介紹嵌入式開發(fā)系統(tǒng)的幾種模式(超級循環(huán)、調(diào)度器),順便侃一侃時間驅(qū)動的系統(tǒng)RTOS (Real Time Operation System實時操作系統(tǒng))和RTS(Real Time System)實時系統(tǒng)。
怎樣在點陣屏上繪圖——基于LCD12864
[本章導讀]
直線由點構(gòu)成,更精確的說,直線是由靠近這條線的像素構(gòu)成。這就引出一個問題,究近那些點算是靠近一條直線;哪些點不算是靠近一條直線,這必須使用一種算法作為依據(jù)。實際上,圖形學算法和純幾何算法還是有很大差別的,問題就出在一個離散化上面,說白了,你畫出的直線很可能是一組波動厲害的鋸齒象素群而不是一條看起來有規(guī)則變化的直線。
當然,太過于理論的東西對我們是沒有多少實際價值的。下面,我就介紹兩種常見的畫線思路,一種就是最容易被想到的直線方程計算的方法,另外一種則是被稱為布蘭森漢姆(Bresenham)的計算機圖形學主流算法。
在介紹完這兩種算法以后,我們會針對LCD12864的硬件結(jié)構(gòu)為例子,介紹,具體算法的實現(xiàn)和優(yōu)化。
怎樣在點陣屏上繪圖——基于LCD12864
首先,我們從最基本的數(shù)學算法說起。
如果我們使用公式y(tǒng) = kx + b來作為繪圖的依據(jù),那么就需要分3種情況:水平直線,斜率為0;垂直直線,斜率為五窮達(或者說k不存在);普通直線。
假設(shè)我們已經(jīng)知道直線的起始坐標點(Xbegin,Ybegin)和終點(Xend,Yend),x,y,是當前的坐標點,如果我們通過增加x反算出y的方法的話,這個公式就可以很容易轉(zhuǎn)換為偽代碼。
LineMode 為直線的類型:水平,垂直,普通
if Xbegin == Xend then LineMode = 水平
elseif Ybegin = Yend then LineMode = 垂直
else k = (Yend - Ybegin) / (Xend - Xbegin)
switch LineMode
case 水平
for x = Xbegin to Xend
在x,Ybegin處畫點
case 垂直
for y = Ybegin to Yend
在Ebegin,y處畫點
default:
for x = Xbegin to Xend
{
y = kx + b
在x,y處畫點
}
非常簡單,不是么?注意,大部分情況下,這個算法存在很多乘法和除法,對單片機系統(tǒng)來說,可能不是那么合適哦。畫出的點也基本令人滿意。
怎樣在點陣屏上繪圖——基于LCD12864
有了上面的代碼墊底,我想很多人都可以放心了,因為大不了跑一個高速晶振也能快速的畫出直線,否則你還需要耐心的閱讀下面的算法。
首先,我們給出這個算法的偽代碼。
在(x1,y1)到(x2,y2)之間畫一條直線
dx 是x到終點橫坐標的距離
dy 是y到終點縱坐標的距離
ix 是dx的絕對值
iy 是dy的絕對值
inc是dx和dy中較大的那個
plot是是否要畫一個點的標志位,boolean變量
plotx 是當前點所在的橫坐標
ploty 是當前點所在的縱坐標
plotx = x1
ploty = y1
x = 0
y = 0
在 plotx,ploty畫一個點——起點
for i = 0 to inc 增量1
x += ix
y += iy
plot = false
if x > inc then
plot = true
x -= inc
if dx > 0 then plotx ++
if dx < 0 then plotx --
if y > inc then
plot = true
y -= inc
if dy > 0 then ploty ++
if dy < 0 then ploty --
if plot == true then 在(plotx,ploty)處畫點
這就是計算機圖形學中流行的布蘭森漢姆(Bresenham)算法,他的意圖就是采用離散的整數(shù)增量來代替斜率增量計算,學習這個算法,最好的方法不是看多少理論,而是按照上面的偽代碼自己完成一條直線的繪制工作,你就能心領(lǐng)神會了——不是小弟我偷懶。
所有的計算都是簡單得整數(shù)計算,代碼效率自然不用小弟我羅嗦哈。
怎樣在點陣屏上繪圖——基于LCD12864
俗語說,巧婦難為無米之炊,有了點再有了直線算法,距離窗體的繪制不遠了,But Stop! “沒有最好,但求更好”這是我們做系統(tǒng)開發(fā)應(yīng)該謹記的一條準則。
有了上面的算法還不夠,畢竟,他們只是一些偽代碼,針對不同的屏幕——準確地說,是針對不同的顯存映射方式,有不同的算法優(yōu)化方法。究竟有哪些優(yōu)化方法暫且不論,其實他們都是一個原理,我想先解釋一下,為什么我們需要優(yōu)化算法,或者說,我們需要先弄清楚是什么地方產(chǎn)生了冗余。
還記得黑白點陣屏幕的顯存映射方式么?它簡單的使用1個字節(jié)表示8個坐標點,同時這1個字節(jié)是沿著屏幕的短邊方向映射的,所以當我們想畫一條垂直的直線時,對于每一個牽涉到的字節(jié)都有可能要重復(fù)的操作8次之多,這種操作不是簡單的畫線,而是要先讀取再計算最后再寫這樣的復(fù)合操作,重復(fù)8次只是為了把整個字節(jié)變黑顯然是一種超級不可容忍的冗余——大家都知道,直接把這個字節(jié)讀取一次,計算一次,再寫一次就完成了。基于這種思想,我們需要把這種特殊情況單獨提取出來,重新優(yōu)化代碼……具體優(yōu)化代碼就留給大家做作業(yè)了哈。
同時補充一下,這樣做,不是只對畫線作了優(yōu)化,事實上,在后面,矩形的填充里面,這種優(yōu)化會極大地提高速度,因為填充的本質(zhì)就是畫線(點)……
最新資訊
- 2025-03-05 關(guān)于工業(yè)液晶屏寬溫操作的介紹
- 2025-03-03 關(guān)于工業(yè)液晶屏觸摸技術(shù)的分析
- 2025-02-27 工業(yè)液晶屏高分辨率的優(yōu)勢與應(yīng)用
- 2025-02-25 高亮液晶屏在惡劣光照條件下的穩(wěn)定
- 2025-02-21 工業(yè)液晶屏的定制化需求
- 2025-02-12 工業(yè)液晶屏的響應(yīng)時間與動態(tài)顯示性
- 2025-02-10 工業(yè)液晶屏的接口類型及其兼容性分
- 2025-02-08 如何從參數(shù)到性能讀懂工業(yè)液晶屏的
- 2025-02-06 工業(yè)液晶屏的切割技術(shù)是探索屏幕制
- 2025-01-21 工業(yè)液晶屏之高分辨率LCD屏的深度解