【正点原子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格式的照片。

相关推荐
菠萝地亚狂想曲12 分钟前
FreeRTOS heap4
c语言·stm32·嵌入式开发
The Mr.Nobody16 分钟前
基于STM32F407的 TFTP Server
arm开发·stm32·嵌入式硬件
飞凌嵌入式17 分钟前
如何用JishuShell在RK3588核心板上快速部署OpenClaw?
arm开发·人工智能·嵌入式硬件·openclaw
余生皆假期-22 分钟前
永磁同步电机的星形 (Y) 和三角形 (Δ) 有何不同?
单片机·嵌入式硬件
点灯小铭24 分钟前
基于单片机的空气质量检测仪系统设计
单片机·嵌入式硬件·毕业设计·课程设计·期末大作业
狂奔蜗牛(bradley)24 分钟前
嵌入式软件中如何用责任链模式重构串口协议栈
网络·单片机·mcu·重构·责任链模式
时空自由民.37 分钟前
LCD显示的图像散乱原因
单片机
鸟电波43 分钟前
硬件笔记——Allegro绘制PCB(未完待续)
笔记·嵌入式硬件·智能硬件
悠哉悠哉愿意1 小时前
【单片机复习笔记】十三届国赛复盘2
笔记·单片机·嵌入式硬件
清风6666661 小时前
基于单片机的矿井温度、烟雾与甲烷检测通风报警系统设计
单片机·嵌入式硬件·毕业设计·课程设计·期末大作业