• 【STM32H7】第30章 ThreadX GUIX炫酷实用的时钟表盘设计,结合硬件RTC实时时钟


    最新教程下载:http://www.armbbs.cn/forum.php?mod=viewthread&tid=98429

    第30章       ThreadX GUIX炫酷实用的时钟表盘设计,结合硬件RTC实时时钟

    本章节为大家讲解漂亮实用的时钟表盘设计,并且结合STM32的硬件RTC实时时钟。

    30.1初学者重要提示

    30.2 第1步,GUIX Studio创建空白窗口

    30.3 第2步,GUIX Studio设置窗口回调

    30.4 第3步,添加图片

    30.5 第5步,窗口回调函数里面设置局部Dirty

    30.6 第6步,窗口绘制回调里面绘制时钟表盘

    30.7 实验例程

    30.8 总结

    30.1 初学者重要提示

    1、  务必看第16章局部刷新的实现。

    2、 GUIX实现时钟表盘的关键是实时图标旋转,即函数gx_canvas_pixelmap_draw的实现。

    30.2 第1步,GUIX Studio创建空白窗口

    GUIX Studio的设置方法与第11章一样。创建的界面效果如下:

     

    30.3 第2步,GUIX Studio设置窗口回调

    30.3.1        窗口事件回调设置

    下面我们为窗口控件设置一个Event Function,此功能是窗口的事件回调函数。在这个回调函数里面,大家可以处理各种事件。

     

    这里为Event Function设置的回调函数名为_cbEventWindow0,然后就可以使用GUIX Studio生成新的代码。生成的代码移植到硬件平台的方法看第12章即可。

    30.3.2        窗口绘制回调设置

    下面我们为窗口设置一个Draw Function,此功能是窗口的绘制回调函数。在这个回调函数里面,大家可以实现各种2D绘制。

     

    这里为Draw Function设置的回调函数名为_cbWindow0,然后就可以使用GUIX Studio生成新的代码。

    30.4 第3步,添加图片

    将时钟表盘背景图片,时针,分针和秒针都添加进来:

     时钟图片都放在了clock文件夹中(本章教程配套例子的文件里面)

    四个添加的图片都要如下方式逐一设置:

    这个compress output对钩一定要去掉,否则无法正常旋转。

    通过前面这三步就完了GUIX Studio的设置工作,剩下就是实际程序的配置。

    30.5 第5步,窗口回调函数里面设置局部Dirty

    通过设置窗口局部Dirty可以触发重绘:

    /* 图像绘制区 */
    GX_RECTANGLE WinPartialDraw =  {0, 0, 0, 0};
    
    /*
    *********************************************************************************************************
    *    函 数 名: _cbEventWindow
    *    功能说明: 窗口window的事件回调函数
    *    形    参: widget     窗口句柄 
    *             event_ptr  事件指针
    *    返 回 值: 返回0表示成功
    *********************************************************************************************************
    */
    UINT _cbEventWindow(GX_WINDOW *widget, GX_EVENT *event_ptr)
    {
    
        switch (event_ptr->gx_event_type)
        {
          /* 控件显示事件 */
            case GX_EVENT_SHOW:
            
                /* 启动一个GUIX定时器 */
                gx_system_timer_start((GX_WIDGET *)widget, GUI_ID_Timer0, 1, 1000/6);
    
                /* 默认事件处理 */
                gx_window_event_process(widget, event_ptr);
                break;
    
            /* 定时器时间溢出事件*/
            case GX_EVENT_TIMER:
                if (event_ptr->gx_event_payload.gx_event_timer_id == GUI_ID_Timer0)
                {
                    /* 设置窗口dirty,这样会触发窗口更新 */
                    gx_system_dirty_partial_add(widget, &WinPartialDraw);
                }
                break;
    
            default:
                return gx_window_event_process(widget, event_ptr);
        }
    
        return 0;
    }

    窗口局部更新也比较容易实现,调用函数gx_system_dirty_partial_add来标记窗口为dirty,这样就会触发GUIX执行绘制回调函数。

    #define gx_system_dirty_partial_add(a, b)   _gxe_system_dirty_partial_add((GX_WIDGET *)a, b)
    UINT  _gxe_system_dirty_partial_add(GX_WIDGET *widget, GX_RECTANGLE *dirty_area)

    与全局更新不同的是局部更新可以设置想更新的区域,这样可以有效降低CPU和DMA2D的利用率。

    1、第1个参数是大家要更新的窗口句柄。

    2、第2个参数是要更新的区域。更新区域是GX_RECTANGLE类型结构体,此结构体定义了矩形区域。我们这里没有设置初始值,是在函数MainTask里面做了配置:

    WinPartialDraw.gx_rectangle_right = DISPLAY_1_THEME_1_CLOCK_CLASSIC_BACKGROUND_pixelmap.gx_pixelmap_width;
    WinPartialDraw.gx_rectangle_bottom = DISPLAY_1_THEME_1_CLOCK_CLASSIC_BACKGROUND_pixelmap.gx_pixelmap_height;

    30.6 第6步,窗口绘制回调里面绘制时钟表盘

    实现代码如下:

    /*
    *********************************************************************************************************
    *    函 数 名: _cbWindow0
    *    功能说明: 窗口window的绘制回调函数
    *    形    参: widget     窗口句柄 
    *    返 回 值: 无
    *********************************************************************************************************
    */
    VOID _cbWindow0(GX_WINDOW *widget)
    {
        int      t0;   /* 用于三个指针的计数 */
        int      t1;
        int      t2;
        
        GX_RECTANGLE drawto;  
        GX_CANVAS *mycanvas; 
        
        
        RTC_ReadClock();
            
        /* 第一个指针计数,用于旋转秒针 */
        t0 = g_tRTC.Sec * 6;
    
        /* 第二个指针计数,用于旋转分针 */
        t1 = g_tRTC.Min * 6;
    
        /* 第三个指针计数,用于旋转时针 */
        t2 = g_tRTC.Hour * 30;
    
        /* 默认的窗口绘制回调函数,即默认界面效果绘制 */
        gx_window_draw(widget);
    
        /* 定义一个矩形框,后续的2D绘制函数都是在这个矩形范围内绘制的 */
        gx_utility_rectangle_define(&drawto,
                                    WinPartialDraw.gx_rectangle_left, 
                                    WinPartialDraw.gx_rectangle_top,
                                    WinPartialDraw.gx_rectangle_right, 
                                    WinPartialDraw.gx_rectangle_bottom);
     
        /* 返回窗口对应的canvas画布 */
        gx_widget_canvas_get(widget, &mycanvas);
        
        
        /* 
          在指定的画布上启动绘图。此功能在内部被延迟绘图算法调用,GUIX在需要画布时自动执行更新。 
          但是允许应用程序绕过延期绘图算法并立即执行。
          首先调用gx_canvas_drawing_inititate在画布上绘画。
          然后调用所需的绘图函数,然后调用gx_canvas_drawing_complete即可。
        */
        gx_canvas_drawing_initiate(mycanvas, widget, &drawto);
        
        /* 表盘背景绘制 */
        gx_canvas_pixelmap_draw(WinPartialDraw.gx_rectangle_left,  
                                WinPartialDraw.gx_rectangle_top, 
                                (GX_PIXELMAP *)&DISPLAY_1_THEME_1_CLOCK_CLASSIC_BACKGROUND_pixelmap);
           
        /* 绘制时针 */       
        gx_canvas_pixelmap_rotate(WinPartialDraw.gx_rectangle_left, 
                                WinPartialDraw.gx_rectangle_top,
                                (GX_PIXELMAP *)&DISPLAY_1_THEME_1_CLOCK_STANDARD_HOUR_HAND_pixelmap, 
                                t2,
                                DISPLAY_1_THEME_1_CLOCK_STANDARD_HOUR_HAND_pixelmap.gx_pixelmap_width/2, 
                                DISPLAY_1_THEME_1_CLOCK_STANDARD_HOUR_HAND_pixelmap.gx_pixelmap_height/2); 
                                
        /* 绘制分针 */                    
        gx_canvas_pixelmap_rotate(WinPartialDraw.gx_rectangle_left, 
                                WinPartialDraw.gx_rectangle_top,
                                (GX_PIXELMAP *)&DISPLAY_1_THEME_1_CLOCK_STANDARD_MINUTE_HAND_pixelmap, 
                                t1,
                                DISPLAY_1_THEME_1_CLOCK_STANDARD_MINUTE_HAND_pixelmap.gx_pixelmap_width/2, 
                                DISPLAY_1_THEME_1_CLOCK_STANDARD_MINUTE_HAND_pixelmap.gx_pixelmap_height/2);  
         /* 绘制秒针 */                          
        gx_canvas_pixelmap_rotate(
                                WinPartialDraw.gx_rectangle_left, 
                                WinPartialDraw.gx_rectangle_top,
                                (GX_PIXELMAP *)&DISPLAY_1_THEME_1_CLOCK_STANDARD_SECOND_HAND_pixelmap, 
                                t0,
                                DISPLAY_1_THEME_1_CLOCK_STANDARD_SECOND_HAND_pixelmap.gx_pixelmap_width/2, 
                                DISPLAY_1_THEME_1_CLOCK_STANDARD_SECOND_HAND_pixelmap.gx_pixelmap_height/2);  
    
        /* 用于强制立即绘制,注意,务必和gx_canvas_drawing_initiate成对调用 */
        gx_canvas_drawing_complete(mycanvas, GX_TRUE);
        
    }
    •  这段代码的关键是函数gx_canvas_pixelmap_draw和gx_canvas_pixelmap_rotate,函数gx_canvas_pixelmap_draw用于绘制背景,而函数gx_canvas_pixelmap_rotate用于绘制旋转的时分秒指针。

    30.7 实验例程

    (注,如果是电阻屏,需要做触摸校准,校准方法看本教程附件章节A)

    配套例子:

    本章节配套了如下两个例子供大家移植参考:

    V7-2045_GUIX炫酷时钟表盘设计,结合硬件RTC

    V7-2046_GUIX Studio设计时钟表盘

    实验目的:

    1. 本章主要学习GUIX的炫酷实用时钟表盘设计。

    实验内容:

    1、共创建了如下几个任务,通过按下按键K1可以通过串口打印任务堆栈使用情况

    App Task Start任务  :启动任务,这里用作BSP驱动包处理。

    App Task MspPro任务 :消息处理,这里用作LED闪烁。

    App Task UserIF任务 :按键消息处理。

    App Task GUI任务    :GUI应用任务。

    App Task STAT任务   :统计任务。

    App Task IDLE任务   :空闲任务。

    GUIX System Thread  :GUI系统任务。

    System Timer Thread任务:系统定时器任务。

    实验效果:

    串口打印任务执行情况:

    IAR,MDK AC5和AC6工程可以串口打印任务执行情况:按开发板的按键K1可以打印,波特率 115200,数据位 8,奇偶校验位无,停止位 1:

     

    30.8 总结

    本章节主要为大家讲解了时钟表盘在GUIX中的显示方法,大家也可以尝试其它方式实现时钟表盘设计。

  • 相关阅读:
    iOS 获取全局唯一标示符
    iOS 获取全局唯一标示符
    如何让UIViewController自动弹出PickerView
    如何让UIViewController自动弹出PickerView
    防止NSTimer和调用对象之间的循环引用
    防止NSTimer和调用对象之间的循环引用
    inputAccessoryView,inputView
    @encode关键字
    @encode关键字
    用 Flask 来写个轻博客 (11) — M(V)C_创建视图函数
  • 原文地址:https://www.cnblogs.com/armfly/p/16118497.html
Copyright © 2020-2023  润新知