天天看點

【STM32H7】第30章 ThreadX GUIX炫酷實用的時鐘表盤設計,結合硬體RTC實時時鐘

​​​​

第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章一樣。建立的界面效果如下:

【STM32H7】第30章 ThreadX GUIX炫酷實用的時鐘表盤設計,結合硬體RTC實時時鐘

30.3 第2步,GUIX Studio設定視窗回調

30.3.1        視窗事件回調設定

下面我們為視窗控件設定一個Event Function,此功能是視窗的事件回調函數。在這個回調函數裡面,大家可以處理各種事件。

【STM32H7】第30章 ThreadX GUIX炫酷實用的時鐘表盤設計,結合硬體RTC實時時鐘

這裡為Event Function設定的回調函數名為_cbEventWindow0,然後就可以使用GUIX Studio生成新的代碼。生成的代碼移植到硬體平台的方法看第12章即可。

30.3.2        視窗繪制回調設定

下面我們為視窗設定一個Draw Function,此功能是視窗的繪制回調函數。在這個回調函數裡面,大家可以實作各種2D繪制。

【STM32H7】第30章 ThreadX GUIX炫酷實用的時鐘表盤設計,結合硬體RTC實時時鐘

這裡為Draw Function設定的回調函數名為_cbWindow0,然後就可以使用GUIX Studio生成新的代碼。

30.4 第3步,添加圖檔

将時鐘表盤背景圖檔,時針,分針和秒針都添加進來:

【STM32H7】第30章 ThreadX GUIX炫酷實用的時鐘表盤設計,結合硬體RTC實時時鐘

 時鐘圖檔都放在了clock檔案夾中(本章教程配套例子的檔案裡面)

【STM32H7】第30章 ThreadX GUIX炫酷實用的時鐘表盤設計,結合硬體RTC實時時鐘

四個添加的圖檔都要如下方式逐一設定:

【STM32H7】第30章 ThreadX GUIX炫酷實用的時鐘表盤設計,結合硬體RTC實時時鐘

這個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任務:系統定時器任務。

實驗效果:

【STM32H7】第30章 ThreadX GUIX炫酷實用的時鐘表盤設計,結合硬體RTC實時時鐘

序列槽列印任務執行情況:

IAR,MDK AC5和AC6工程可以序列槽列印任務執行情況:按開發闆的按鍵K1可以列印,波特率 115200,資料位 8,奇偶校驗位無,停止位 1:

【STM32H7】第30章 ThreadX GUIX炫酷實用的時鐘表盤設計,結合硬體RTC實時時鐘

30.8 總結

本章節主要為大家講解了時鐘表盤在GUIX中的顯示方法,大家也可以嘗試其它方式實作時鐘表盤設計。