【第3版emWin教程】第56章 emWin6.x的摄像头OV7670动态图形显示

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

第56章       emWin6.x的摄像头OV7670动态图形显示

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

目录

56.1 初学者重要提示

56.2 第1步,开辟存储设备

56.3 第2步,摄像头DMA传输完成中断发消息

56.4 第3步,窗口回调函数里面绘制图像并开启下次传输

56.5 实验例程说明(RTOS)

56.6 实验例程说明(裸机)

56.7 总结


56.1 初学者重要提示

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

 

56.2 第1步,开辟存储设备

我们这里以640*480分辨率为例进行说明,实现代码如下:

/*
*********************************************************************************************************
*	函 数 名: MainTask
*	功能说明: GUI主函数
*	形    参: 无
*	返 回 值: 无
*********************************************************************************************************
*/
void MainTask(void) 
{

//省略未写
	
	/* 创建存储设备,用于加载摄像头数据 */
	hMem = GUI_MEMDEV_CreateEx(0, 0, 640, 480, GUI_MEMDEV_NOTRANS);
	uiDispMemAddr = (uint32_t)GUI_MEMDEV_GetDataPtr(hMem);
	
    /* 屏幕显示后点亮,有效防止瞬间高亮 */
    GUI_Delay(200);
	LCD_SetBackLight(255);

	/* 初始摄像头 */
	bsp_InitCamera();
	CAM_Start(uiDispMemAddr);
		
	/* 临时加载个红色背景 */
	GUI_MEMDEV_Select(hMem);
	GUI_SetBkColor(GUI_RED);
	GUI_Clear();
	GUI_MEMDEV_Select(0);
	
//省略未写

}
  •   通过函数GUI_MEMDEV_CreateEx创建摄像头所需的缓冲器,我们这里是640*480分辨率,所以存储设备也创建这么大即可。
  •   函数bsp_InitCamera初始化摄像头,然后函数CAM_Start先启动一次传输。
  •   函数GUI_MEMDEV_Select实现一个临时的绘制,方便查看是否申请存储设备成功。

56.3 第2步,摄像头DMA传输完成中断发消息

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

/*
*********************************************************************************************************
*	函 数 名: 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传输结束 */
}
  •   上面代码中红色代码是关键,这里是发送自定义消息给emWin的窗口回调函数。

56.4 第3步,窗口回调函数里面绘制图像并开启下次传输

代码实现如下:

/*
*********************************************************************************************************
*	函 数 名: 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;
	}
}
  1.   窗口回调消息MSG_CAMERA的处理比较关键, 其实是可以直接在这个消息里处理,但是这个里面直接处理,三缓冲效果就无法正常执行了,也就是图形会有撕裂,所以我们这里简单开个单次定时器,在定时器消息里面执行图形绘制。
  2.   定时器消息里面有个三个知识点:
  •   WM_SelectWindow实现将图像显示到本窗口上。在WM_PAINT消息里面的话,就不需要调用此函数了,其它消息里面需要调用。
  •   函数GUI_MULTIBUF_Begin和GUI_MULTIBUF_End实现三缓冲绘制,将其整体加载后绘制,防止撕裂。
  •   函数GUI_MEMDEV_WriteAt实现图像实际绘制。

56.5 实验例程说明(RTOS)

配套例子:

V7-576_emWin6.x实验_摄像头动态采集展示(RTOS,320x240)

V7-578_emWin6.x实验_摄像头动态采集展示(RTOS,640x480)

实验目的:

  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文件中的配置如下:

#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分辨率界面效果。

 

56.6 实验例程说明(裸机)

配套例子:

V7-575_emWin6.x实验_摄像头动态采集展示(裸机,320x240)

V7-577_emWin6.x实验_摄像头动态采集展示(裸机,640x480)

实验目的:

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

emWin界面显示效果:

800*480分辨率界面效果。

 emWin动态内存配置:

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

#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动态内存。

56.7 总结

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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值