12864液晶画点和画任意两点间直线原理、算法及程序原码

2020-02-05 09:18发布

12864液晶画点和画任意直线的原理和算法
程序原码经验证可行


12864实际上是256x64二维显示空间,整个液晶屏分上下两个半屏。整个屏一共有256列,64行。可以把它分成16大列,每一大列包含16列。图形RAM的起始址址为0x80,设置读或写的地址时,要先写Y坐标,再写X坐标。要使用画图功能,就要设置扩允指令集。

画点原理:先确定坐标->读出数据->修改数据->数据写回原处。

程序原码:

//画点函数
void Draw_Point(uchar x,uchar y,uchar color)
{
        uchar row,tier,row_bit;
        uchar ReadOldH,ReadOldL;

        tier=x>>4;                        //把256列分成16大列,每大列包含16列
        row_bit=x&0x0f;                  //计算所给坐标在某一大列中的哪一列
        
        if(y<32)                                //分上下半屏显示
                row=y;                        //上半屏
        else                                       
        {
                row=y-32;                //下半屏
                tier+=8;                        
        }
        
        WriteCommand(0x34);     //8Bit扩充指令集,即使是36H也要写两次   
          WriteCommand(0x36);     //绘图ON,基本指令集里面36H不能开绘图  

        WriteCommand(0x80+row);     // 行位置
        WriteCommand(0x80+tier);     // 列位置  

        ReadData();
        ReadOldH=ReadData();                                //某大列的前8列数据,低位在前,高位在后
        ReadOldL=ReadData();                                //某大列的后8列数据
        
         if( row_bit < 8 )                                //修改读出的数据
    {
        switch( color)
        {
            case 0 : ReadOldH &=( ~( 0x01 << ( 7 - row_bit ))) ; break ;
            case 1 : ReadOldH |= ( 0x01 << ( 7 - row_bit ))  ;  break ;
            case 2 : ReadOldH ^= ( 0x01 << ( 7 - row_bit ))    ; break ;
            default : break ;   
        }
    }
    else
    {
        switch(color)
        {
            case 0 : ReadOldL &= (~( 0x01 << ( 15 - row_bit ))) ;  break ;
            case 1 : ReadOldL |= ( 0x01 << ( 15 - row_bit ))    ;  break ;
            case 2 : ReadOldL ^= ( 0x01 << ( 15 - row_bit ))  ;  break ;
            default : break ;
        }
        
    }

        WriteCommand(0x80+row);     // 行位置
        WriteCommand(0x80+tier);     // 列位置

        WriteData( ReadOldH ) ;                        //把修改后的数据写回原地址
           WriteData( ReadOldL ) ;
                     
}


画任意两点间直线的原理和算法:采用Bresenham画线算法。

设线段方程:ax+by+c=0(x1<x<x2,y1<y<y2)
令dx=x2-x1,dy=y2-y1
则:斜率-a/b = dy/dx.

斜率大于0:
从第一个点开始,我们有F(x,1,y1) = a*x1+b*y1+c=0
下面求线段ax+by+c=0与x=x1+1的交点:
由a*(x1+1)+b*y+c = 0, 求出交点坐标y=(-c-a(x1+1))/b
所以交点与点(x+1,y+0.5)的y坐标差值Sub1 = (-c-a(x1+1))/b - (y1+0.5) = -a/b-0.5,即Sub1的处始值为-a/b-0.5。

则可得条件当 Sub1 = -a/b-0.5>0时候,即下个点为(x+1,y+1),反之,下个点为(x+1,y).
代入a/b,则Sub1 = dy/dx-0.5.

判断条件为:2dy-dx>0?

斜率小于0:同理。

斜率=0:即为横线。
斜率=1:即为竖线。

程序原码:

//画任意两点间的直线
void DrawLine( 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 )
{
        if(delta_y>0)
     DrawTierLine( StartX,StartY, EndY-StartY, Color ) ;
        else
        DrawTierLine( StartX,EndY, StartY-EndY, Color ) ;
     return ;
}
else
{
     incx = -1 ;
}
if( delta_y > 0 )
{
     incy = 1 ;
}


//画横线
else if(delta_y == 0 )
{
        if(delta_x>0)
     DrawRowLine( StartY,StartX,EndX-StartX, Color ) ;
        else
        DrawRowLine( StartY,EndX,StartX-EndX, Color ) ;   
     return ;
}
else
{
     incy = -1 ;
}

if(delta_x<0)
delta_x =-delta_x ;
if(delta_y<0)   
delta_y =-delta_y;

if( delta_x > delta_y )
{
     distance = delta_x ;
}
else
{
     distance = delta_y ;
}
DrawPoint( StartX, StartY, Color ) ;   
/* Draw Line*/
for( t = 0 ; t <= distance+1  ; t++ )
{
     DrawPoint( StartX, StartY, Color ) ;
     x += delta_x ;
     y += delta_y ;

        //2dy-dx>0?
     if( x > distance )                                
     {
         x -= distance ;
         StartX += incx ;
     }
     if( y > distance )
     {
         y -= distance ;
         StartY += incy ;
     }
}
}
size=4]
0条回答

一周热门 更多>