liuweiele 发表于 2010-5-8 21:01:52

一款最简单的“模拟时钟”

硬件平台: S3C2450 + 4.3寸TFT(480x272,24bpp)

liuweiele 发表于 2010-5-8 21:02:42

“模拟时钟”源程序:
点击此处下载 ourdev_552468.rar(文件大小:1K) (原文件名:SimulationClock.rar)

liuweiele 发表于 2010-5-8 21:34:21

源码解析


#include        "Include.h"

/*============================================================================*/

void        SimulationClock(        HDC hdc,int x,int y,int dx,int dy,int bk_c,
                                                int hour_c,int min_c,int sec_c,
                                                int Hour,int Min,int Sec)
{
               
        #define        PI        3.1415926
       
       
        int radius;      //表盘半径
       
        int        s_Len;    //秒针长度
        int        m_Len;    //分针长度
        int        h_Len;    //时针长度
        int cx,cy;         //表盘中点
        int i,x0,y0,x1,y1;
        ////
       
        Hour%=12;                 
        radius        =MIN((dx>>1),(dy>>1));//计算表盘半径
        s_Len        =(radius*7)>>3;              //设置秒针长度为7/8半径       
        m_Len        =(radius*6)>>3;              //设置分针长度为6/8半径          
        h_Len        =(radius*5)>>3;         //设置时针长度为5/8半径               
       
        cx        =x+(dx>>1);            //计算x中点
        cy        =y+(dy>>1);            //计算y中点
        ////
       
        if(bk_c!=RGB_TRANS)               //如果背景非透明色
        {
                FillRectangle(hdc,x,y,dx,dy,bk_c); //填充背景
               
                for(i=0;i<360;i+=6)   //以6度递增绘制分钟和秒钟刻度
                {                               
                        if((i%30)==0)//以30度递增绘制小时刻度
                        {
                                     //这里绘制小时刻度
                                     //计算刻度两点坐标,刻度长度为表盘半径的(1/16)-4
                                x0 = (int)(cx + sin(i*PI/180)*(radius-2));
                                y0 = (int)(cy - cos(i*PI/180)*(radius-2));       
                               
                                x1 = (int)(cx + sin(i*PI/180)*(radius-(radius>>4)-4));
                                y1 = (int)(cy - cos(i*PI/180)*(radius-(radius>>4)-4));
                               
                                LineWith(hdc,x0,y0,x1,y1,3,RGB(20,20,20)); //用直线连接两点坐标
                        }
                        else
                        {      //这里绘制分钟和秒钟刻度,距表盘中点为:(半径-4)
                                x0 = (int)(cx + sin(i*PI/180)*(radius-4));
                                y0 = (int)(cy - cos(i*PI/180)*(radius-4));       

                                PutPixel(hdc,x0,y0,RGB(20,20,20));   
                        }
                       
                }
        }
        ////

        //绘制时针,时针角度=Hour*30+30*Min/60
        x0 = (int)(cx + sin((Hour*30+Min/2)*PI/180)*h_Len);
        y0 = (int)(cy - cos((Hour*30+Min/2)*PI/180)*h_Len);
        x1 = (int)(cx + sin(((Hour+6)*30+Min/2)*PI/180)*((h_Len>>3)+2));
        y1 = (int)(cy - cos(((Hour+6)*30+Min/2)*PI/180)*((h_Len>>3)+2));
        LineWith(hdc,cx,cy,x0,y0,3,hour_c);
        LineWith(hdc,cx,cy,x1,y1,3,hour_c);

        //绘制分针,分针角度=Min*6
        x0        =(int)(cx + sin((Min*6)*PI/180)*m_Len);
        y0        =(int)(cy - cos((Min*6)*PI/180)*m_Len);       
        x1        =(int)(cx + sin(((Min+30)*6)*PI/180)*((m_Len>>3)+2));
        y1        =(int)(cy - cos(((Min+30)*6)*PI/180)*((m_Len>>3)+2));       
        LineWith(hdc,cx,cy,x0,y0,3,min_c);
        LineWith(hdc,cx,cy,x1,y1,3,min_c);
       
        //绘制秒针,秒针角度=Sec*6
        x0        =(int)(cx + sin((Sec*6)*PI/180)*s_Len);
        y0        =(int)(cy - cos((Sec*6)*PI/180)*s_Len);       
        x1        =(int)(cx + sin(((Sec+30)*6)*PI/180)*((s_Len>>3)+2));
        y1        =(int)(cy - cos(((Sec+30)*6)*PI/180)*((s_Len>>3)+2));       
        Line(hdc,cx,cy,x0,y0,sec_c);
        Line(hdc,cx,cy,x1,y1,sec_c);
        FillCircle(hdc,cx,cy,2,sec_c); //绘制秒针修饰点
       

}

/*============================================================================*/
/*============================================================================*/

static        RESULT        WinRealTimeProc(HWND hwnd,U32 msg,WPARAM wParam,LPARAM lParam)
{
        HDC hdc;
        char buf;
        RECT rc;
        COORD x,y;
        RTC_TIME time;
        ////
       
        switch(msg)
        {
       
                case        MSG_CREATE: //主窗口创建
                                                               
                                break;
                                ////

                                               
                case        MSG_TIMER://定时器消息
                                InvalidateRect(hwnd,0,0); //刷新窗口
                                break;
                                ////
                                       
                case        MSG_PAINT: //绘制窗口
               
                                hdc=BeginPaint(hwnd);

                                RTC_GetTime(&time);
                                SimulationClock(hdc,0,0,WindowClientWidth(hwnd),WindowClientHeight(hwnd),
                                                                GetWindowBkColor(hwnd),RGB(20,20,20),RGB(20,20,20),RGB(200,0,0),
                                                                time.Hour,time.Min,time.Sec);
                                EndPaint(hwnd,hdc);
                                break;
                                ////

                default:        DefaultWindowProc(hwnd,msg,wParam,lParam); //其它消息交给系统处理
               
        }
       
        return MSG_NULL;
}

/*============================================================================*/

void        WinRealTime(void)
{
        HWND hwnd;
        MSG        msg;
        HANDLE hTimer0;
        ////
       
        创建主窗口
        hwnd        =CreateMainWindow(        300,64,160,180,//位置:300,64,尺寸:160x180
                                RGB(96,160,96),//窗口背景色
                                WS_CAPTION|WS_VISIBLE|WS_BORDER_DUAL,0, //窗口风格:带标题栏,窗口可见,双边框
                                WinRealTimeProc,//窗口过程
                                "模拟时钟"); // 窗口标题
       
        hTimer0=SetTimer(hwnd,0x3000,200,NULL); //设置定时器(ID=0x3000,时间:300ms,无回调函数)
                                                       
        ShowWindow(hwnd,SW_SHOW); //显示窗口
        while(GetMessage(&msg,hwnd))    //进入消息循环
        {
                TranslateMessage(&msg);
                DispatchMessage(&msg);
        }
       
        KillTimer(hTimer0);      //销毁定时器
        DestroyMainWindow(hwnd); //销毁主窗口
        //ExitThisThread();      //退出线程
}


/*============================================================================*/
/*============================================================================*/

liuweiele 发表于 2010-5-8 21:39:37

基于多线程,多窗口下环境的程序运行效果:

http://cache.amobbs.com/bbs_upload782111/files_28/ourdev_552472.jpg
(原文件名:照片 2462.jpg)

http://cache.amobbs.com/bbs_upload782111/files_28/ourdev_552473.jpg
(原文件名:照片 2463.jpg)

http://cache.amobbs.com/bbs_upload782111/files_28/ourdev_552474.jpg
(原文件名:照片 2481.jpg)

http://cache.amobbs.com/bbs_upload782111/files_28/ourdev_552475.jpg
(原文件名:照片 2479.jpg)

gzyang 发表于 2010-5-8 21:45:28

看看那,楼主发了好多“精华”了!

1181zjf 发表于 2010-5-8 21:46:27

jh

liuweiele 发表于 2010-5-8 21:55:41

无需贴图,全部由软件算法生成

jack_yu 发表于 2010-5-8 21:56:22

mark!

hujg 发表于 2010-5-8 22:11:23

好。

dmxfeng 发表于 2010-5-8 22:28:07

不错!顶一下

lv998127 发表于 2010-5-8 22:47:46

顶一下

niba 发表于 2010-5-8 22:58:33

楼主的精品帖子必顶。。。贴贴精华

liuweiele 发表于 2010-5-8 23:51:48

回复【11楼】niba
楼主的精品帖子必顶。。。贴贴精华
-----------------------------------------------------------------------

雕虫小技,不足挂齿

dengxiaofeng 发表于 2010-5-9 00:14:14

呵呵,路过!!!

liuweiele 发表于 2010-5-10 12:34:59

支持任意尺寸自动调整

xzbx 发表于 2010-5-10 13:55:39

真的不错!顶一下

tonydh 发表于 2010-5-10 16:08:21

mark!

dongtinhu 发表于 2010-6-12 08:49:00

谢谢高手,正找相关的东西呢

cgbabc 发表于 2010-6-12 10:03:31

学习

wajlh 发表于 2010-6-12 17:06:57

make

clever0725 发表于 2010-6-21 19:17:38

这是linux下的应用程序吗?带不带系统?

liuweiele 发表于 2010-6-21 21:54:12

不是Linux

esdart 发表于 2010-6-21 22:06:09

顶一下,留着用。

quzegang 发表于 2010-6-21 23:15:43

又见弓虽贝占!

yessir 发表于 2010-6-24 21:15:54

兄弟果然厉害! 不知道是否尝试过2450双总线的好处呢? 我指如下情况:运行你自己的arm-os操作系统,然后一个任务通过DMA读SD卡到内存buffer里面,一个任务用DMA从buffer再搬移到一个空的bank地址里面(有点变态,测试总线搬移数据能力罢了),然后,或者还有个任务在用DMA读flash!。然后比较各种情况的cpu占用!?
    本人,2440 + ucos @400Mhz,数据总线100Mhz,边读SD卡,(25MHZ,4bit,SDIO,DMA操作,最高持续10MB/S),边往bank5扔数据(DMA操作),cpu占高50%以上。不读卡,只扔数据,占比10%以下。怎么个垃圾SD card 在APB上,还会拖延cpu时间呢?

liuweiele 发表于 2010-6-24 21:33:51

目前还没有做这方面的测试

wjhltk 发表于 2010-7-5 11:48:22

mark

liuzhijun 发表于 2010-7-5 11:58:35

楼主又发了好多“精华”!

tom919 发表于 2010-7-6 16:25:53

又是精华,mark……

tom919 发表于 2010-8-31 16:51:54

楼主好,不知你是否还在关注你的这篇杰作。能否请教一下你程序中的LineWith()函数原型?我自己弄了一个,不知为什么,用宽度为3画的线有的不正常,也就是没有3个pixel宽,但是也有的地方正常。这个函数在turbo c中作图形测试正常,不知道为什么。请指教,谢谢!
我的函数如下:

void LineWith(int x1,int y1,int x2,int y2,int width,int color)
{
//Width: 1: Normer_width, 1 pixel wide; 3: Thick_width, 3 pixel wide.
int dx,dy;

dx=x1-x2;
dy=y1-y2;
if(dx<0) dx=-dx;        // dx=abs(dx)
if(dy<0) dy=-dy;        // dy=abs(dy)
   
if(width==3)
   {
    if(dy>=dx)
   {      
      Glib_Line(x1,y1,x2,y2,color);
      Glib_Line(x1+1,y1,x2+1,y2,color);
      Glib_Line(x1-1,y1,x2-1,y2,color);
   }
   
    else        //dx>dy
   {
                Glib_Line(x1,y1,x2,y2,color);
                Glib_Line(x1,y1+1,x2,y2+1,color);
                Glib_Line(x1,y1-1,x2,y2-1,color);
   }
   }
else        //width==1
    Glib_Line(x1,y1,x2,y2,color);
   
}

liuweiele 发表于 2010-8-31 17:52:05

回复【29楼】tom919 Tom
-----------------------------------------------------------------------

你的实现算法不合理

tom919 发表于 2010-8-31 19:59:34

回复【30楼】liuweiele Liuwei
-----------------------------------------------------------------------
谢谢LZ回复。但为什么不合理呢?
我之前出错的函数前面是直接用了abs函数,即:
dx=abs(x1-x2);
dy=abs(y1-y2);

我上面贴出的修改后函数我还没有测试是否有所改善,到时我再试试。

lv998127 发表于 2010-8-31 21:55:29

排好队学习

danpianjibb 发表于 2012-12-11 15:36:20

基本可以用,测试通过。

sblpp 发表于 2012-12-11 20:18:34

yessir 发表于 2010-6-24 21:15 static/image/common/back.gif
兄弟果然厉害! 不知道是否尝试过2450双总线的好处呢? 我指如下情况:运行你自己的arm-os操作系统,然后一 ...

catch 开了吗?
页: [1]
查看完整版本: 一款最简单的“模拟时钟”