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

2023-12-17 00:18

本文主要是介绍【STM32H7】第29章 ThreadX GUIX的摄像头OV7670动态图像显示,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

最新教程下载:第3版emWin教程和ThreadX GUIX教程开工,双管齐下,GUIX更新至第29章,emWin更新至第56章(2022-01-10) - uCOS & uCGUI & emWin & embOS & TouchGFX & ThreadX - 硬汉嵌入式论坛 - Powered by Discuz!

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

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

目录

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 总结


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中断实现代码如下:

/*
*********************************************************************************************************
*	函 数 名: 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可以触发重绘:

/* 摄像头图像绘制区 */
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执行绘制回调函数。

#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步,窗口绘制回调里面绘制图像并开启下一帧传输

实现代码如下:

/* 摄像头位图定义 */
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中的显示方法,大家也可以尝试其它方式实现动态图像展示。

这篇关于【STM32H7】第29章 ThreadX GUIX的摄像头OV7670动态图像显示的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


原文地址:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.chinasem.cn/article/502418

相关文章

C#如何动态创建Label,及动态label事件

《C#如何动态创建Label,及动态label事件》:本文主要介绍C#如何动态创建Label,及动态label事件,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录C#如何动态创建Label,及动态label事件第一点:switch中的生成我们的label事件接着,

SpringCloud动态配置注解@RefreshScope与@Component的深度解析

《SpringCloud动态配置注解@RefreshScope与@Component的深度解析》在现代微服务架构中,动态配置管理是一个关键需求,本文将为大家介绍SpringCloud中相关的注解@Re... 目录引言1. @RefreshScope 的作用与原理1.1 什么是 @RefreshScope1.

MyBatis 动态 SQL 优化之标签的实战与技巧(常见用法)

《MyBatis动态SQL优化之标签的实战与技巧(常见用法)》本文通过详细的示例和实际应用场景,介绍了如何有效利用这些标签来优化MyBatis配置,提升开发效率,确保SQL的高效执行和安全性,感... 目录动态SQL详解一、动态SQL的核心概念1.1 什么是动态SQL?1.2 动态SQL的优点1.3 动态S

Vue 调用摄像头扫描条码功能实现代码

《Vue调用摄像头扫描条码功能实现代码》本文介绍了如何使用Vue.js和jsQR库来实现调用摄像头并扫描条码的功能,通过安装依赖、获取摄像头视频流、解析条码等步骤,实现了从开始扫描到停止扫描的完整流... 目录实现步骤:代码实现1. 安装依赖2. vue 页面代码功能说明注意事项以下是一个基于 Vue.js

mybatis-plus 实现查询表名动态修改的示例代码

《mybatis-plus实现查询表名动态修改的示例代码》通过MyBatis-Plus实现表名的动态替换,根据配置或入参选择不同的表,本文主要介绍了mybatis-plus实现查询表名动态修改的示... 目录实现数据库初始化依赖包配置读取类设置 myBATis-plus 插件测试通过 mybatis-plu

Linux虚拟机不显示IP地址的解决方法(亲测有效)

《Linux虚拟机不显示IP地址的解决方法(亲测有效)》本文主要介绍了通过VMware新装的Linux系统没有IP地址的解决方法,主要步骤包括:关闭虚拟机、打开VM虚拟网络编辑器、还原VMnet8或修... 目录前言步骤0.问题情况1.关闭虚拟机2.China编程打开VM虚拟网络编辑器3.1 方法一:点击还原VM

基于Canvas的Html5多时区动态时钟实战代码

《基于Canvas的Html5多时区动态时钟实战代码》:本文主要介绍了如何使用Canvas在HTML5上实现一个多时区动态时钟的web展示,通过Canvas的API,可以绘制出6个不同城市的时钟,并且这些时钟可以动态转动,每个时钟上都会标注出对应的24小时制时间,详细内容请阅读本文,希望能对你有所帮助...

CSS模拟 html 的 title 属性(鼠标悬浮显示提示文字效果)

《CSS模拟html的title属性(鼠标悬浮显示提示文字效果)》:本文主要介绍了如何使用CSS模拟HTML的title属性,通过鼠标悬浮显示提示文字效果,通过设置`.tipBox`和`.tipBox.tipContent`的样式,实现了提示内容的隐藏和显示,详细内容请阅读本文,希望能对你有所帮助... 效

使用Python开发一个图像标注与OCR识别工具

《使用Python开发一个图像标注与OCR识别工具》:本文主要介绍一个使用Python开发的工具,允许用户在图像上进行矩形标注,使用OCR对标注区域进行文本识别,并将结果保存为Excel文件,感兴... 目录项目简介1. 图像加载与显示2. 矩形标注3. OCR识别4. 标注的保存与加载5. 裁剪与重置图像

Vue中动态权限到按钮的完整实现方案详解

《Vue中动态权限到按钮的完整实现方案详解》这篇文章主要为大家详细介绍了Vue如何在现有方案的基础上加入对路由的增、删、改、查权限控制,感兴趣的小伙伴可以跟随小编一起学习一下... 目录一、数据库设计扩展1.1 修改路由表(routes)1.2 修改角色与路由权限表(role_routes)二、后端接口设计