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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 25203|回復: 19
打印 上一主題 下一主題
收起左側

12864液晶顯示圖片,畫點,畫任意直線

  [復制鏈接]
跳轉到指定樓層
樓主
ID:76244 發表于 2015-4-7 00:35 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
12864液晶更高級的用法。
首先是它的繪圖功能。
讓我們先來顯示一整副的圖片吧,也就是128x64大小。
在使用繪圖功能時,先要打開擴充指令集,然后再打開繪圖功能。接著就是送數據顯示了。這里我們首先要弄明白ST7920的顯示坐標關系。其顯示坐標如下。



從圖中可以看出,X方向共有8個字(16個字節)Y方向共有0~31 行 分為上下兩個屏。
弄懂了之后我們就可以依照此坐標來顯示一整屏的圖片了。
隨便用一個圖片的提取轉換軟件,講一副126X64大小的圖片轉換成字節數據,總共字節大小為128*64/8 = 1024個字節。

下面我們來看看這個顯示整屏圖像的函數
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++ )      //寫一整行數據
            {
                v_Lcd12864SendData_f( *pPicture++ ) ;
            }
        }
    }
    v_Lcd12864SendCmd_f( 0x30 ) ;
}

看看效果圖片如下:顯示一個人的圖像


下面來看看如何在任意一個位置顯示或者是擦除一個點

對于12864這種二值顯示屏來說,其顯示狀態無外乎顯示和不顯示一個點這兩種狀態。而在任意位置畫點,是我們隨心所欲的畫線,畫圓,畫矩形的等GUI函數的基礎。
為了讓這個位置有一個參考點,我們有必要定義一個坐標系
在這里,我定義的坐標系如下
0,0------------------------------------127,0
|                                                          |
|                                                          |
|                                                          |
|                                                          |
0,63----------------------------------127,63

0,0代表屏幕的左上角,127,63代表屏幕的右下角。
對于屏幕上面任意一個點,如果我們想要點亮它,必須先讀出此點的狀態,然后再修改該點,最后送出去,即 讀----修改----寫。按照這個步驟,然后再運用C語言中的位操作運算符 可以很方便的完成畫點的函數。
由于畫點函數涉及到讀ST7920內部RAM的操作,因此,我們必須先要完成這個讀數據的函數
具體實現過程如下:
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 ;   
}

然后是畫點的函數,其實現過程如下:

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 )    ;
}

有了畫點的函數之后,一切似乎都變得簡單了,因為點是一切復雜圖形的最基本的組成單位。
下面我們就在這個畫點函數的基礎上,實現畫水平線和垂直線的兩個函數。
畫水平線:
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)    ;
}

下面我們就用以上兩個畫線函數,在液晶屏上面畫一個表格出來
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 ) ;

看看顯示效果


怎么樣,你的實現了嗎?
只能畫水平線和垂直線似乎太簡單和單調點了。
要是能在任意兩點間畫一條直線就好了,那樣我們就可以做很多事情了。
下面就讓我們去實現它!
在這里我們采用Bresenham畫線算法,關于這個算法,網上有很多資料,請大家以它為關鍵字到網上去搜索,在這里就不啰嗦了。
下面是算法的具體實現過程:
void v_Lcd12864DrawLine_f( unsigned char StartX, unsigned char StartY, unsigned char EndX, unsigned char EndY, unsigned char Color )
{
    int t, distance;      /*根據屏幕大小改變變量類型(如改為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 ;
        }
    }
}

老規矩,我們用這個函數隨便畫任意斜率的幾條直線看看。
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 ) ;

下面是具體的效果圖:



評分

參與人數 1黑幣 +8 收起 理由
zhaok2013 + 8 贊一個!

查看全部評分

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏23 分享淘帖 頂2 踩
回復

使用道具 舉報

沙發
ID:76348 發表于 2015-4-7 16:47 | 只看該作者
觀摩!!51黑有你更精彩!
回復

使用道具 舉報

板凳
ID:77282 發表于 2015-5-16 21:19 | 只看該作者
這么高級的功能怎么沒人頂呢!頂起來!
回復

使用道具 舉報

地板
ID:94867 發表于 2016-3-23 07:36 | 只看該作者
這個不錯我先回復,
回復

使用道具 舉報

5#
ID:105313 發表于 2016-3-23 21:21 來自觸屏版 | 只看該作者
謝謝分享
回復

使用道具 舉報

6#
ID:110507 發表于 2016-3-24 11:16 | 只看該作者
挺好的程序
回復

使用道具 舉報

7#
ID:135812 發表于 2016-8-2 17:36 | 只看該作者
我的撒撒手動閥手動閥樓上的啦啦啦啦
回復

使用道具 舉報

8#
ID:134810 發表于 2016-9-25 14:21 來自觸屏版 | 只看該作者
想不到12864還可以畫圖,,用按鍵控制喏,很有意思
回復

使用道具 舉報

9#
ID:57620 發表于 2017-3-10 13:06 | 只看該作者
這個好,工程應用上非常有用。太感謝了
回復

使用道具 舉報

10#
ID:198716 發表于 2017-5-10 19:59 | 只看該作者
這個不錯
回復

使用道具 舉報

11#
ID:290892 發表于 2018-7-12 20:44 | 只看該作者
非常感謝
回復

使用道具 舉報

12#
ID:373594 發表于 2018-7-22 00:25 | 只看該作者
delta_x = ABS( delta_x );   
    delta_y = ABS( delta_y );
對不起,原諒我是個菜雞,這個ABS是個函數嗎?那為什么沒看到定義呢?
回復

使用道具 舉報

13#
ID:373594 發表于 2018-7-24 19:53 | 只看該作者
echowithme 發表于 2018-7-22 00:25
delta_x = ABS( delta_x );   
    delta_y = ABS( delta_y );
對不起,原諒我是個菜雞,這個ABS是個函 ...

#include<math.h>

絕對值
回復

使用道具 舉報

14#
ID:481641 發表于 2019-4-12 16:39 | 只看該作者
有更全一點的代碼嗎
回復

使用道具 舉報

15#
ID:387410 發表于 2019-9-30 16:21 | 只看該作者
樓主優秀,用到看一下,謝謝
回復

使用道具 舉報

16#
ID:387410 發表于 2019-9-30 16:22 | 只看該作者
頂一下,不錯
回復

使用道具 舉報

17#
ID:276663 發表于 2020-5-23 00:38 | 只看該作者
問題是,如果屏幕不支持讀數據呢?
回復

使用道具 舉報

18#
ID:601642 發表于 2020-5-23 19:03 來自觸屏版 | 只看該作者
妙啊!
回復

使用道具 舉報

19#
ID:253767 發表于 2020-5-24 06:57 | 只看該作者
謝謝分享!!!
回復

使用道具 舉報

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

本版積分規則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 国产精品美女一区二区 | 精品1区 | 欧美日韩中文在线 | 成人国产毛片 | 午夜无码国产理论在线 | 91看片网 | 美国一级毛片a | 久久久久国产精品一区二区 | 免费网站在线 | 中文字幕亚洲欧美 | 国产成人午夜精品影院游乐网 | 夜夜爽夜夜操 | 久久婷婷麻豆国产91天堂 | 欧美日韩国产精品激情在线播放 | 亚洲综合首页 | 亚洲精品视频一区 | 91麻豆产精品久久久久久夏晴子 | 中文字幕在线一区 | 色综合一区二区三区 | 日韩亚洲欧美综合 | 毛片免费观看 | 亚洲欧美视频一区二区 | www.亚洲区 | 亚洲国产精品区 | 国产精品免费一区二区三区四区 | 成人性视频免费网站 | 91资源在线观看 | 亚洲高清视频一区 | 热久久免费视频 | 欧美黄色片在线观看 | 一级黄色片毛片 | 91视频在线| 黄色网一级片 | 国产欧美一区二区三区在线看蜜臀 | 国产精品一区二区不卡 | 91国内精精品久久久久久婷婷 | 日韩毛片免费视频 | 国产视频一区在线 | 国产98色在线 | 日韩 | 日日爽| www国产精品 |