本篇目标:使用STM32F407驱动摄像头OV7670,并上位机显示照片结果。

材料准备:

* STM32F4标准工程:stm32f407自建标准工程(stm32f4标准工程
<http://download.csdn.net/download/q361750389/10254946>)
* STM32F4摄像头测试工程:里面包含ov7670驱动文件、STM32F4摄像头测试工程,上位机测试软件(stm32f4摄像头测试最终工程
<https://download.csdn.net/download/q361750389/10275530>)
摄像头OV7670硬件连接与接口

这里使用的模块是OV7670不带FIFO的版本,使用STM32F407的DCMI+DMA进行数据传输,保证数据的速度,并把数据提取出来发送到上位机显示照片。
摄像头与STM32F4的连接如图:


测试摄像头OV7670驱动

用keil打开STM32F4标准工程,往里面添加代码,测试摄像头OV7670:

* 将准备材料测试工程中的摄像头驱动文件夹(ov7670)拷贝到stm32f407标准工程dev文件夹(新建)下。
* 在Manage Project Items添加文件夹ov7670,然后添加刚才拷贝文件夹下的C文件。
* 在Options->C/C++->Include Paths添加dev下复制文件夹ov7670的路径。
* 需要修改ov7670.h与sccb.h文件中对应的IO引脚,修改成自己对应的引脚口,应该用注释标出。
*
仔细检查ov7670.c与sccb.c文件中的引脚初始化函数,确认相关RESET、PWDN、SCCB等引脚初始化正确;修改dcmi.c的My_DCMI_Init函数中对于DCMI相关引脚的初始化,与自己的引脚对应。
* 在main.c中添加头文件: #include "ov7670.h" #include "dcmi.h" #include "ov7670test.h"
* 添加全局变量: extern u8 ov_rev_ok;
* 向main函数中添加代码,如下: int main(void) { /* stm32系统配置 */ Sys_Config(); //新添加 if
(OV7670_Init() !=0) { printf("ov7670 init error.\r\n"); } else {
OV7670_USART_Init(); }while(1) { LED1_ON; delay_ms(100); //新添加 if (ov_rev_ok) {
ShanWai_SendCamera(camera_buffer, PIC_WIDTH, PIC_HEIGHT); ov_rev_ok =0; } else
{ DCMI_Start(); } LED1_OFF; delay_ms(100); } }
* 编译通过后,烧写进STM32F4,首先观察Printf串口打印,是否有错误信息?
*
连接串口2至PC机,打开山外多功能调试助手->智能车助手:选择对应com口,波特率修改成最大值与代码一致,宽对应代码ov7670.h->PIC_WIDTH宏定义,高对应PIC_HEIGHT宏定义,小端对齐,打开串口。
* 等待图像区显示图像,如图:

摄像头OV7670代码解析

在这里解析一下OV7670的代码,先看一张代码的流程图:

看几个重要函数:

* OV7670_Init u8 OV7670_Init(void) { u16 i=0; u16 reg=0; /* RESET/PWDN引脚初始化 */
OV7670_RST_PW_Init(); OV7670_PWDN_L;//POWER ON delay_ms(100); OV7670_RST_L;
//复位OV7670 delay_ms(100); OV7670_RST_H; //结束复位 /* SCCB引脚初始化 */ SCCB_Init();
//初始化SCCB 的IO口 SCCB_WR_Reg(0X12, 0x80); //软复位OV7670 delay_ms(50);
reg=SCCB_RD_Reg(0X1c); //读取厂家ID 高八位 reg<<=8; reg|=SCCB_RD_Reg(0X1d); //读取厂家ID
低八位 if(reg!=OV7670_MID) { printf("\r\nMID:%d\r\n",reg); return 1; }
reg=SCCB_RD_Reg(0X0a); //读取厂家ID 高八位 reg<<=8; reg|=SCCB_RD_Reg(0X0b); //读取厂家ID
低八位 if(reg!=OV7670_PID) { printf("HID:%d\r\n\r\n",reg); return 2; } //初始化配置
OV7670寄存器,采用QVGA分辨率(320*240) for(i=0;i<sizeof(ov7670_init_reg_tbl)/sizeof
(ov7670_init_reg_tbl[0]);i++) { SCCB_WR_Reg(ov7670_init_reg_tbl[i][0
],ov7670_init_reg_tbl[i][1]); } //裁剪摄像头照片尺寸,参数:起始坐标x、y;长度、高度;裁剪长高不可大于上面设置的分辨率
OV7670_Window_Set(PIC_START_X,PIC_START_Y,PIC_WIDTH,PIC_HEIGHT);/* 白平衡设置,默认值0 */
OV7670_Light_Mode(0); /* 色度设置,默认值2 */ OV7670_Color_Saturation(2); /* 亮度设置,默认值2
*/ OV7670_Brightness(1); /* 对比度设置,默认值2 */ OV7670_Contrast(2); /*
DCMI初始化,包括IO口和中断 */ My_DCMI_Init(); /* DCMI DMA设置,数据指向照片数组camera_buffer */
DCMI_DMA_Init((uint32_t)&camera_buffer,sizeof(camera_buffer)/4
,DMA_MemoryDataSize_HalfWord,DMA_MemoryInc_Enable);//DCMI DMA return 0x00; //ok
}
* DMA2_Stream1_IRQHandler void DMA2_Stream1_IRQHandler(void) { if
(DMA_GetFlagStatus(DMA2_Stream1,DMA_FLAG_TCIF1)==SET)//DMA2_Steam1,传输完成标志 {
DMA_Cmd(DMA2_Stream1, DISABLE); DMA_ClearFlag(DMA2_Stream1,DMA_FLAG_TCIF1);
//清除传输完成中断 /* 摄像头获取照片数据完毕,在这里添加操作代码 */ /* 数据获取标志ov_rev_ok置位,在main函数中操作 */
ov_rev_ok= 1; datanum++; } }
注意点

在之前驱动摄像头的过程中,一些驱动难点:

*
OV7670接口上的XCLK必须要接,这里用的是STM32F4分频输出MCO1,这里的分频系数要调试好,太高太低都不合适,代码定位在sccb.c的32行RCC_MCO1Config函数;
* OV7670的寄存器要配置正确,一些关于分频的寄存器要特别注意,在文件ov7670config.h中。
*
OV7670_Window_Set用来裁剪照片的尺寸,正常的QVGA分辨率320*240,一个数组在STM32F4里放不下,可以用函数裁剪成小一点的尺寸存入数组用来传输数组。
小结:对于驱动摄像头OV7670解释了大概的思路,实际移植过程中会有很多改参数,调试的不过,需要自己对着数据手册耐心探索一下,不过过程不变其中。
接下来就把OV7670移植到家庭IOT监测工程中,将原本RGB565的照片数据转换成bmp数据上传到ONENET平台,达到监测的目的,加油,共勉~

友情链接
KaDraw流程图
API参考文档
OK工具箱
云服务器优惠
阿里云优惠券
腾讯云优惠券
华为云优惠券
站点信息
问题反馈
邮箱:ixiaoyang8@qq.com
QQ群:637538335
关注微信