前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【第3版emWin教程】第57章 emWin6.x的炫酷时钟表盘设计,结合硬件RTC

【第3版emWin教程】第57章 emWin6.x的炫酷时钟表盘设计,结合硬件RTC

作者头像
Simon223
发布2022-05-10 10:49:22
3080
发布2022-05-10 10:49:22
举报

教程不断更新中:http://www.armbbs.cn/forum.php?mod=viewthread&tid=98429

第57章       emWin6.x的炫酷时钟表盘设计,结合硬件RTC

本章节为大家讲解emWin中炫酷时钟,结合硬件RTC。

57.1 初学者重要提示

57.2 第1步,相关图标生成位图

57.3 第2步,开辟存储设备

57.4 第3步,初始化存储设备

57.5 第4步,创建时钟表盘窗口

57.6 第5步,最关键的窗口回调函数实现

57.7 实验例程说明(RTOS)

57.8 实验例程说明(裸机)

57.9 总结

57.1 初学者重要提示

1、 emWin实现时钟表盘的关键是实时图标旋转,即函数GUI_MEMDEV_RotateHQ的实现。

57.2 第1步,相关图标生成位图

位图的原始图片已经存到本章教程配套例子的Doc文件夹中,位图的生成方法详见本章教程的第15章,这里我们选择如下格式,时钟表盘,时针,分针和秒针都是同样的设置:

57.3 第2步,开辟存储设备

我们这里要开辟五个存储设备,大小都是250*250。特别注意开辟的存储设备格式要带alpha通道的8888颜色格式。

代码语言:javascript
复制
   /* 时钟表盘所需存储设备 */
hMemBK = GUI_MEMDEV_CreateFixed(0,0, bmclock_classic_background.XSize, bmclock_classic_background.YSize,
 GUI_MEMDEV_HASTRANS, GUI_MEMDEV_APILIST_32, GUI_COLOR_CONV_8888);
    
    /* 时钟秒针所需存储设备 */
hMemSec = GUI_MEMDEV_CreateFixed(0,0, bmclock_classic_background.XSize, bmclock_classic_background.YSize,
 GUI_MEMDEV_NOTRANS, GUI_MEMDEV_APILIST_32, GUI_COLOR_CONV_8888);

    /* 时钟分针所需存储设备 */
hMemMin = GUI_MEMDEV_CreateFixed(0, 0, bmclock_classic_background.XSize, 
bmclock_classic_background.YSize,
 GUI_MEMDEV_NOTRANS, GUI_MEMDEV_APILIST_32, GUI_COLOR_CONV_8888);

    /* 时钟小时所需存储设备 */
hMemHour = GUI_MEMDEV_CreateFixed(0, 0, bmclock_classic_background.XSize, 
bmclock_classic_background.YSize, 
GUI_MEMDEV_NOTRANS, GUI_MEMDEV_APILIST_32, GUI_COLOR_CONV_8888);
 
    /* 时钟目的存储所需存储设备 */
    hMemDST =GUI_MEMDEV_Cr

57.4 第3步,初始化存储设备

我们这里要给存储设备初始化一个数值,方便我们后面旋转指针使用:

代码语言:javascript
复制
/* 将时钟表盘绘制到存储设备 */
    GUI_MEMDEV_Select(hMemBK);
    GUI_SetBkColor(GUI_TRANSPARENT);
    GUI_Clear();
    GUI_DrawBitmap(&bmclock_classic_background, 0, 0); 
    GUI_MEMDEV_Select(0);
 
    /* 将秒针绘制到存储设备 */
    GUI_MEMDEV_Select(hMemSec);
    GUI_SetBkColor(GUI_TRANSPARENT);
    GUI_Clear();
    GUI_DrawBitmap(&bmclock_standard_second_hand, 
                    0, 
                    0); 
    GUI_MEMDEV_Select(0);

    /* 将分针绘制到存储设备 */
    GUI_MEMDEV_Select(hMemMin);
    GUI_SetBkColor(GUI_TRANSPARENT);
    GUI_Clear();
    GUI_DrawBitmap(&bmclock_standard_minute_hand, 0, 0);              
    GUI_MEMDEV_Select(0);

    /* 将时针绘制到存储设备 */
    GUI_MEMDEV_Select(hMemHour);
    GUI_SetBkColor(GUI_TRANSPARENT);
    GUI_Clear();
    GUI_DrawBitmap(&bmclock_standard_hour_hand, 
                    0, 
                    0); 
                    
    GUI_MEMDEV_Select(0);
  • 特别注意,我们这里的绘制是有技巧的,由于我们是带alpha通道的透明图片,所以这里绘制到存储设备,需要调用函数GUI_SetBkColor(GUI_TRANSPARENT),GUI_Clear(),否则绘制的图片是带黑色背景的。

57.5 第4步,创建时钟表盘窗口

为例方便移植和管理,我们把时钟表盘创建到一个独立的窗口上:

代码语言:javascript
复制
    /* 创建一个窗口,用于绘制时钟 */
    WM_CreateWindowAsChild((xSize - bmclock_classic_background.XSize)/2 , 
                           (ySize - bmclock_classic_background.YSize)/2, 
                           bmclock_classic_background.XSize,
                           bmclock_classic_background.YSize, 
                           WM_HBKWIN, 
                           WM_CF_SHOW, 
                           _cbClock, 
                           0);

57.6 第5步,最关键的窗口回调函数实现

代码实现如下:

代码语言:javascript
复制
/*
*********************************************************************************************************
*    函 数 名: CAM_Stop
*    功能说明: 停止DMA和DCMI
*    形    参: 无
*    返 回 值: 无
*********************************************************************************************************
*/
#include "MainTask.h"
void CAM_Stop(void)
{
    HAL_DCMI_Stop(&hdcmi);
}

void DMA1_Stream7_IRQHandler(void)
{
    HAL_DMA_IRQHandler(&hdma_dcmi);
}

void HAL_DCMI_FrameEventCallback(DCMI_HandleTypeDef *hdcmi)
{
    /* 关闭摄像 */
    CAM_Stop();
    WM_SendMessageNoPara(hWinMainTask, MSG_CAMERA);
    g_tCam.CaptureOk = 1;        /* 表示DMA传输结束 */
}

/*
*********************************************************************************************************
*    函 数 名: _cbDialog
*    功能说明: 对话框回调函数        
*    形    参: pMsg  回调参数 
*    返 回 值: 无
*********************************************************************************************************
*/
static void _cbDialog(WM_MESSAGE * pMsg) 
{
    static  WM_HTIMER hTimerCAMERA;

    switch (pMsg->MsgId) 
    {
        /* 接收到摄像头数据 */
        case MSG_CAMERA:
            hTimerCAMERA = WM_CreateTimer(pMsg->hWin, ID_TimerCAMERA, 2, 0);    
            break;
        
        case WM_TIMER:
            /* 删除定时器 */
            WM_DeleteTimer(hTimerCAMERA);
        
            /* 选择操作窗口 */
            WM_SelectWindow(hWinMainTask);
        
            /* Cache Clean和无效化 */
            SCB_CleanInvalidateDCache();
        
            /* 绘制到多缓冲里面 */
            GUI_MULTIBUF_Begin();
            //g_tCam.CaptureOk = 0;
            GUI_MEMDEV_WriteAt(hMem, 0, 0);
            GUI_MULTIBUF_End();
        
            WM_SelectWindow(WM_HBKWIN);
        
            /* 开始下次绘制 */
            CAM_Start1(uiDispMemAddr);    
            break;

        default:
            WM_DefaultProc(pMsg);
            break;
    }
}

/*
*********************************************************************************************************
*    函 数 名: _cbClock
*    功能说明: 时钟回调函数
*    形    参: pMsg 窗口回调消息
*    返 回 值: 无
*********************************************************************************************************
*/
static void _cbClock(WM_MESSAGE * pMsg) {
    GUI_MEMDEV_Handle ret;

    int      t0;   /* 用于三个指针的计数 */
    int      t1;
    int      t2;
    
    switch (pMsg->MsgId) {
        case WM_CREATE:
            /* 创建定时器 */
            WM_CreateTimer(pMsg->hWin, /* 接受信息的窗口的句柄 */
                            0,           /* 用户定义的Id。如果不对同一窗口使用多个定时器,此值可以设置为零。 */
                            10,        /* 周期,此周期过后指定窗口应收到消息*/
                            0);          /* 留待将来使用,应为0 */ 

            break;

        /* 定时1秒更新一次时间 */
        case WM_TIMER:
            WM_RestartTimer(pMsg->Data.v, 1000);

            RTC_ReadClock();

            /* 第一个指针计数,用于旋转秒针 */
            t0 = 360 -  g_tRTC.Sec * 6;

            /* 第二个指针计数,用于旋转分针 */
            t1 = 360 - g_tRTC.Min * 6;

            /* 第三个指针计数,用于旋转时针 */
            t2 = 360 -   g_tRTC.Hour * 30;

            /* 将相关内容绘制到存储设备hMemDST里面 */
            ret = GUI_MEMDEV_Select(hMemDST);
            GUI_SetBkColor(GUI_RED);
            GUI_Clear();

            /* 绘制时钟表盘 */
            GUI_MEMDEV_WriteAt(hMemBK,0, 0);

            /* 绘制时针 */
            GUI_MEMDEV_RotateHQ(hMemHour, hMemDST, 0, 0, t2 * 1000, 1000);

            /* 绘制分针 */
            GUI_MEMDEV_RotateHQ(hMemMin, hMemDST, 0, 0, t1 * 1000, 1000);

            /* 绘制秒针 */
            GUI_MEMDEV_RotateHQ(hMemSec, hMemDST, 0, 0, t0 * 1000, 1000);

            GUI_MEMDEV_Select(ret);
            
            /* 执行窗口无效化,会触发执行WM_PAINT消息 */
            WM_InvalidateWindow(pMsg->hWin);
            break;

        case WM_PAINT:
            GUI_MEMDEV_WriteAt(hMemDST, (xSize - bmclock_classic_background.XSize)/2 , 
(ySize - bmclock_classic_background.YSize)/2);
            break;

        default:
            WM_DefaultProc(pMsg);
            break;
    }
}
  • WM_CREATE:

创建了一个定时器。

  •  WM_TIMER:

1、 函数WM_RestartTimer设置每秒更新1次。

2、 函数RTC_ReadClock用于读取硬件定时器实时时钟。

3、 通过GUI_MEMDEV_Select实现时钟表盘,时针,分针和秒针绘制到存储设备hMemDST里面。

4、 函数GUI_MEMDEV_RotateHQ用于旋转指针。

5、 函数WM_InvalidateWindow实现窗口无效化,从而会触发WM_PAINT消息的执行。

  • WM_PAINT:

通过函数GUI_MEMDEV_WriteAt整体绘制时钟表盘到界面上。

57.7 实验例程说明(RTOS)

配套例子:

V7-579_emWin6.x炫酷时钟表盘设计,结合硬件RTC(裸机)

V7-580_emWin6.x炫酷时钟表盘设计,结合硬件RTC(RTOS)

实验目的:

  1. 学习emWin上动态展示摄像头采集数据。
  2. emWin功能的实现在MainTask.c文件里面。

实验内容:

1、K1按键按下,串口或者RTT打印任务执行情况(串口波特率115200,数据位8,奇偶校验位无,停止位1)。

2、(1) 凡是用到printf函数的全部通过函数App_Printf实现。

(2) App_Printf函数做了信号量的互斥操作,解决资源共享问题。

3、默认上电是通过串口打印信息,如果使用RTT打印信息:

MDK AC5,MDK AC6或IAR通过使能bsp.h文件中的宏定义为1即可

#define Enable_RTTViewer  1

4、各个任务实现的功能如下:

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

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

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

App Task COM   任务 :暂未使用。

App Task GUI    任务 :GUI任务。

μCOS-III任务调试信息(按K1按键,串口打印):

RTT 打印信息方式:

程序设计:

任务栈大小分配:

μCOS-III任务栈大小在app_cfg.h文件中配置:

#define  APP_CFG_TASK_START_STK_SIZE                      512u

#define  APP_CFG_TASK_MsgPro_STK_SIZE                     2048u

#define  APP_CFG_TASK_COM_STK_SIZE                        512u

#define  APP_CFG_TASK_USER_IF_STK_SIZE                    512u

#define  APP_CFG_TASK_GUI_STK_SIZE                        2048u

任务栈大小的单位是4字节,那么每个任务的栈大小如下:

App Task Start   任务 :2048字节。

App Task MspPro任务 :8192字节。

App Task UserIF  任务 :2048字节。

App Task COM   任务 :2048字节。

App Task GUI    任务 :8192字节。

系统栈大小分配:

μCOS-III的系统栈大小在os_cfg_app.h文件中配置:

#define  OS_CFG_ISR_STK_SIZE                      512u     

系统栈大小的单位是4字节,那么这里就是配置系统栈大小为2KB

emWin动态内存配置:

GUIConf.c文件中的配置如下:

代码语言:javascript
复制
#define EX_SRAM   1/*1 used extern sram, 0 used internal sram */

#if EX_SRAM
#define GUI_NUMBYTES  (1024*1024*24)
#else
#define GUI_NUMBYTES  (100*1024)
#endif

通过宏定义来配置使用内部SRAM还是外部的SDRAM做为emWin的动态内存,当配置:

#define  EX_SRAM     1 表示使用外部SDRAM作为emWin动态内存,大小24MB。

#define  EX_SRAM     0 表示使用内部SRAM作为emWin动态内存,大小100KB。

默认情况下,本教程配套的所有emWin例子都是用外部SDRAM作为emWin动态内存。

emWin界面显示效果:

800*480分辨率界面效果。

57.8 实验例程说明(裸机)

配套例子:

V7-579_emWin6.x炫酷时钟表盘设计,结合硬件RTC(裸机)

V7-580_emWin6.x炫酷时钟表盘设计,结合硬件RTC(RTOS)

实验目的:

  1. 学习emWin上动态展示摄像头采集数据。
  2. emWin功能的实现在MainTask.c文件里面。

emWin界面显示效果:

800*480分辨率界面效果。

emWin动态内存配置:

GUIConf.c文件中的配置如下:

代码语言:javascript
复制
#define EX_SRAM   1/*1 used extern sram, 0 used internal sram */

#if EX_SRAM
#define GUI_NUMBYTES  (1024*1024*24)
#else
#define GUI_NUMBYTES  (100*1024)
#endif

通过宏定义来配置使用内部SRAM还是外部的SDRAM做为emWin的动态内存,当配置:

#define  EX_SRAM     1 表示使用外部SDRAM作为emWin动态内存,大小24MB。

#define  EX_SRAM     0 表示使用内部SRAM作为emWin动态内存,大小100KB。

默认情况下,本教程配套的所有emWin例子都是用外部SDRAM作为emWin动态内存。

57.9 总结

本章节主要为大家讲解了炫酷时钟显示方法,大家也可以尝试其它方式实现动态展示。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2022-04-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 第57章       emWin6.x的炫酷时钟表盘设计,结合硬件RTC
    • 57.1 初学者重要提示
      • 57.2 第1步,相关图标生成位图
        • 57.3 第2步,开辟存储设备
          • 57.4 第3步,初始化存储设备
            • 57.5 第4步,创建时钟表盘窗口
              • 57.6 第5步,最关键的窗口回调函数实现
                • 57.7 实验例程说明(RTOS)
                  • 57.8 实验例程说明(裸机)
                    • 57.9 总结
                    相关产品与服务
                    对象存储
                    对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
                    领券
                    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档