12864液晶更高級的用法。
首先是它的繪圖功能。
讓我們先來顯示一整副的圖片吧,也就是128x64大小。
在使用繪圖功能時,先要打開擴充指令集,然后再打開繪圖功能。接著就是送數(shù)據(jù)顯示了。這里我們首先要弄明白ST7920的顯示坐標關(guān)系。其顯示坐標如下。
從圖中可以看出,X方向共有8個字(16個字節(jié))Y方向共有0~31 行 分為上下兩個屏。
弄懂了之后我們就可以依照此坐標來顯示一整屏的圖片了。
隨便用一個圖片的提取轉(zhuǎn)換軟件,講一副126X64大小的圖片轉(zhuǎn)換成字節(jié)數(shù)據(jù),總共字節(jié)大小為128*64/8 = 1024個字節(jié)。 下面我們來看看這個顯示整屏圖像的函數(shù)
void v_Lcd12864DrawPicture_f( unsigned char code *pPicture )
{
unsigned char i, j, k ;
for( i = 0 ; i < 2 ; i++ )//分上下兩屏寫
{
for( j = 0 ; j < 32 ; j++ )
{
v_Lcd12864SendCmd_f( 0x80 + j ) ;//寫Y坐標
if( i == 0 ) //寫X坐標
{
v_Lcd12864SendCmd_f( 0x80 ) ;
}
else
{
v_Lcd12864SendCmd_f( 0x88 ) ;
}
for( k = 0 ; k < 16 ; k++ ) //寫一整行數(shù)據(jù)
{
v_Lcd12864SendData_f( *pPicture++ ) ;
}
}
}
v_Lcd12864SendCmd_f( 0x30 ) ;
} 看看效果圖片如下:顯示一個人的圖像 
下面來看看如何在任意一個位置顯示或者是擦除一個點 對于12864這種二值顯示屏來說,其顯示狀態(tài)無外乎顯示和不顯示一個點這兩種狀態(tài)。而在任意位置畫點,是我們隨心所欲的畫線,畫圓,畫矩形的等GUI函數(shù)的基礎(chǔ)。
為了讓這個位置有一個參考點,我們有必要定義一個坐標系
在這里,我定義的坐標系如下
0,0------------------------------------127,0
| |
| |
| |
| |
0,63----------------------------------127,63 0,0代表屏幕的左上角,127,63代表屏幕的右下角。
對于屏幕上面任意一個點,如果我們想要點亮它,必須先讀出此點的狀態(tài),然后再修改該點,最后送出去,即 讀----修改----寫。按照這個步驟,然后再運用C語言中的位操作運算符 可以很方便的完成畫點的函數(shù)。
由于畫點函數(shù)涉及到讀ST7920內(nèi)部RAM的操作,因此,我們必須先要完成這個讀數(shù)據(jù)的函數(shù)
具體實現(xiàn)過程如下:
unsigned char u8_Lcd12864ReadByte_f( void )
{
unsigned char byReturnValue ;
v_Lcd12864CheckBusy_f() ;
io_LCD12864_DATAPORT = 0xff ;
SET_DATA
SET_READ
CLR_EN
SET_EN
byReturnValue = io_LCD12864_DATAPORT ;
CLR_EN return byReturnValue ;
} 然后是畫點的函數(shù),其實現(xiàn)過程如下: void v_Lcd12864DrawPoint_f( unsigned char X, unsigned char Y, unsigned char Color )
{
unsigned char Row , Tier , Tier_bit ;
unsigned char ReadOldH, ReadOldL ;
v_Lcd12864SendCmd_f( 0x34 ) ;
v_Lcd12864SendCmd_f( 0x36 ) ;
Tier = X >> 4 ;
Tier_bit = X & 0x0f ;
if( Y < 32 )
{
Row = Y ;
}
else
{
Row = Y - 32 ;
Tier += 8 ;
}
v_Lcd12864SendCmd_f( Row + 0x80 ) ;
v_Lcd12864SendCmd_f( Tier + 0x80 ) ;
u8_Lcd12864ReadByte_f() ;
ReadOldH = u8_Lcd12864ReadByte_f() ;
ReadOldL = u8_Lcd12864ReadByte_f() ;
v_Lcd12864SendCmd_f( Row + 0x80 ) ;
v_Lcd12864SendCmd_f( Tier + 0x80 ) ;
if( Tier_bit < 8 )
{
switch( Color)
{
case 0 : ReadOldH &=( ~( 0x01 << ( 7 - Tier_bit ))) ; break ;
case 1 : ReadOldH |= ( 0x01 << ( 7 - Tier_bit )) ; break ;
case 2 : ReadOldH ^= ( 0x01 << ( 7 - Tier_bit )) ; break ;
default : break ;
}
v_Lcd12864SendData_f( ReadOldH ) ;
v_Lcd12864SendData_f( ReadOldL ) ;
}
else
{
switch(Color)
{
case 0 : ReadOldL &= (~( 0x01 << ( 15 - Tier_bit ))) ; break ;
case 1 : ReadOldL |= ( 0x01 << ( 15 - Tier_bit )) ; break ;
case 2 : ReadOldL ^= ( 0x01 << ( 15 - Tier_bit )) ; break ;
default : break ;
}
v_Lcd12864SendData_f( ReadOldH ) ;
v_Lcd12864SendData_f( ReadOldL ) ;
}
v_Lcd12864SendCmd_f( 0x30 ) ;
} 有了畫點的函數(shù)之后,一切似乎都變得簡單了,因為點是一切復(fù)雜圖形的最基本的組成單位。
下面我們就在這個畫點函數(shù)的基礎(chǔ)上,實現(xiàn)畫水平線和垂直線的兩個函數(shù)。
畫水平線:
void v_Lcd12864DrawLineX_f( unsigned char X0, unsigned char X1, unsigned char Y, unsigned char Color )
{ unsigned char Temp ;
if( X0 > X1 )
{
Temp = X1 ;
X1 = X0 ;
X0 = Temp ;
}
for( ; X0 <= X1 ; X0++ )
v_Lcd12864DrawPoint_f( X0, Y, Color ) ;
}
畫垂直線:
void v_Lcd12864DrawLineY_f( unsigned char X, unsigned char Y0, unsigned char Y1, unsigned char Color )
{
unsigned char Temp ;
if( Y0 > Y1 )
{
Temp = Y1 ;
Y1 = Y0 ;
Y0 = Temp ;
}
for(; Y0 <= Y1 ; Y0++)
v_Lcd12864DrawPoint_f( X, Y0, Color) ;
} 下面我們就用以上兩個畫線函數(shù),在液晶屏上面畫一個表格出來
v_Lcd12864DrawLineX_f( 0, 127 , 0, 1 ) ;
v_Lcd12864DrawLineX_f( 0, 127 , 7, 1 ) ;
v_Lcd12864DrawLineX_f( 0, 127 , 15, 1 ) ;
v_Lcd12864DrawLineX_f( 0, 127 , 23, 1 ) ;
v_Lcd12864DrawLineX_f( 0, 127 , 31, 1 ) ;
v_Lcd12864DrawLineX_f( 0, 127 , 39, 1 ) ;
v_Lcd12864DrawLineX_f( 0, 127 , 47, 1 ) ;
v_Lcd12864DrawLineX_f( 0, 127 , 55, 1 ) ;
v_Lcd12864DrawLineX_f( 0, 127 , 63, 1 ) ;
v_Lcd12864DrawLineY_f( 0, 0 , 63, 1 ) ;
v_Lcd12864DrawLineY_f( 15, 0 , 63, 1 ) ;
v_Lcd12864DrawLineY_f( 31, 0 , 63, 1 ) ;
v_Lcd12864DrawLineY_f( 47, 0 , 63, 1 ) ;
v_Lcd12864DrawLineY_f( 63, 0 , 63, 1 ) ;
v_Lcd12864DrawLineY_f( 79, 0 , 63, 1 ) ;
v_Lcd12864DrawLineY_f( 95, 0 , 63, 1 ) ;
v_Lcd12864DrawLineY_f( 111, 0 , 63, 1 ) ;
v_Lcd12864DrawLineY_f( 127, 0 , 63, 1 ) ; 看看顯示效果 
怎么樣,你的實現(xiàn)了嗎?
只能畫水平線和垂直線似乎太簡單和單調(diào)點了。
要是能在任意兩點間畫一條直線就好了,那樣我們就可以做很多事情了。
下面就讓我們?nèi)崿F(xiàn)它!
在這里我們采用Bresenham畫線算法,關(guān)于這個算法,網(wǎng)上有很多資料,請大家以它為關(guān)鍵字到網(wǎng)上去搜索,在這里就不啰嗦了。
下面是算法的具體實現(xiàn)過程:
void v_Lcd12864DrawLine_f( unsigned char StartX, unsigned char StartY, unsigned char EndX, unsigned char EndY, unsigned char Color )
{
int t, distance; /*根據(jù)屏幕大小改變變量類型(如改為int型)*/
int x = 0 , y = 0 , delta_x, delta_y ;
char incx, incy ;
delta_x = EndX - StartX ;
delta_y = EndY - StartY ; if( delta_x > 0 )
{
incx = 1;
}
else if( delta_x == 0 )
{
v_Lcd12864DrawLineY_f( StartX, StartY, EndY, Color ) ;
return ;
}
else
{
incx = -1 ;
}
if( delta_y > 0 )
{
incy = 1 ;
}
else if(delta_y == 0 )
{
v_Lcd12864DrawLineX_f( StartX, EndX, StartY, Color ) ;
return ;
}
else
{
incy = -1 ;
} delta_x = ABS( delta_x );
delta_y = ABS( delta_y );
if( delta_x > delta_y )
{
distance = delta_x ;
}
else
{
distance = delta_y ;
}
v_Lcd12864DrawPoint_f( StartX, StartY, Color ) ;
/* Draw Line*/
for( t = 0 ; t <= distance+1 ; t++ )
{
v_Lcd12864DrawPoint_f( StartX, StartY, Color ) ;
x += delta_x ;
y += delta_y ;
if( x > distance )
{
x -= distance ;
StartX += incx ;
}
if( y > distance )
{
y -= distance ;
StartY += incy ;
}
}
} 老規(guī)矩,我們用這個函數(shù)隨便畫任意斜率的幾條直線看看。
v_Lcd12864DrawLine_f( 0, 0, 127, 63, 1 ) ;
v_Lcd12864DrawLine_f( 0, 63, 127, 0 , 1 ) ;
v_Lcd12864DrawLine_f( 12, 0, 127, 63, 1 ) ;
v_Lcd12864DrawLine_f( 52, 63, 127, 0 , 1 ) ;
v_Lcd12864DrawLine_f( 32, 63, 98, 0, 1 ) ;
v_Lcd12864DrawLine_f( 67, 0, 127, 63 , 1 ) ; 下面是具體的效果圖:

|