【正点原子STM32连载】 第五十三章 照相机实验 摘自【正点原子】APM32F407最小系统板使用指南

1)实验平台:正点原子stm32f103战舰开发板V4

2)平台购买地址:https://detail.tmall.com/item.htm?id=609294757420

3)全套实验源码+手册+视频下载地址: http://www.openedv.com/thread-340252-1-1.html##

第五十三章 照相机实验

本章将介绍使用APM32F407模拟照相机将摄像头采集到的图像数据以BMP或JPEG的文件格式保存至SD中,是前面章节中SD卡驱动、摄像头驱动、FATFS、字库管理库、图片编解码库等的综合应用。通过本章的学习,读者将学习到编码BMP文件以及保存摄像头采集到图像数据的保存。

本章分为如下几个小节:

53.1 硬件设计

53.2 程序设计

53.3 下载验证

53.1 硬件设计

53.1.1 例程功能

  1. 程序运行后会先检查SD卡,若检测不到SD卡则无法进行本实验,若SD无法访问则后续不能保存图片文件
  2. 初始化完成后,LCD实时显示摄像头采集到的数据
  3. 按下KEY0或KEY_UP按键,可分别进行拍摄并保存BMP或JPG格式的图片文件至SD卡
  4. LED1闪烁,提示DCI捕获到一帧数据
  5. LED0闪烁,指示程序正在运行
    53.1.2 硬件资源
  6. LED
    LED0 - PF9
    LED1 - PF10
  7. 按键
    KEY0 - PE4
    KEY_UP - PA0
  8. 正点原子 2.8/3.5/4.3/7/10寸TFTLCD模块(仅限MCU屏,16位8080并口驱动)
  9. ATK-MC2640摄像头模块
    OV_D0~D7 - PC6/PC7/PC8/PC9/PC11/PB6/PE5/PE6
    OV_SCL - PD6
    OV_SDA - PD7
    OV_VSYNC - PB7
    OV_HREF - PA4
    OV_PCLK - PA6
    OV_PWDN - PG9
    OV_RESET - PG15
    OV_XCLK - PA8
  10. SD卡(SDIO驱动)
  11. NOR Flash(SPI驱动)
    53.1.3 原理图
    本章实验涉及的SD卡、摄像头、LCD等的连接原理图,请读者自行查看前面对应章节中的连接原理图。
    53.2 程序设计
    53.2.1 实验应用代码
    本章实验的应用代码,如下所示:
c 复制代码
int main(void)
{
    uint8_t t = 0;
    uint8_t key;
    uint8_t res;
    uint8_t sd_ok = 1;
    uint8_t *pname;
    
    NVIC_ConfigPriorityGroup(NVIC_PRIORITY_GROUP_3);	/* 设置中断优先级分组为组3 */
    sys_apm32_clock_init(336, 8, 2, 7);					/* 配置系统时钟 */
    delay_init(168);										/* 初始化延时功能 */
    usart_init(115200);									/* 初始化串口 */
    led_init();											/* 初始化LED */
    key_init();											/* 初始化按键 */
    lcd_init();											/* 初始化LCD */
    piclib_init();										/* 初始化画图 */
    sram_init();											/* 初始化外部SRAM */
    my_mem_init(SRAMIN);								/* 初始化内部SRAM内存池 */
    my_mem_init(SRAMCCM);								/* 初始化CCM内存池 */
    my_mem_init(SRAMEX);								/* 初始化外部SRAM内存池 */
    exfuns_init();										/* 为exfuns申请内存 */
    f_mount(fs[0], "0:", 1);							/* 挂载SD卡 */
    f_mount(fs[1], "1:", 1);							/* 挂载NOR Flash */
    
    while (ov2640_init() != 0)							/* 初始化OV2640 */
    {
    		/* 摄像头错误,代码省略 */
    }
    
    sw_sdcard_mode();
    while (sd_init() != SD_OK)							/* 初始化SD卡 */
    {
    		/* SD卡错误,代码省略 */
    }
    
    while (fonts_init() != 0)							/* 检查字库 */
    {
    		/* 字库错误,代码省略 */
    }
    
    text_show_string(30, 50, 200, 16, "正点原子APM32开发板", 16, 0, RED);
    text_show_string(30, 70, 200, 16, "照相机实验", 16, 0, RED);
    text_show_string(30, 90, 200, 16, "KEY0:拍照(bmp格式)", 16, 0, RED);
    text_show_string(30, 110, 200, 16, "KEY_UP:拍照(jpg格式)", 16, 0, RED);
    
    /* 创建PHOTO文件夹 */
    res = (uint8_t)f_mkdir("0:/PHOTO");
    if ((res != (uint8_t)FR_EXIST) && (res != 0))
    {
    		/* SD卡错误,代码省略 */
    }
    
    /* 申请内存 */
    g_dci_line_buf[0] = (uint32_t *)mymalloc(SRAMIN,
    											JPEG_LINE_SIZE * sizeof(uint32_t));
    g_dci_line_buf[1] = (uint32_t *)mymalloc(SRAMIN,
    											JPEG_LINE_SIZE * sizeof(uint32_t));
    g_jpeg_data_buf = (uint32_t *)mymalloc(SRAMEX, JPEG_BUF_SIZE);
    pname = (uint8_t *)mymalloc(SRAMIN, 30);
    while (	(g_dci_line_buf[0] == NULL) ||
    			(g_dci_line_buf[1] == NULL) ||
    			(g_jpeg_data_buf == NULL) ||
    (pname == NULL))
    {
    		/* 内存分配错误,代码省略 */
    }
    
    sw_ov2640_mode();
    ov2640_rgb565_mode();							/* 配置OV2640为RGB565模式 */
    dci_init();											/* 初始化DCI */
    dci_dma_init(	(uint32_t)&(LCD->LCD_RAM),			/* 配置DCI DMA */
    					0,
    					1,
    					DMA_MEMORY_DATA_SIZE_HALFWORD,
    					DMA_MEMORY_INC_DISABLE);
    ov2640_outsize_set(lcddev.width, lcddev.height);	/* 全屏缩放 */
    dci_start();											/* 启动DCI传输 */
    ov2640_flash_intctrl();								/* 内部控制闪光灯 */
    
    while (1)
    {
    		t++;
    		key = key_scan(0);
    		
    		if (key != 0)									/* 有按键按下 */
    		{
    			dci_stop();									/* 先禁止DCI传输 */
    			if (sd_ok == 1)								/* SD卡正常 */
    			{
    				sw_sdcard_mode();						/* 切换为SD卡模式 */
    				switch (key)
    				{
    					case KEY0_PRES:
    					{
    						/* 得到BMP格式文件名 */
    						camera_new_pathname(pname, 0);
    						/* 编码并保存BMP文件 */
    						res = bmp_encode(	pname,
    											0,
    											0,
    											lcddev.width,
    											lcddev.height,
    											0);
    						break;
    					}
    					case WKUP_PRES:
    					{
    						/* 得到JPG格式文件名 */
    						camera_new_pathname(pname, 1);
    						/* 保存OV2640输出的JPEG数据到JPG文件 */
    						res = ov2640_jpg_photo(pname);
    						ov2640_outsize_set(lcddev.width, lcddev.height);
    						break;
    					}
    					default:
    					{
    						break;
    					}
    				}
    				sw_ov2640_mode();						/* 切换为OV2640模式 */
    				if (res != 0)
    				{
    					text_show_string(30, 130, 240, 16,
    									"写入文件错误!", 16, 0, RED);
    				}
    				else
    				{
    					text_show_string(10, 130, 240, 16, "拍照成功!", 16, 0, RED);
    					text_show_string(10, 150, 240, 16, "保存为:", 16, 0, RED);
    					text_show_string(10 + 56, 150, 240, 16,
    									(char*)pname, 16, 0, RED);
    				}
    				
    				delay_ms(1000);
    			}
    			else/* SD卡不可用 */
    			{
    				text_show_string(30, 130, 240, 16, "SD卡错误!", 16, 0, RED);
    				text_show_string(30, 150, 240, 16, "拍照功能不可用!", 16, 0, RED);
    			}
    			delay_ms(2000);
    			dci_start();								/* 恢复DCI传输 */
    		}
    		
    		if (t == 20)
    		{
    			LED0_TOGGLE();
    			t = 0;
    		}
    		
    		delay_ms(10);
    }
}

可以看到,本章实验实际上是前面章节中SD卡驱动、摄像头驱动、FATFS、字库管理库、图片编解码库等的综合应用,并没有涉及新的内容。要注意的是,对于正点原子APM32F407最小系统板,其SD卡和摄像头是无法同时工作的,因为它们使用到了部分共同的GPIO引脚,因此在本章实验中,需要对GPIO引脚的复用模式进行切换,以正常使用SD卡或摄像头,用于切换GPIO引脚复用模式的函数,如下所示:

c 复制代码
/**
 * @bref	切换为OV2640模式
 * @note	切换PC8/PC9/PC11为DCI复用功能(AF13)
 * @param	无
 * @retval	无
 */
static void sw_ov2640_mode(void)
{
    OV2640_PWDN(0);
    GPIO_ConfigPinAF(GPIOC, GPIO_PIN_SOURCE_8, GPIO_AF_DCMI);
    GPIO_ConfigPinAF(GPIOC, GPIO_PIN_SOURCE_9, GPIO_AF_DCMI);
    GPIO_ConfigPinAF(GPIOC, GPIO_PIN_SOURCE_11, GPIO_AF_DCMI);
}

/**
 * @bref	切换为SD卡模式
 * @note	切换PC8/PC9/PC11为SDIO复用功能(AF12)
 * @param	无
 * @retval	无
 */
static void sw_sdcard_mode(void)
{
    OV2640_PWDN(1);
    GPIO_ConfigPinAF(GPIOC, GPIO_PIN_SOURCE_8, GPIO_AF_SDIO);
    GPIO_ConfigPinAF(GPIOC, GPIO_PIN_SOURCE_9, GPIO_AF_SDIO);
    GPIO_ConfigPinAF(GPIOC, GPIO_PIN_SOURCE_11, GPIO_AF_SDIO);
}

从应用代码的初始化函数中可以看到,在初始化过程中,配置了DCI和DMA将摄像头返回的图像数据传输至LCD上进行显示,初始化完成后,便检测按键输入,若无按键输入,则一直在LCD上显示摄像头采集到的图像数据,若检测到KEY0按键被按下,则调用函数bmp_encode()读取LCD上整个屏幕显示的数据并编码保存到SD卡上,若检测到KEY_UP按键,则调用函数ov2640_jpg_photo()将摄像头配置为JPEG格式输出图像数据,然后获取摄像头输出的一帧JPEG数据,并将JPEG数据通过FATFS写入SD的指定文件中。

53.3 下载验证

在完成编译和烧录操作后,可以看到LCD上实时显示这摄像头采集到的图像数据,此时若按下KEY0按键,可以看到LCD上显示了拍照成功和BMP图片保存路径的提示信息,若按下KEY_UP按键,可以看到LCD上显示了拍照成功和JPEG图片保存路径的提示信息。拍照完成后,可通过PC或图片显示实验例程(需修改获取图片的文件夹路径为"0:PHOTO")查看所拍摄的BMP或JPEG格式的照片。

相关推荐
网易独家音乐人Mike Zhou4 小时前
【卡尔曼滤波】数据预测Prediction观测器的理论推导及应用 C语言、Python实现(Kalman Filter)
c语言·python·单片机·物联网·算法·嵌入式·iot
zy张起灵4 小时前
48v72v-100v转12v 10A大功率转换电源方案CSM3100SK
经验分享·嵌入式硬件·硬件工程
PegasusYu6 小时前
STM32CUBEIDE FreeRTOS操作教程(九):eventgroup事件标志组
stm32·教程·rtos·stm32cubeide·free-rtos·eventgroup·时间标志组
lantiandianzi11 小时前
基于单片机的多功能跑步机控制系统
单片机·嵌入式硬件
文弱书生65611 小时前
输出比较简介
stm32
哔哥哔特商务网11 小时前
高集成的MCU方案已成电机应用趋势?
单片机·嵌入式硬件
跟着杰哥学嵌入式11 小时前
单片机进阶硬件部分_day2_项目实践
单片机·嵌入式硬件
电子科技圈12 小时前
IAR与鸿轩科技共同推进汽车未来
科技·嵌入式硬件·mcu·汽车
东芝、铠侠总代1361006839313 小时前
浅谈TLP184小型平面光耦
单片机·嵌入式硬件·物联网·平面
lantiandianzi13 小时前
基于单片机中医药柜管理系统的设计
单片机·嵌入式硬件