前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【STM32H7】第29章 ThreadX GUIX的摄像头OV7670动态图像显示

【STM32H7】第29章 ThreadX GUIX的摄像头OV7670动态图像显示

作者头像
Simon223
发布2022-03-10 14:43:00
3980
发布2022-03-10 14:43:00
举报

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

第29章 ThreadX GUIX的摄像头OV7670动态图像显示

本章节为大家讲解ThreadX GUIX中实现摄像头图像的动态展示。

29.1初学者重要提示

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

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

29.4 第3步,开辟摄像头图像空间

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

29.6 第6步,窗口绘制回调里面绘制图像并开启下一帧传输

29.7 实验例程

29.8 总结

29.1 初学者重要提示

  1. 务必看第16章局部刷新的实现。
  2. 本章配套了320*240和640*480两种分辨率图像显示案例。
  3. GUIX中实现摄像头动态图像展示的关键是开辟一个存储设备,每次摄像头采集的一帧数据通道DMA传输到缓冲里面后,将其通过存储设备绘制到GUIX里面。

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

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

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

29.3.1 窗口事件回调设置

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

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

29.3.2 窗口绘制回调设置

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

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

29.4 第3步,开辟摄像头图像空间

将SDRAM后2MB的空间作为摄像头图像空间:

#define SDRAM_CAMERA (0xC0000000 + 30 * 1024 * 1024)

29.5 第4步,摄像头DMA完整中断发消息

一帧640*480图像传输完毕后,DMA中断实现代码如下:

代码语言:javascript
复制
/*
*********************************************************************************************************
*    函 数 名: CAM_Stop
*    功能说明: 停止DMA和DCMI
*    形    参: 无
*    返 回 值: 无
*********************************************************************************************************
*/
#include   "gx_api.h"
GX_EVENT event;

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();
     event.gx_event_type = 0x40000000;
     gx_system_event_send(&event);
    g_tCam.CaptureOk = 1;        /* 表示DMA传输结束 */
}
  • 上面代码中红色代码是关键,这里是发送自定义消息给GUIX的窗口回调函数。

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

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

代码语言:javascript
复制
/* 摄像头图像绘制区 */
GX_RECTANGLE WinPartialDraw =  {0, 0, 640, 480};

/*
*********************************************************************************************************
*    函 数 名: _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:

            /* 默认事件处理 */
            gx_window_event_process(widget, event_ptr);
            break;

        /* 接收到摄像头图像数据 */
        case 0x40000000:
            /* 设置窗口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执行绘制回调函数。

代码语言:javascript
复制
#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个参数是大家要更新的窗口句柄。
  • 第2个参数是要更新的区域。更新区域是GX_RECTANGLE类型结构体,此结构体定义了矩形区域。

29.7 第6步,窗口绘制回调里面绘制图像并开启下一帧传输

实现代码如下:

代码语言:javascript
复制
/* 摄像头位图定义 */
GX_PIXELMAP CAMREA_pixelmap =
{
    0x00000001,                              /* major version                  */
    0x00000000,                              /* minor version                  */
    0,                                       /* flags                          */
    GX_COLOR_FORMAT_565RGB,                  /* Format                         */
    (GX_UBYTE *) 0,
    640*480*2,    /* the size of pixelmap_data*/
    NULL,
    0,                                       /* auxiliary data size            */
    0x00,                                    /* used for transparent iamges    */
    640,                                     /* width in pixel                 */
    480                                      /* height in pixel                */
};

/*
*********************************************************************************************************
*    函 数 名: _cbWindow0
*    功能说明: 窗口window的绘制回调函数
*    形    参: widget     窗口句柄 
*    返 回 值: 无
*********************************************************************************************************
*/
VOID _cbWindow0(GX_WINDOW *widget)
{
    GX_RECTANGLE drawto;  
    GX_CANVAS *mycanvas; 
    
    /* 默认的窗口绘制回调函数,即默认界面效果绘制 */
    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,
 &CAMREA_pixelmap);

    /* 用于强制立即绘制,注意,务必和gx_canvas_drawing_initiate成对调用 */
    gx_canvas_drawing_complete(mycanvas, GX_TRUE);
    
    /* 更新完毕开启下一帧 */
    CAM_Start1(SDRAM_CAMERA);
}
  • 这段代码的关键是函数gx_canvas_pixelmap_draw,我们提前定义好位图大小CAMREA_pixelmap,然后更新设置的WinPartialDraw局部区域。
  • 函数CAM_Start1用于启动下一帧。

29.8 实验例程

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

配套例子:

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

  • V7-2041_GUIX Camera 320x240
  • V7-2042_GUIX Studio Camera 320x240
  • V7-2043_GUIX Camera 640x480
  • V7-2044_GUIX Studio Camera 640x480

实验目的:

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:

29.9 总结

本章节主要为大家讲解了摄像头动态图像在GUIX中的显示方法,大家也可以尝试其它方式实现动态图像展示。

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

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

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 第29章 ThreadX GUIX的摄像头OV7670动态图像显示
    • 29.1 初学者重要提示
      • 29.2 第1步,GUIX Studio创建空白窗口
        • 29.3 第2步,GUIX Studio设置窗口回调
          • 29.3.1 窗口事件回调设置
          • 29.3.2 窗口绘制回调设置
        • 29.4 第3步,开辟摄像头图像空间
          • 29.5 第4步,摄像头DMA完整中断发消息
            • 29.6 第5步,窗口回调函数里面设置局部Dirty
              • 29.7 第6步,窗口绘制回调里面绘制图像并开启下一帧传输
                • 29.8 实验例程
                  • 29.9 总结
                  相关产品与服务
                  访问管理
                  访问管理(Cloud Access Management,CAM)可以帮助您安全、便捷地管理对腾讯云服务和资源的访问。您可以使用CAM创建子用户、用户组和角色,并通过策略控制其访问范围。CAM支持用户和角色SSO能力,您可以根据具体管理场景针对性设置企业内用户和腾讯云的互通能力。
                  领券
                  问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档