




版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
1、.12864學習(控制器ST7920)在學習12864其他功能前先學習一下12864的幾個基本函數void delay(uint x)/延時函數x=x*12;while(x-)_nop_();/包含在intrins.h頭文件_nop_();_nop_();void write_lcd_cmd(uchar cmd)/寫命令RS=0;RW=0;EN=1;P0=cmd;/delay(1);EN=0;delay(1);void write_lcd_date(uchar date)/寫數據函數RS=1;RW=0;EN=1;P0=date;/delay(1);EN=0;delay(1);void disp
2、lay_pos(uchar x,uchar y)/設置顯示地址,用于顯示中文字時設計顯示地址uchar pos;switch(x)case 0:pos=0x80;break;/當x為0指向第一行case 1:pos=0x90;break;/當x為1指向第二行case 2:pos=0x88;break;/當x為2指向第三行case 3:pos=0x98;break;/當x為3指向第四行default:pos=0x80; /x為其它值時指向第一行pos=pos+y;write_lcd_cmd(pos);/*=函數功能:讀取12864液晶繁忙標志BF位狀態BF=1繁忙,BF=0不忙注意:與讀取數據不
3、同讀取繁忙標志位是是屬于寫指令,要將RS置低=*/void read_lcd_bf()uchar BF=1;P0=0xff;doRS=0;RW=1;EN=0;EN=1;_nop_();BF=P0;BF=BF>>7;while(BF);12864顯示圖片要讓一個點有顯示就要讓相應的點置高電平。要想知道如何控制一個點的高低電平就要知道它的地址是怎樣排列的。我們看著12864液晶是連在一起的一塊屏幕,就會想當然的認為它的地址也是一直地增的,但是你錯了。12864是分為上下兩個半屏的。12864液晶模塊顯示地址如圖所示。注意:12864顯示分為上下兩屏,而不是一個整屏。什么意思呢?就是說它
4、的地址是分成兩大部分(既上下兩大部分)。如圖,上半屏的水平地址X是從0x800x87并且它的每個水平地址都包含了十六個點的顯示區(如圖紅色標注)。下半屏水平地址是從0x880x8f,而上下半屏的縱坐標Y都是從031。這個是我定義的坐標關系簡圖坐標對應關系簡圖向12864 GDROM寫如數據來繪圖的過程:1、關閉繪圖顯示功能2、先打開擴充指令功能3、連續寫入X坐標地址,和y坐標地址(說明書上是寫著先寫X在寫y坐標,但是程序是卻是先寫Y再寫X坐標,否則會出錯。還有這里寫地址使用寫命令函數不是用寫數據函數)4、向GDROM 中寫入數據5、打開繪圖顯示功能/*=函數功能:清除GDROM的內容,如果不清
5、除會出現花屏現象清除方法:向GDROM中寫入0x00來清除內容=*/void clear_gcrom()uchar i,j,k,lcd_x,lcd_y;lcd_x=0x80;lcd_y=0x80;write_lcd_cmd(0x34);/打開擴充指令關閉繪圖顯示(繪圖指令為擴充指令,并且在繪圖期間必須關閉繪圖顯示功能)for(i=0;i<2;i+)/分為上下兩半屏清除顯示for(j=0;j<32;j+)write_lcd_cmd(lcd_y+j);write_lcd_cmd(lcd_x);for(k=0;k<16;k+)write_lcd_date(0x00);lcd_x=0
6、x88;/將x指向下半屏write_lcd_cmd(0x36);/打開繪圖指令write_lcd_cmd(0x30);/操作恢復為常用指令/*=函數功能:向12864中寫入一幅圖片函數參數:*p為指向圖片數據的指針lcd_x為水平顯示位置,lcd_y為垂直顯示位置,函數將12864屏分成上下兩屏寫入,上半屏LCD_x=0x80,下半屏lcd_x=0x88=*/void write_image(uchar *p)uchar i,j,k,lcd_x,lcd_y;lcd_x=0x80;lcd_y=0x80;write_lcd_cmd(0x34);/打開擴充功能for(i=0;i<2;i+)/分
7、為上下兩屏for(j=0;j<32;j+)write_lcd_cmd(lcd_y+j);write_lcd_cmd(lcd_x);for(k=0;k<16;k+)/寫入顯示數據write_lcd_date(*p+);lcd_x=0x88;/將x地址指向下半屏write_lcd_cmd(0x36);/打開繪圖功能write_lcd_cmd(0x30);/操作恢復為常用指令12864畫圖功能如果你想在液晶上顯示幾條線的話用上面的畫圖方法可以實現,但是要畫一條任意直線,而且還要讓直線可以變化的話用上面的方法肯定不是最好的方法,因為你每一條線的數據都要事先保存起來,再調用。先不說程序存儲空
8、間會不夠用,更重要的是相當麻煩。你是不是也想只要一種方法只要給出直線的起始和終點坐標就可以畫出一條直線來呢?在學習畫直線之前我們先來往12864任意點上畫一個點。畫一點很簡單只要將相應點置高電平就可以了。注意在12864液晶相應點上畫一點,在向12864中畫點時先要讀取出該地址上的數據,再在讀取到的數據中加入該點的數據,如果不先讀取如果以前那個地址就有顯示的數據時,可能就會破壞那個地址的顯示/*=函數功能;讀取12864數據注意:讀取數據時是在RS=1、RW=1、EN=1期間進行的。讀數據一定要在EN為高電平期間進行。還有就是不要想當然的認為讀數據指令要將RS置低,恰恰相反要將RS置高。=*/
9、uchar read_lcd_date()uchar date;P0=0xff;RS=1;RW=1;EN=0;EN=1;date=P0;_nop_();EN=0;return date;/*=函數功能:在12864液晶相應點上畫一點,在向12864中畫點時先要讀取出該地址上的數據,再在讀取到的數據中加入該點的數據,如果不先讀取如果以前那個地址就有顯示的數據時,可能就會破壞那個地址的顯示參數功能說明:x為水平方向上的坐標,y為垂直方向的坐標,color為所畫點的顏色,0畫白點,1畫黑點,2使相應位顏色取反read_H,read_L分別用來保存從12864中讀取到數據的高低字節數據=*/void
10、write_dian(uchar x,uchar y,uchar color)uchar x_locate,y_locate;uchar x_bit;uchar read_H,read_L;x_locate=x/16;/求出要顯示點在具體的哪一個地址上x_bit=x%16;/求出要顯示點在具體在地址的哪一位上if(y<32)/說明在屏的上半屏y_locate=y;elsey_locate=y-32;x_locate=x_locate+8;/將x_locate指向下半屏write_lcd_cmd(0x34);/寫擴充命令write_lcd_cmd(y_locate+0x80);/寫垂直方向
11、地址write_lcd_cmd(x_locate+0x80);/寫水平方向的地址read_lcd_bf();read_lcd_date();/空讀一次12864的數據(一定要空讀一次否則會出錯)至于為什么要空讀我也不是很清楚read_H=read_lcd_date();/連續讀取相應地址高低字節的數據read_L=read_lcd_date();if(x_bit<8)/判斷x地址數據是在高字節還是低字節,x_bit<8在高字節/為什么在高字節,應為地址為從左到右switch(color)case 0:read_H&=(0x01<<(7-x_bit);break;
12、case 1:read_H|=(0x01<<(7-x_bit);break;case 2:read_H=(0x01<<(7-x_bit);break;default:break;write_lcd_cmd(y_locate+0x80);write_lcd_cmd(x_locate+0x80);write_lcd_date(read_H);write_lcd_date(read_L);elseswitch(color)case 0:read_L&=(0x01<<(15-x_bit);break;case 1:read_L|=(0x01<<(
13、15-x_bit);break;case 2:read_L=(0x01<<(15-x_bit);break;default:break;write_lcd_cmd(y_locate+0x80);write_lcd_cmd(x_locate+0x80);write_lcd_date(read_H);write_lcd_date(read_L);write_lcd_cmd(0x36);write_lcd_cmd(0x30); 到這里畫點函數就結束了,在現在我們來應用畫點函數向12864里面畫垂直和水平直線,利用畫點函數就很好實現的,只要將直線所在水平線或垂直線上的點全部置成高電平就可以
14、了。/*=函數功能:畫水平直線參數說明:x0為水平線起始點,x1為水平直線終止點,y圖畫在第幾行color為 0時為白線, 為1時為黑線,2時取反該直線上的點=*/void write_x_line(uchar x0,uchar x1,uchar y,uchar color)uchar temp;if(x0>x1)/當X0在X1后面時將X1作為起始點temp=x0;x0=x1;x1=temp;for( ;x0<x1;x0+)write_dian(x0,y,color);/*=函數功能:畫垂線參數說明:y0 為起始點 y1為結束點,x為所在第幾列 ,color同上為顏色選擇=*/vo
15、id write_y_line(uchar x,uchar y0,uchar y1,uchar color)uchar temp;if(y0>y1)/當y0在X1后面時將y1作為起始點temp=y0;y0=y1;y1=temp;for( ;y0<y1;y0+)write_dian(x,y0,color);到這里我相信你以經可以靈活的畫出直線和垂線了吧。在畫直線之前先來學習一下直線的基本畫法原理。在這里使用Bresenham算法。下面是我找到得幾種直線畫法的原理。由直線的斜率確定選擇在x方向或y方向上每次遞增(減)1個單位,另一變量的遞增(減)量為0或1,它取決于實際直線與最近光柵網
16、格點的距離,這個距離的最大誤差為0.5。假定直線斜率k在01之間。此時,只需考慮x方向每次遞增1個單位,決定y方向每次遞增0或1。 設 直線當前點為(xi,y) 直線當前光柵點為(xi,yi)則 下一個直線的點應為(xi+1,y+k) 下一個直線的光柵點 或為右光柵點(xi+1,yi)(y方向遞增量0) 或為右上光柵點(xi+1,yi+1)(y方向遞增量1)記直線與它垂直方向最近的下光柵點的誤差為d,有:d=(y+k)yi,且 0d1 當d<0.5:下一個象素應取右光柵點(xi+1,yi) 當d0.5:下一個象素應取右上光柵點(xi+1,yi+1)如果直線的(起)端點在整數點上,誤差項d
17、的初值:d00,x坐標每增加1,d的值相應遞增直線的斜率值k,即:dd + k。一旦d1,就把它減去1,保證d的相對性,且在0-1之間。令e=d-0.5,關于d的判別式和初值可簡化成: e的初值e0= -0.5,增量亦為k; e<0時,取當前象素(xi,yi)的右方象素(xi+1,yi); e>0時,取當前象素(xi,yi)的右上方象素(xi+1,yi+1); e=0時,可任取上、下光柵點顯示。Bresenham算法的構思巧妙:它引入動態誤差e,當x方向每次遞增1個單位,可根據e的符號決定y方向每次遞增 0 或 1。 e<0,y方向不遞增 e>0,y方向遞增1 x方向每
18、次遞增1個單位,e = e + k因為e是相對量,所以當e>0時,表明e的計值將進入下一個參考點(上升一個光柵點),此時須:e = e - 1通過(0,0)的所求直線的斜率大于0.5,它與x=1直線的交點離y=1直線較近,離y=0直線較遠,因此取光柵點(1,1)比(1,0)更逼近直線;如果斜率小于0.5,則反之;當斜率等于0.5,沒有確定的選擇標準,但本算法選擇(1,1)1、浮點型的算法x=xsy=ysx = xe -xsy = ye -ys/initialize e to compensate for a nonzero interceptError =y/x-0.5/begin th
19、e main loopfor i=1 to x WritePixel (x, y, value) if (Error 0) then y=y+1 Error = Error -1 end if x=x+1 Error = Error +y/xnext ifinish2整數Bresenham算法 · 上述Bresenham算法在計算直線斜率和誤差項時要用到浮點運算和除法,采用整數算術運算和避免除法可以加快算法的速度。 由于上述Bresenham算法中只用到誤差項(初值Error =y/x-0.5)的符號因此只需作如下的簡單變換: NError = 2*Error*x即可得到整數算法,這
20、使本算法便于硬件(固件)實現。(程序)o /Bresenham's integer line resterization algorithm for the first octal./The line end points are (xs,ys) and (xe,ye) assumed not equal. All variables are assumed integer./initialize variablesx=xsy=ysx = xe -xsy = ye -ys/initialize e to compensate for a nonzero interceptNError
21、=2*y-x /Error =y/x-0.5/begin the main loopfor i=1 to x WritePixel (x, y) if (NError >=0) then y=y+1 NError = NError 2*x /Error = Error -1 end if x=x+1 NError = NError +2*y /Error = Error +y/xnext ifinish接下來就開使畫任意角度的直線了。/*=函數功能:判斷整數的正負及是否為零函數說明:當形參X大于零返回1,等于零返回零,小于零返回-1.=*/uchar pan_duan_fu_hao(uc
22、har x)if(x>0)return 1;/當x大于零返回1else if(x=0)return 0;/當x為零返回0elsereturn -1;/當x小于零返回-1/*=函數功能:畫一條任意斜率的直線函數思想:利用Bresenham畫法基礎上自己稍加改進。既當直線dy>dx時將y坐標依次加一(相當于將y軸于x軸互換)。這里選擇的是浮點型的畫圓方法。會減慢運算速度。也可使用整形的運算方法運算速度更快參數說明:start_x,start_y,end_x,end_y,分別為直線起始坐標和終點坐標,color為直線顏色。length為畫點時循環的次數,falg為dy與dx的大小的標志,
23、當dy>dx時flag置1.=*/void write_line(uchar start_x,uchar start_y,uchar end_x,uchar end_y,uchar color)uint i,length;float temp,dx,dy;char incx,incy,flag;dx=end_x-start_x;/求開始x坐標和結束X坐標的距離dy=end_y-start_y;/求開始y坐標和結束y坐標的距離incx=pan_duan_fu_hao(dx);/判斷整數的正負及是否為零incy=pan_duan_fu_hao(dy);if(incx=0)/當x軸沒有增加時畫一條垂線write_y_line(start_x,start_y,end_y,color);if(incy=0)/當y軸沒有增加時畫一條水平線write_x_line(start_x,end_x,start_y,color);dx=abs(
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 個人簡歷中自我評價范文(18篇)
- 倉儲管理心得體會600字(5篇)
- 教師年終總結匯編(16篇)
- 業務員工作總結模板(17篇)
- 城區租賃糾紛合同書(4篇)
- 七年級上學期學生自我評價(4篇)
- 大一生活回顧與總結(5篇)
- 2025中學政教處工作總結范文(19篇)
- 筑夢路上演講稿集合(16篇)
- 計算機實習生工作總結(9篇)
- GB/T 44260-2024虛擬電廠資源配置與評估技術規范
- 2024浴場承包范本
- 酒店自帶食品免責協議書
- 山東節制閘工程施工組織設計
- 中藥化學試題及答案
- 2024春期國開電大本科《現代漢語專題》在線形考(任務1至6)試題及答案
- HJ 1235-2021 入河(海)排污口命名與編碼規則-PDF解密
- JTG F80-1-2004 公路工程質量檢驗評定標準 第一冊 土建工程
- 《1984》讀書分享課件
- 肺動脈高壓的傳統治療
- 園林植物識別-草本花卉的識別
評論
0/150
提交評論