ucos_emwin_ucgui吧 关注:384贴子:3,095
  • 11回复贴,共1

【emWin实战教程V2.0】第39章 窗口管理器之定时器使用

只看楼主收藏回复

完整65章+12章附件教程下载地址:http://bbs.armfly.com/read.php?tid=19834
完整65章+12章附件教程下载地址:http://bbs.armfly.com/read.php?tid=19834
完整65章+12章附件教程下载地址:http://bbs.armfly.com/read.php?tid=19834
第39章 窗口管理器之定时器使用
本期教程为大家讲解窗口管理器之定时器使用方法,这个定时器使用起来比较简单,而且很实用,以后的项目工程中很多时候要用到,不过使用时有些小问题要特别注意,如果不注意的话,定时器将无法正确启动。
39.1 初学者重要提示
39.2 定时器功能介绍
39.3 桌面窗口上使用定时器实例
39.4 对话框上使用定时器实例
39.5 实验例程说明(RTOS)
39.6 实验例程说明(裸机)
39.7 总结


IP属地:河北1楼2017-02-04 17:27回复
    39.1 初学者重要提示
    1、特别注意定时器使用时的注意事项,在本章39.2小节详细讲解了,要不定时器无法正确启动。然后再结合本章教程给出的实例进行学习。
    2、窗口管理器这块的API函数应该是emWin手册所有章节中函数最多的,定时器的API函数也属于这部分。下图是中文版手册里面API函数位置:

    下图是英文版手册里面API函数的位置:


    IP属地:河北2楼2017-02-04 17:28
    回复
      2026-09-18 11:12:50
      广告
      不感兴趣
      开通SVIP免广告
      39.2定时器功能介绍
      STemWin中有四个定时器相关的API函数供用户调用。

      这四个函数都是简单易用,不过使用时有些问题还是要注意下,要不无法正确启动,初学者也是经常在这几个点犯错误,导致配置了定时器,却没有效果。
      1、WM_HTIMERWM_CreateTimer(WM_HWIN hWin, int UserId, int Period, int Mode)
      此函数用于创建定时器,注意,这个函数创建的定时器是单次的,也是说定时器时间到后定时器就不再工作了,如果还想继续使用,务必要在窗口回调函数的定时器消息WM_TIMER里面调用函数WM_RestartTimer重启此定时器。
      第1个参数 hWin填写窗口的句柄,即给那个窗口创建定时器。这个参数比较关键,很多初学者经常在这个参数上犯错误。如果是给对话框创建定时器,且对话框的主体是框架窗口FrameWin或者直接给框架窗口FrameWin创建定时器,此参数必须要使用函数WM_GetClientWindow获得框架窗口的客户区,这一点非常重要。如果对话框的主体是Windows或者直接给Windows窗口创建定时器,无需使用函数WM_GetClientWindow了,直接填句柄就可以了。
      第2个参数UserId填写此定时器的ID,设置ID的目的是方便同一个窗口创建了多个定时器的话,可以用来区分是哪个定时器。
      第3个参数Period是定时器周期,确切的说是溢出时间更贴切,因为此定时器不是自动重启的,仅执行一次,时间到后会给定时器所在窗口的回调函数发送WM_TIMER消息,如果要重新启动需要在此消息里面调用函数WM_RestartTimer重新启动。
      第4个参数暂时保留,未被使用。
      2、void WM_DeleteTimer(WM_HTIMERhTimer)
      此函数用于定时器删除,参数是定时器句柄(即调用函数WM_CreateTimer的返回值)。
      3、intWM_GetTimerId(WM_HTIMER hTimer);
      此函数用于获得定时器ID,参数是定时器句柄(即调用函数WM_CreateTimer的返回值)。
      4、void WM_RestartTimer(WM_HTIMERhTimer, int Period)
      此函数用于重启定时器。
      第1个参数是定时器句柄,即调用函数WM_CreateTimer的返回值。
      第2个参数是重新配置定时器的溢出时间。
      -----------------
      讲解完这些,也许初学者还有些模糊,没有关系,且看下面举的几个例子,看完后基本就都理解了。


      IP属地:河北3楼2017-02-04 17:28
      回复
        39.3 桌面窗口上使用定时器实例
        这个Demo主要是实现每隔1000ms改变一次桌面窗口的颜色,源代码如下(可以将其直接的复制到开发板或者模拟器上面运行)。
        #include "DIALOG.h"
        /*
        *********************************************************************************************************
        * 变量
        *********************************************************************************************************
        */
        GUI_COLOR _acColor[3] ={GUI_BLUE,GUI_RED,GUI_YELLOW}; //--------------(1)
        static charucBackColor;
        /*
        *********************************************************************************************************
        * 函 数名: _cbBkWindow
        * 功能说明: 桌面窗口回调函数
        * 形 参:无
        * 返 回值: 返回对话框句柄
        *********************************************************************************************************
        */
        static void _cbBkWindow(WM_MESSAGE * pMsg)
        {
        WM_HWINhWin = pMsg->hWin;
        switch(pMsg->MsgId)
        {
        /* 重绘消息 */
        caseWM_PAINT: //--------------(2)
        ucBackColor++;
        if(ucBackColor == 3)
        {
        ucBackColor= 0;
        }
        GUI_SetBkColor(_acColor[ucBackColor]);
        GUI_Clear();
        break;
        /* 定时器消息 */
        caseWM_TIMER: //--------------(3)
        WM_InvalidateWindow(hWin);
        WM_RestartTimer(pMsg->Data.v,1000);
        break;
        default:
        WM_DefaultProc(pMsg);
        }
        }
        /*
        *********************************************************************************************************
        * 函 数名: MainTask
        * 功能说明: GUI主函数
        * 形 参:无
        * 返 回值: 无
        *********************************************************************************************************
        */
        void MainTask(void)
        {
        WM_HTIMERhTimer;
        /* 初始emWin */
        GUI_Init();
        /* 设置桌面窗口回调函数 */
        WM_SetCallback(WM_HBKWIN,_cbBkWindow); //--------------(4)
        /* 为桌面窗口创建定时器,定时器溢出时间1000ms*/
        hTimer =WM_CreateTimer(WM_HBKWIN, 0, 1000, 0); //--------------(5)
        while(1)
        {
        GUI_Delay(10);
        }
        }
        1. 定义一个数组,里面有三种颜色,再定义一个变量,用于三种颜色的切换。
        2. 桌面窗口回调函数的重绘消息,每执行一次更新一次背景色。
        3. 定时器消息,这里要特别注意,如果想要定时器周期性执行,而不是只执行一次,必须得调用重启定时器函数WM_RestartTimer()。在这个消息里面将桌面窗口无效,从而会触发窗口管理器去执行WM_PAINT消息,这样就实现了定时修改桌面窗口背景色。
        4. 设置桌面窗口的回调函数。
        5. 创建定时器函数,溢出时间是1000ms。
        这个Demo的实际显示效果如下:


        IP属地:河北4楼2017-02-04 17:29
        回复
          39.4 对话框上使用定时器实例
          这个Demo的主要功能是在对话框上面实现一个计数功能,每100ms更新一次,下面是源码(可以将其直接的复制到开发板或者模拟器上面运行)
          #include "DIALOG.h"
          #include "stdio.h"
          /*
          *********************************************************************************************************
          * 变量
          *********************************************************************************************************
          */
          static int Count = 0;
          /*
          *********************************************************************************************************
          * GUI_WIDGET_CREATE_INFO类型数组
          *********************************************************************************************************
          */
          static const GUI_WIDGET_CREATE_INFO_aDialogCreate[] = {
          {FRAMEWIN_CreateIndirect, "armfly", 0, 0, 0, 320,240,0,0},
          {TEXT_CreateIndirect, "0000", GUI_ID_TEXT0, 30,30,300,48,0,0}
          };
          /*
          *********************************************************************************************************
          * 函 数名: _cbCallback
          * 功能说明: 对话框回调函数
          * 形 参:pMsg 回调参数
          * 返 回值: 无
          *********************************************************************************************************
          */
          static void _cbCallback(WM_MESSAGE * pMsg)
          {
          intNCode, Id;
          charbuf[10];
          WM_HWINhWin = pMsg->hWin;
          switch(pMsg->MsgId)
          {
          caseWM_INIT_DIALOG:
          //
          //初始化框架窗口
          //
          FRAMEWIN_SetFont(hWin,&GUI_Font24B_ASCII);
          FRAMEWIN_SetTextAlign(hWin,GUI_TA_VCENTER|GUI_TA_CENTER);
          FRAMEWIN_SetTitleHeight(hWin,30);
          //
          //初始化文本控件
          //
          TEXT_SetFont(WM_GetDialogItem(hWin,GUI_ID_TEXT0),&GUI_FontD36x48);
          break;
          /* 定时器消息 */
          caseWM_TIMER: //--------------(1)
          Count++;
          sprintf(buf, "%04d", Count);
          TEXT_SetText(WM_GetDialogItem(hWin,GUI_ID_TEXT0),(const char *)buf);
          WM_RestartTimer(pMsg->Data.v,100);
          break;
          caseWM_KEY:
          switch (((WM_KEY_INFO*)(pMsg->Data.p))->Key)
          {
          case GUI_KEY_ESCAPE:
          GUI_EndDialog(hWin, 1);
          break;
          case GUI_KEY_ENTER:
          GUI_EndDialog(hWin, 0);
          break;
          }
          break;
          caseWM_NOTIFY_PARENT:
          Id = WM_GetId(pMsg->hWinSrc);
          NCode = pMsg->Data.v;
          switch (Id)
          {
          case GUI_ID_OK:
          if(NCode==WM_NOTIFICATION_RELEASED)
          GUI_EndDialog(hWin, 0);
          break;
          case GUI_ID_CANCEL:
          if(NCode==WM_NOTIFICATION_RELEASED)
          GUI_EndDialog(hWin, 0);
          break;
          }
          break;
          default:
          WM_DefaultProc(pMsg);
          }
          }
          /*
          *********************************************************************************************************
          * 函 数名: MainTask
          * 功能说明: GUI主函数
          * 形 参:无
          * 返 回值: 无
          *********************************************************************************************************
          */
          void MainTask(void)
          {
          WM_HWINhDlg;
          WM_HTIMERhTimer;
          /* 初始emWin */
          GUI_Init();
          /*窗口使能使用内存设备,防止闪烁 */
          WM_SetCreateFlags(WM_CF_MEMDEV);
          /* 创建一个对话框 */
          hDlg =GUI_CreateDialogBox(_aDialogCreate, GUI_COUNTOF(_aDialogCreate),&_cbCallback, 0, 0, 0);
          /* 给对话框hDlg创建定时器,溢出时间是100ms */
          hTimer =WM_CreateTimer(WM_GetClientWindow(hDlg), 0, 100, 0); //--------------(2)
          while(1)
          {
          GUI_Delay(10);
          }
          }
          1. 定时器消息,在定时器消息中实现文件控件计数值的更新,每次计数值加1。
          2. 给对话框创建一个定时器,特别注意,这里需要获取对话框中客户区窗口的句柄才可以使用。
          这个例子的实际显示效果如下:


          IP属地:河北5楼2017-02-04 17:30
          回复
            39.5 实验例程说明(RTOS)
            配套例子:
            V6-550_STemWin实验_窗口管理器之定时器使用(RTOS)
            实验目的:
            1. 本实验主要学习窗口管理器之定时器使用方法。
            2. emWin功能的实现在MainTask.c文件里面。
            实验内容:
            1. K1按键按下,串口打印任务执行情况(波特率115200,数据位8,奇偶校验位无,停止位1)。
            2. K2按键按下,实现截图功能,将图片以BMP格式保存到SD卡中。
            3. GUI任务主要是给对话框创建了一个定时器,每100ms更新一次文件控件的计数值。
            4. 各个任务实现的功能如下:
            App Task Start 任务:实现按键和触摸扫描。
            App Task MspPro任务 :实现截图功能,将图片以BMP格式保存到SD卡中。
            App Task UserIF 任务:按键消息处理。
            App Task COM 任务:暂未使用。
            App Task GUI 任务:GUI任务。
            μCOS-III任务调试信息(按K1按键,串口打印):

            STemWin界面显示效果:
            800*480分辨率界面效果。

            STemWin动态内存配置:
            GUIConf.c文件中的配置如下:
            #define EX_SRAM 1/*1 used extern sram, 0 used internal sram */
            #if EX_SRAM
            #define GUI_NUMBYTES (1024*1024*8)
            #else
            #define GUI_NUMBYTES (100*1024)
            #endif
            通过宏定义来配置使用内部SRAM还是外部的SDRAM做为emWin的动态内存,当配置:
            #define EX_SRAM 1 表示使用外部SDRAM作为emWin动态内存,大小8MB。
            #define EX_SRAM 0 表示使用内部SRAM作为emWin动态内存,大小100KB。
            默认情况下,本教程配套的所有emWin例子都是用外部SDRAM作为emWin动态内存。


            IP属地:河北6楼2017-02-04 17:30
            回复
              39.6 实验例程说明(裸机)
              配套例子:
              V6-551_STemWin实验_窗口管理器之定时器使用(裸机)
              实验目的:
              1. 本实验主要学习窗口管理器之定时器使用方法。
              2. emWin功能的实现在MainTask.c文件里面。
              实验内容:
              1. emWin部分主要实现给对话框创建一个定时器,每100ms更新一次文件控件的计数值。
              STemWin界面显示效果:
              800*480分辨率界面效果。

              STemWin动态内存配置:
              GUIConf.c文件中的配置如下:
              #define EX_SRAM 1/*1 used extern sram, 0 used internal sram */
              #if EX_SRAM
              #define GUI_NUMBYTES (1024*1024*8)
              #else
              #define GUI_NUMBYTES (100*1024)
              #endif
              通过宏定义来配置使用内部SRAM还是外部的SDRAM做为emWin的动态内存,当配置:
              #define EX_SRAM 1 表示使用外部SDRAM作为emWin动态内存,大小8MB。
              #define EX_SRAM 0 表示使用内部SRAM作为emWin动态内存,大小100KB。
              默认情况下,本教程配套的所有emWin例子都是用外部SDRAM作为emWin动态内存。


              IP属地:河北8楼2017-02-04 17:31
              回复
                续39.6
                程序设计:
                栈大小分配:
                系统栈大小在startup_stm32f429_439xx.s文件中配置:

                栈大小的单位是字节,那么这里配置的系统栈大小就是8192字节。
                主函数初始化:
                /*
                *********************************************************************************************************
                * 函 数名: main
                * 功能说明: 标准c程序入口。
                * 形 参:无
                * 返 回值: 无
                *********************************************************************************************************
                */
                int main (void)
                {
                /*初始化外设 */
                bsp_Init();
                /* 进入emWin主函数 */
                MainTask();
                }
                硬件外设初始化
                硬件外设的初始化是在bsp.c文件实现:
                /*
                *********************************************************************************************************
                * 函 数名: bsp_Init
                * 功能说明: 初始化所有的硬件设备。该函数配置CPU寄存器和外设的寄存器并初始化一些全局变量。只需要调用一次
                * 形 参:无
                * 返 回值: 无
                *********************************************************************************************************
                */
                void bsp_Init(void)
                {
                /*
                由于ST固件库的启动文件已经执行了CPU系统时钟的初始化,所以不必再次重复配置系统时钟。
                启动文件配置了CPU主时钟频率、内部Flash访问速度和可选的外部SRAM FSMC初始化。
                系统时钟缺省配置为168MHz,如果需要更改,可以修改 system_stm32f4xx.c 文件
                */
                /*使能CRC 因为使用STemWin前必须要使能 */
                RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_CRC, ENABLE);
                /* 优先级分组设置为4,可配置0-15级抢占式优先级,0级子优先级,即不存在子优先级。*/
                NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
                SystemCoreClockUpdate(); /* 根据PLL配置更新系统时钟频率变量 SystemCoreClock */
                bsp_InitUart(); /* 初始化串口 */
                bsp_InitKey(); /* 初始化按键变量(必须在 bsp_InitTimer() 之前调用) */
                bsp_InitExtIO(); /*FMC总线上扩展了32位输出IO, 操作LED等外设必须初始化 */
                bsp_InitLed(); /* 初始LED指示灯端口 */
                bsp_InitI2C(); /* 配置I2C总线 */
                bsp_InitSPIBus(); /* 配置SPI总线 */
                bsp_InitSFlash(); /*初始化SPI Flash */
                bsp_InitExtSDRAM(); /* 初始化SDRAM*/
                bsp_DetectLcdType(); /* 检测触摸板和LCD面板型号, 结果存在全局变量g_TouchType, g_LcdType */
                TOUCH_InitHard(); /* 初始化配置触摸芯片 */
                LCD_ConfigLTDC(); /* 初始化配置LTDC */
                result =f_mount(&fs, "0:/", 0); /* 挂载文件系统 */
                }


                IP属地:河北9楼2017-02-04 17:32
                回复
                  2026-09-18 11:06:50
                  广告
                  不感兴趣
                  开通SVIP免广告
                  39.7 总结
                  本章节就为大家讲解这么多,窗口定时器简单实用,望初学者务必掌握,以后用到的地方还是很多的。


                  IP属地:河北10楼2017-02-04 17:32
                  回复
                    谢谢老师,今年学习的GUI,这篇帖子太有用了


                    IP属地:吉林来自Android客户端11楼2020-02-18 15:02
                    回复
                      大神你好,
                      我想在同一个窗口dialog,同时显示dht11的温湿度值和RTC时钟值。我现在只定义了一个窗口定时器,现在温湿度值显示正常了,可是只要把RTC值一加,程序就死机了,不知道是什么原因,困扰了好几天,也解决不了,不知道是什么原因?
                      谢谢,谢谢!


                      IP属地:陕西12楼2020-10-22 15:30
                      回复
                        怎么在同一个窗口简历两个定时器?


                        13楼2021-03-25 17:49
                        回复