打印
[DemoCode下载]

SHOW---LCD12864之模拟指针式时钟

[复制链接]
1277|14
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
C洛达尔多|  楼主 | 2015-12-17 20:23 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
LCD12864是个好东西,之前介绍了用LCD12864显示一个简易的动画,以及用LCD12864做一个俄罗斯方块游戏,今天再介绍一点其他的好玩的东西-----用LCD12864做一个模拟指针式时钟。用LCD12864做一个模拟指针式时钟,其实主要用的是LCD12864(ST7920)的绘图功能:
      1.利用圆心坐标和半径画一个圆作为表盘
      2.利用两点间画线功能画出时分秒指针。
      让我们一起来做一个LCD12864模拟指针式时钟,Let's GO!!
     LCD12864的底层驱动很简单,利用时序图可以轻松解决,这部分就跳过了。所以,我们首先要解决的是如何画圆。我在查找资料时,发现有好几种方法,我使用的是这种:

沙发
C洛达尔多|  楼主 | 2015-12-17 20:24 | 只看该作者
            /****************************************

            对称法画圆的8个镜像点

            *****************************************/

            void CircleDot(unsigned char x,unsigned char y,char xx,char yy,unsigned char Color)//内部函数,对称法画圆的8个镜像点

            {

                    Lcd_PutPixel((x+yy),(y+xx),Color);//第 1 个 8 分圆

                    Lcd_PutPixel((x+xx),(y+yy),Color);//第 2 个 8 分圆

                    Lcd_PutPixel((x-xx),(y+yy),Color);//第 3 个 8 分圆

                    Lcd_PutPixel((x-yy),(y+xx),Color);//第 4 个 8 分圆

                    Lcd_PutPixel((x-yy),(y-xx),Color);//第 5 个 8 分圆

                    Lcd_PutPixel((x-xx),(y-yy),Color);//第 6 个 8 分圆

                    Lcd_PutPixel((x+xx),(y-yy),Color);//第 7 个 8 分圆

                    Lcd_PutPixel((x+yy),(y-xx),Color);//第 8 个 8 分圆

            }


            /******************************************

            向LCD指定圆心坐标画一个半径为r的指定颜色的圆

            *******************************************/

            void Lcd_Circle(unsigned char x,unsigned char y,unsigned char r,unsigned char Color)//中点法画圆

            {//中点法画圆

                    unsigned char xx,yy;

                    char deltax,deltay,d;

                    xx=0;

                    yy=r;

                    deltax=3;

                    deltay=2-r-r;

                    d=1-r;

                    CircleDot(x,y,xx,yy,Color);//对称法画圆的8个镜像点

                    while (xx

                        {

                                if (d<0)

                                {

                                        d+=deltax;

                                        deltax+=2;

                                        xx++;

                                }

                                else

                                {

                                        d+=deltax+deltay;

                                        deltax+=2;

                                        deltay+=2;

                                        xx++;

                                        yy--;

                                }

                                CircleDot(x,y,xx,yy,Color);//对称法画圆的8个镜像点

                        }

                }

使用特权

评论回复
板凳
C洛达尔多|  楼主 | 2015-12-17 20:24 | 只看该作者
利用画圆函数可以先画出时钟的表盘,下一步,我们得再画出时分秒的指针。画时分秒的指针其实用到的是任意两点间画一条线这个功能,如何实现呢?答案是:布兰森汉姆(Bresenham)算法画线!在画线、画圆中经常会用到Bresenham算法,Bresenham算法是什么?如果你感兴趣的话,可以先搜一下,网上关于这个的介绍很多很多,我就不介绍了,上代码:

使用特权

评论回复
地板
C洛达尔多|  楼主 | 2015-12-17 20:25 | 只看该作者
        /*******************************************

        向LCD指定起始坐标和结束坐标之间画一条指定颜色的直线

        ********************************************/

        void Lcd_Line(unsigned char x1,unsigned char y1,unsigned char x2,unsigned char y2,unsigned char Color)

        {

                unsigned int x,y;

                unsigned int d_x,d_y;//d_x=x2-x1;d_y=y2-y1;

                int err=0;

                unsigned char temp=0;

                if(y2

                    {

                            x=x1;

                            y=y1;

                            x1=x2;

                            y1=y2;

                            x2=x;

                            y2=y;

                    }

                    d_y=y2-y1;

                    if (d_y==0)

                    {

                            if (x1>x2)

                            {

                                    x=x1;

                                    x1=x2;

                                    x2=x;

                            }

                            for (x=x1;x<=x2;x++)

                                    Lcd_PutPixel(x,y1,Color);

                    }

                   

                    else

                    {

                            if(x2>=x1)

                            {

                                    temp=1;

                                    d_x=x2-x1;

                            }

                            else

                            d_x=x1-x2;

                            x=x1;

                            y=y1;

                            Lcd_PutPixel(x,y,Color);

                   

                            if(temp&&(d_y<=d_x))

                            while(x!=x2)

                            {

                                    if(err<0)

                                    {

                                            x=x+1;

                                            err=err+(y2-y);

                                    }

                                    else

                                    {

                                            x=x+1;

                                            y=y+1;

                                            err=err+(y2-y)-(x2-x);

                                    }

                                    Lcd_PutPixel(x,y,Color);

                            }

                   

                            else if(temp&&(d_y>d_x))

                            while(y!=y2)

                            {

                                    d_x=x2-x;

                                    d_y=y2-y;

                                    if(err<0)

                                    {

                                            x=x+1;

                                            y=y+1;

                                            err=err+d_y-d_x;

                                    }

                                    else

                                    {

                                            y=y+1;

                                            err=err-d_x;

                                    }

                                    Lcd_PutPixel(x,y,Color);

                                   

                            }

                   

                            else if(!temp&&(d_y<=d_x))

                            while(x!=x2)

                            {

                                    d_x=x-x2;

                                    d_y=y2-y;

                                    if(err<0)

                                    {

                                            x=x-1;

                                            err=err+d_y;

                                    }

                                    else

                                    {

                                            x=x-1;

                                            y=y+1;

                                            err=err+d_y-d_x;

                                    }

                                    Lcd_PutPixel(x,y,Color);

                            }

                   

                            else if(!temp &&(d_y>d_x))

                            {

                                    while(y!=y2)

                                    {

                                            d_x=x-x2;

                                            d_y=y2-y;

                                            if(err<0)

                                            {

                                                    x=x-1;

                                                    y=y+1;

                                                    err=err+d_y-d_x;

                                            }

                                            else

                                            {

                                                    y=y+1;

                                                    err=err-d_x;

                                            }

                                            Lcd_PutPixel(x,y,Color);

                                    }

                            }

                    }

            }

使用特权

评论回复
5
C洛达尔多|  楼主 | 2015-12-17 20:26 | 只看该作者
有了画线的方法,我们还不能画出时分秒指针,因为画线需要起点坐标和末点坐标。指针是从圆心这一点指向这一刻时间的一条线,起点坐标有了,就是圆盘的圆心坐标,但是末点坐标不知道。比如1秒,秒针由圆心坐标指向1秒的位置,这个1秒的位置在哪??我们可以由圆心坐标和半径,以及时间的角度算出:

使用特权

评论回复
6
C洛达尔多|  楼主 | 2015-12-17 20:26 | 只看该作者
    /***************************************************

    函数名称:LcdTimeX(uint8 Length,uint8 Angle)

    函数功能:计算指针的X坐标

    输入参数:circle_x:圆心横坐标

              Length  :半径长度

                     Angle   :角度

    输出参数: x坐标

    ****************************************************/

    unsigned char Lcd_TimeX(unsigned char circle_x,unsigned char Length,unsigned char Angle)

    {

       unsigned char x;

       if((Angle>0) && (Angle<=15))

       {  

         x = circle_x + Length * (sin(PI * Angle / 30));   

       }

       else if(Angle > 15 && Angle <= 30)   

       {  

          x = circle_x + Length * cos((PI * Angle) / 30 - (PI / 2 ));

       }

       else if(Angle > 30 && Angle <= 45)

       {

           x = circle_x - Length * sin((PI * Angle) / 30- PI);

       }

       else

       {

           x = circle_x-Length * cos((PI * Angle) / 30 - ((3 * PI) / 2));

       }  

            return x;                       

    }

使用特权

评论回复
7
C洛达尔多|  楼主 | 2015-12-17 20:27 | 只看该作者
    /***************************************************

    函数名称:LcdTimeY(uint8 Length,uint8 Angle)

    函数功能:计算指针的Y坐标

    输入参数:circle_y:圆心纵坐标

              Length  :半径长度

                     Angle   :角度

    输出参数: Y坐标

    ****************************************************/

    unsigned char Lcd_TimeY(unsigned char circle_y,unsigned char Length,unsigned char Angle)

    {

       unsigned char y;

       if((Angle>0) && (Angle<=15))

       {  

          y = circle_y - Length * (cos(PI * Angle / 30));   

       }

       else if(Angle > 15 && Angle <= 30)   

       {  

          y = circle_y + Length * sin((PI * Angle) / 30 - (PI / 2 ));

       }

       else if(Angle > 30 && Angle <= 45)

       {

           y = circle_y + Length * cos((PI * Angle) / 30- PI);

       }

       else

       {

           y = circle_y - Length * sin((PI * Angle) / 30 - ((3 * PI) / 2));

       }

       return y;                       

    }

使用特权

评论回复
8
C洛达尔多|  楼主 | 2015-12-17 20:28 | 只看该作者
好了,所有的东西都准备齐全了,开工!!
   
先画表盘:
void init_Point_Clock() //初始化表盘
{
      unsigned char i;
      Lcd_Circle(32,32,31,1);//画圆  圆心坐标(32,32) 半径31
      for(i=0;i<60;i++)
     {
        if((i%5)==0)      //画刻度
       {
           Lcd_Line(Lcd_TimeX(32,30,i),Lcd_TimeY(32,30,i),Lcd_TimeX(32,27,i),Lcd_TimeY(32,27,i),1);                                       
       }
    }
}

使用特权

评论回复
9
C洛达尔多|  楼主 | 2015-12-17 20:28 | 只看该作者
我用的是定时器做的,这一时刻的时间与上一时刻不一样时,把上一时刻的指针消除掉,显示这一时刻的指针
//【0】:上一时刻时间
//【1】:这一时刻时间
struct POINT_CLOCK
{
        unsigned char hour;
        unsigned char minute;
        unsigned char second;

}Point_Time[2];


/*========================================================================
*name:Display_Pointer(struct POINT_CLOCK AA,unsigned char color)
*function:显示时、分、秒指针
*参    数:结构体: 时分秒   
*                   color: 0不显示  1:显示
*注:秒针长24
        分针长17
         秒针长12
=========================================================================*/
void Display_Pointer(struct POINT_CLOCK AA,unsigned char color)        //指针显示
{
        Lcd_Line(Lcd_TimeX(32,24,AA.second),Lcd_TimeY(32,24,AA.second),32,32,color);         
        Lcd_Line(Lcd_TimeX(32,17,AA.minute),Lcd_TimeY(32,17,AA.minute),32,32,color);        
        Lcd_Line(Lcd_TimeX(32,12,AA.minute/10+5*(AA.hour%12)),Lcd_TimeY(32,12,AA.minute/10+5*(AA.hour%12)),32,32,color);                                                         
}

使用特权

评论回复
10
C洛达尔多|  楼主 | 2015-12-17 20:29 | 只看该作者
/*========================================================================
*name:Display_PointClock(struct POINT_CLOCK AA,unsigned char color)
*function:显示时、分、秒指针
*参    数:结构体0:存放上一个时分秒   》》》两者不同时,刷新显示
           结构体1:存放这一个时分秒   》》》
*
*                   color:0不显示  1:显示
=========================================================================*/
void Display_PointClock()        //指针式时钟显示
{
        if(Point_Time[0].second!=Point_Time[1].second)      //秒刷新
        {
                Lcd_Line(Lcd_TimeX(32,24,Point_Time[0].second),Lcd_TimeY(32,24,Point_Time[0].second),32,32,0);
        }
        if(Point_Time[0].minute!=Point_Time[1].minute)    //分刷新
        {
                 Lcd_Line(Lcd_TimeX(32,17,Point_Time[0].minute),Lcd_TimeY(32,17,Point_Time[0].minute),32,32,0);        
        }
        if((Point_Time[0].minute/10+5*(Point_Time[0].hour%12))!=(Point_Time[1].minute/10+5*(Point_Time[1].hour%12)))   //时刷新显示
        {
        Lcd_Line(Lcd_TimeX(32,12,Point_Time[0].minute/10+5*(Point_Time[0].hour%12)),Lcd_TimeY(32,12,Point_Time[0].minute/10+5(Point_Time[0].hour%12)),32,32,0);        
        }
        Display_Pointer(Point_Time[1],1);        //现在的指针式时钟显示
        Point_Time[0]=Point_Time[1];
}

使用特权

评论回复
11
落叶行健ywm| | 2015-12-21 16:39 | 只看该作者
不错,没事的时候测试下!

使用特权

评论回复
12
jy6715| | 2015-12-22 09:28 | 只看该作者
谢谢分享

使用特权

评论回复
13
bkn1860| | 2015-12-22 09:43 | 只看该作者
刚好用手上的12864玩玩,谢谢分享

使用特权

评论回复
14
捉虫天师| | 2016-1-31 14:29 | 只看该作者

谢谢分享

使用特权

评论回复
15
quray1985| | 2016-2-1 16:21 | 只看该作者
12864的屏有没有彩屏啊,做个俄罗斯方块挺好玩的

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

28

主题

236

帖子

0

粉丝