数码之家

 找回密码
 立即注册

QQ登录

只需一步,快速开始

微信登录

微信扫一扫,快速登录

搜索
查看: 41|回复: 1

《DNESP32S3使用指南-IDF版_V1.6》第三十五章 摄像头实验

[复制链接]
发表于 昨天 09:17 | 显示全部楼层 |阅读模式
第三十五章 摄像头实验

LCD_CAM控制块CAMERA模块则用于接收并行视频数据信号,支持DVP 8-/16-bit模式。DNESP32S3开发板板载了一个摄像头接口(P2),该接口可以用来连接正点原子 OV5640/OV2640/OV7725等摄像头模块。本章,我们将使用ESP32-S3驱动正点原子 OV56400/OV2640摄像头模块,实现摄像头功能。
本章分为如下几个小节:
35.1 OV5640CAMERA模块简介
35.2 硬件设计
35.3 程序设计
35.4 下载验证


35.1 OV5640CAMERA模块简介
本节将分为两个部分,分别介绍OV5640简介和DNESP32S3 LCD_CAM接口简介。另外,所有OV5640的相关资料,都在光盘:A盘à7,硬件资料àOV5640资料 文件夹里面。
35.1.1 OV5640简介
OV5640是OV(OmniVision)公司生产的一颗1/4寸的CMOS QSXGA(2592*1944)图像传感器,提供了一个完整的500W像素摄像头解决方案,并且集成了自动对焦(AF)功能,具有非常高的性价比。
该传感器体积小、工作电压低,提供单片QSXGA摄像头和影像处理器的所有功能。通过SCCB 总线控制,可以输出整帧、子采样、缩放和取窗口等方式的各种分辨率8/10位影像数据。该产品QSXGA图像最高达到15帧/秒(1080P图像可达30帧,720P图像可达60帧,QVGA分辨率时可达120帧)。用户可以完全控制图像质量、数据格式和传输方式。所有图像处理功能过程包括伽玛曲线、白平衡、对比度、色度等都可以通过SCCB接口编程。OmmiVision 图像传感器应用独有的传感器技术,通过减少或消除光学或电子缺陷如固定图案噪声、拖尾、浮散等,提高图像质量,得到清晰稳定的彩色图像。
OV5640的特点有:
l 采用1.4μm*1.4μm像素大小,并且使用OmniBSI技术以达到更高性能(高灵敏度、低串扰和低噪声)
l 自动图像控制功能:自动曝光(AEC)、自动白平衡(AWB)、自动消除灯光条纹、自动黑电平校准(ABLC)和自动带通滤波器(ABF)等。
l 支持图像质量控制:色饱和度调节、色调调节、gamma校准、锐度和镜头校准等
l 标准的SCCB接口,兼容IIC接口
l 支持RawRGB、RGB(RGB565/RGB555/RGB444)、CCIR656、YUV(422/420)、YCbCr(422)和压缩图像(JPEG)输出格式
l 支持QSXGA(500W)图像尺寸输出,以及按比例缩小到其他任何尺寸
l 支持闪光灯
l 支持图像缩放、平移和窗口设置
l 支持图像压缩,即可输出JPEG图像数据
l 支持数字视频接口(DVP)和MIPI接口
l 支持自动对焦
l 自带嵌入式微处理器
OV5640的功能框图如图35.1.1.1所示:
图35.1.1.1 OV5640功能框图
其中image array部分的尺寸,OV5640的官方数据并没有给出具体的数字,其最大的有效输出尺寸为:2592*1944,即500W像素,我们根据官方提供的一些应用文档,发现其设置的image array最大为:2632*1951,所以,在接下来的介绍,我们设定其image array最大为2632*1951。
1DVP接口说明
OV5640支持数字视频接口(DVP)和MIPI接口,因为我们的DNESP32S3使用的DCMI接口,仅支持DVP接口,所以,OV5640必须使用DVP输出接口,才可以连接我们的阿波罗ESP32开发板。
OV5640提供一个10位DVP接口(支持8位接法),其MSB和LSB可以程序设置先后顺序,正点原子 OV5640模块采用默认的8位连接方式,如图35.1.1.2所示:
图35.1.1.2 OV5640默认8位连接方式
OV5640的寄存器通过SCCB时序访问并设置,SCCB时序和IIC时序十分类似。SCCB 与标准的 I2C 协议的区别是它每次传输只能写入或读取一个字节的数据,而 I2C协议是支持突发读写的,即在一次传输中可以写入多个字节的数据(EEPROM中的页写入时序即突发写)。在本章我们不做介绍,请大家参考光盘《OmniVision Technologies Seril Camera Control Bus(SCCB) Specification》这个文档。
2、窗口设置说明
接下来,我们介绍一下OV5640的:ISP(Image Signal Processor)输入窗口设置、预缩放窗口设置和输出大小窗口设置,这几个设置与我们的正常使用密切相关,有必要了解一下。他们的设置关系,如图35.1.1.3所示:
图35.1.1.3 OV5640各窗口设置关系
ISP输入窗口设置(ISP input size
该设置允许用户设置整个传感器区域(physical pixel size ,2632*1951)的感兴趣部分,也就是在传感器里面开窗(X_ADDR_ST、Y_ADDR_ST、X_ADDR_END和Y_ADDR_END),开窗范围从0*0~2632*1951都可以设置,该窗口所设置的范围,将输入ISP进行处理。
ISP输入窗口,通过:0X3800~0X3807等8个寄存器进行设置,这些寄存器的定义请看:OV5640_CSP3_DS_2.01_Ruisipusheng.pdf 这个文档(下同)。
预缩放窗口设置(pre-scaling size
该设置允许用户在ISP输入窗口的基础上,再次设置将要用于缩放的窗口大小。该设置仅在ISP输入窗口内进行x/y方向的偏移(X_OFFSET/Y_OFFSET)。通过:0X3810~0X3813等4个寄存器进行设置。
输出大小窗口设置(data output size
该窗口是以预缩放窗口为原始大小,经过内部DSP进行缩放处理后,输出给外部的图像窗口大小。它控制最终的图像输出尺寸(X_OUTPUT_SIZE/Y_OUTPUT_SIZE)。通过:0X3808~0X380B等4个寄存器进行设置。注意:当输出大小窗口与预缩放窗口比例不一致时,图像将进行缩放处理(会变形),仅当两者比例一致时,输出比例才是1:1(正常)。
图35.1.1.3中,右侧data output size区域,才是OV5640输出给外部的图像尺寸,也就是显示在LCD上面的图像大小。输出大小窗口与预缩放窗口比例不一致时,会进行缩放处理,在LCD上面看到的图像将会变形。
3、输出时序说明
接下来,我们介绍一下OV5640的图像数据输出时序。首先我们简单介绍一些定义:
QSXGA,这里指:分辨率为2592*1944的输出格式,类似的还有:QXGA(2048*1536)、UXGA(1600*1200)、SXGA(1280*1024)、WXGA+(1440*900)、WXGA(1280*800)、XGA(1024*768)、SVGA(800*600)、VGA(640*480)、QVGA(320*240)和QQVGA(160*120)等。
PCLK,即像素时钟,一个PCLK时钟,输出一个像素(或半个像素)。
VSYNC,即帧同步信号。
HREF /HSYNC,即行同步信号。
OV5640的图像数据输出(通过Y[9:0])就是在PCLK,VSYNC和HREF/ HSYNC的控制下进行的。首先看看行输出时序,如图35.1.1.4所示:
图35.1.1.4 OV5640行输出时序
从上图可以看出,图像数据在HREF为高的时候输出,当HREF变高后,每一个PCLK时钟,输出一个8位/10位数据。我们采用8位接口,所以每个PCLK输出1个字节,且在RGB/YUV输出格式下,每个tp=2个Tpclk,如果是Raw格式,则一个tp=1个Tpclk。比如我们采用QSXGA时序,RGB565格式输出,每2个字节组成一个像素的颜色(低字节在前,高字节在后),这样每行输出总共有2592*2个PCLK周期,输出2592*2个字节。
再来看看帧时序(QSXGA模式),如图35.1.1.5所示:
图35.1.1.5 OV5640帧时序
上图清楚的表示了OV5640在QSXGA模式下的数据输出。我们按照这个时序去读取OV5640的数据,就可以得到图像数据。
4、自动对焦(Auto Focus)说明
OV5640由内置微型控制器完成自动对焦,并且VCM(Voice Coil Motor,即音圈马达)驱动器也已集成在传感器内部。微型控制器的控制固件(firmware)从主机下载。当固件运行后,内置微型控制器从OV5640传感器读得自动对焦所需的信息,计算并驱动VCM马达带动镜头到达正确的对焦位置。主机可以通过IIC命令控制微型控制器的各种功能。
OV5640的自动对焦命令(通过SCCB总线发送),如表35.1.1.1所示:
地址
寄存器名
描述
0X3022
CMD_MAIN
AF主命令寄存器
0X03:触发单次自动对焦过程
0X04:启动持续自动对焦过程
0X06:暂停自动对焦过程
0X08:释放马达回到初始状态
0X12:设置对焦区域
0X00:命令完成
0X3023
CMD_ACK
命令确认
0X00:命令完成
0X01:命令执行中
0X3029
FW_STATUS
对焦状态
0X7F:固件下载完成,但未执行,可能是:固件有问题/微控制器关闭
0X7E:固件初始化中
0X70:释放马达,回到初始状态
0X00:正在自动对焦
0X10:自动对焦完成
表35.1.1.1 OV5640自动对焦命令
OV5640内部的微控制器收到自动对焦命令后会自动将CMD_MAIN(0X3022)寄存器数据清零,当命令完成后会将CMD_ACK(0X3023)寄存器数据清零。
自动对焦(AF)过程
第一步:在第一次进入图像预览的时候(图像可以正常输出时),下载固件(firmware)。
第二步:拍照前,自动对焦,对焦完成后,拍照。
第三步:拍照完毕,释放马达到初始状态。
接下来,我们分别说明:
下载固件
OV5640初始化完成后,就可以下载AF自动对焦固件了,其操作和下载初始化参数类似,AF固件下载地址为:0X8000,初始化数组由厂家提供(本例程该数组保存在ov5640af.h里面),下载固件完成后,通过检查0X3029寄存器的值,来判断固件状态(等于0X70,说明正常)。
自动对焦
OV5640支持单次自动对焦和持续自动对焦,通过0X3022寄存器控制。单次自动对焦过程如下:
1,将0X3022寄存器写为0X03,开始单点对焦过程。
2,读取寄存器0X3029,如果返回值为0X10,代表对焦已完成。
3,写寄存器0X3022为0X06,暂停对焦过程,使镜头将保持在此对焦位置。
其中,前两步是必须的,第三步,可以不要,因为单次自动对焦完成以后,就不会继续自动对焦了,镜头也就不会动了。
持续自动对焦过程如下:
1, 将0X22寄存器写为0X08,释放马达到初始位置(对焦无穷远)。
2, 将0X3022寄存器写为0X04,启动持续自动对焦过程。
3, 读取寄存器0X3023,等待命令完成。
4, 当OV5640每次检测到失焦时,就会自动进行对焦(一直检测)。
释放马达,结束自动对焦
最后,在拍照完成,或者需要结束自动对焦的时候,我们对在寄存器0X3022写入0X08,即可释放马达,结束自动对焦。
最后说一下OV5640的图像数据格式,我们一般用2种输出方式:RGB565和JPEG。当输出RGB565格式数据的时候,时序完全就是上面两幅图介绍的关系。以满足不同需要。而当输出数据是JPEG数据的时候,同样也是这种方式输出(所以数据读取方法一模一样),不过PCLK数目大大减少了,且不连续,输出的数据是压缩后的JPEG数据,输出的JPEG数据以:0XFF,0XD8开头,以0XFF,0XD9结尾,且在0XFF,0XD8之前,或者0XFF,0XD9之后,会有不定数量的其他数据存在(一般是0),这些数据我们直接忽略即可,将得到的0XFF,0XD8~0XFF,0XD9之间的数据,保存为.jpg/.jpeg文件,就可以直接在电脑上打开看到图像了。
OV5640自带的JPEG输出功能,大大减少了图像的数据量,使得其在网络摄像头、无线视频传输等方面具有很大的优势。OV5640我们就介绍到这,关于OV5640更详细的介绍,请大家参考:A盘à7,硬件资料àOV5640资料à OV5640_CSP3_DS_2.01_Ruisipusheng.pdf。
正点原子OV5640摄像头模块
本实验,我们将使用DNESP32S3开发板的DCMI接口连接正点原子 OV5640摄像头模块,该模块采用8位数据输出接口,自带24M有源晶振,无需外部提供时钟,模组支持自动对焦功能,且支持闪光灯,整个模块只需提供3.3V 供电即可正常使用。
正点原子 OV5640摄像头模块外观如图35.1.1.6所示:  
图35.1.1.6 ALIENTEK OV5640摄像头模块外观图
模块原理图如图35.1.1.7所示:
图35.1.1.7 正点原子OV5640摄像头模块原理图
从上图可以看出,正点原子 OV5640摄像头模块自带了有源晶振,用于产生24M时钟作为OV5640的XCLK输入,模块的闪光灯(LED1&LED2)由OV5640的STROBE脚控制(可编程控制)。同时自带了稳压芯片,用于提供OV5640稳定的2.8V和1.5V工作电压,模块通过一个2*9的双排排针(P6)与外部通信,与外部的通信信号如表35.1.1.2所示:
信号
作用描述
信号
作用描述
VCC3.3
模块供电脚,接3.3V电源
OV_PCLK
像素时钟输出
GND
模块地线
OV_PWDN
掉电使能(高有效)
OV_SCL
SCCB通信时钟信号
OV_VSYNC
帧同步信号输出
OV_SDA
SCCB通信数据信号
OV_HREF
行同步信号输出
OV_D[7:0]
8位数据输出
OV_RESET
复位信号(低有效)
表35.1.1.2 OV5640模块信号及其作用描述
35.1.2 CAMERA模块简介
前面讲解到,ESP32-S3LCD_CAM控制器包含独立的LCD模块和Camera模块。其中LCD模块已经在第三十五章节中介绍过。下面我们介绍Camera模块用于接收并行视频数据信号,其总线支持DVP 8-/16-bit 模式。
以下是Camera模块特点:
①:支持以下工作模式:
Camera 从机接收模式。
Camera 主机接收模式。
②:支持同时外接 LCD Camera
③:支持单独外接 Camera(即 DVP 图像传感器)。
– 可配置为 8-bit 16-bit 位并行输入模式。
Camera 数据可由 GDMA 存入内部存储器。
④:支持 LCD_CAM 接口中断。
CAMERA控制器功能框图如下:
35.1.2.1 ESP32-S3 LCD_CAM模块的结构框图
这个系统的CAMERA模块和LCD模块类似:包含一个独立的接收控制单元(Camera_Ctrl),用于控制摄像头的接收;一个接收异步FIFOAsync Rx FIFO),用于与外部设备交互,接收数据;一个LCD_Clock Generator时钟生成模块,用于生成对应模块的时钟;以及一个格式转换模块,即RGB/YCbCr Converter,用于各种格式的视频数据互相转换。这些模块协同工作,确保系统能够高效、稳定地处理和传输视频数据。
1CAMERA模块信号描述
CAMERA模块信号对应了上图右上角的几个信号,它们的具体作用如下所示。
工作模式
信号
方向
功能
Camera 从机接收模式
CAM_PCLK
输入
像素时钟输入信号
CAM_V_SYNC
输入
帧同步输入信号 (VSYNC)
CAM_H_SYNC
输入
行同步输入信号 (HSYNC)
CAM_H_ENABLE
输入
行有效输入信号 (DE)
CAM_Data_in[N:0]
输入
数据总线,支持8/16位并行数据输入
Camera 主机接收模式
CAM_PCLK
输入
像素时钟输入信号
CAM_CLK
输出
主机时钟输出信号
CAM_V_SYNC
输入
帧同步输入信号 (VSYNC)
CAM_H_SYNC
输入
行同步输入信号 (HSYNC)
CAM_H_ENABLE
输入
行有效输入信号 (DE)
CAM_Data_in[N
输入
数据总线,支持8/16位并行数据输入
35.1.2.1 CAMERA模块信号描述
从上表可以看到,CAMERA模块工作模式分为两种,分别为从机接收模式和主机接收模式。一般我们使用主机接收模式开启动摄像头模组。
在启动CAMERA模块时,信号的位宽是一个关键参数。根据所接入的CAMERA的位宽,N的值会有所不同。如果使用位宽为16位,则N的值为15。相反,如果使用8位的位宽,则N的值为7。因此,根据CAMERA的位宽,可以确定N的具体值。
2CAMERA时钟选择
CAMERA模块的时钟LCD模块时钟选择是一样的配置流程,请读者参考第三十五章的35.1.2小节。
35.2 硬件设计
35.2.1. 例程功能
本章实验功能简介:程序下载完成,摄像头的图像数据在SPILCD显示屏上显示。
35.2.2. 硬件资源
1. XL9555
IIC_SDA-IO41
IIC_SCL-IO42
2. SPILCD
CS-IO21
SCK-IO12
SDA-IO11
DC-IO40(在P5端口,使用跳线帽将IO_SETLCD_DC相连)
PWR- IO1_3XL9555)
RST- IO1_2XL9555)
3. CAMERA
OV_SCL-IO38
OV_SDA- IO 39
VSYNC- IO 47
HREF- IO 48
PCLK- IO 45
D0- IO 4
D1- IO 5
D2- IO 6
D3- IO 7
D4- IO 15
D5- IO 16
D6- IO 17
D7- IO 18
RESET-IO0_5XL9555)
PWDN-IO0_4XL9555)
35.2.3. 原理图
CAMERA接口与ESP32-S3的连接关系,如下图所示:
图35.2.3.1 CAMERA接口与ESP32-S3的连接电路图
35.3 程序设计
35.3.1 程序流程图
程序流程图能帮助我们更好的理解一个工程的功能和实现的过程,对学习和设计工程有很好的主导作用。下面看看本实验的程序流程图:
35.3.1.1 CAMERA实验程序流程图
35.3.2 CAMERA函数解析
本章实验要使用到乐鑫官方的esp32-camera驱动库,此驱动库承载ESP32系列Soc兼容的图像传感器驱动程序。此外,它还提供了一些工具,允许将捕获的帧数据转换为更常见的BMPJPEG格式。要使用此功能,需要导入必要的头文件:
#include "esp_camera.h"
接下来,作者将介绍一些常用的ESP32-S3中的CAMERA函数,这些函数的描述及其作用如下:
1,初始化摄像头驱动
该函数用于检测并配置摄像头,其函数原型如下所示:
esp_err_t esp_camera_init(const camera_config_t *config);
该函数的形参描述,如下表所示:
形参
描述
config
这是指向摄像机配置参数的指针
表35.3.2.1 函数esp_camera_init ()形参描述
该函数的返回值描述,如下表所示:
返回值
描述
ESP_OK
返回:0,表示配置成功
表35.3.2.2 函数esp_camera_init ()
返回值描述该函数使用camera_config_t类型的结构体变量传入,该结构体的定义如下所示:
结构体
成员变量
参数介绍
camera_config_t
.pin_pwdn
相机电源下降线的GPIO引脚
.pin_reset
摄像机复位线GPIO引脚
.pin_xclk
相机XCLK线的GPIO引脚
.pin_sccb_sda
相机SDA线的GPIO引脚
.pin_sccb_scl
相机SCL线的GPIO引脚
.pin_d0~pin_d7
摄像机D0~D7线的GPIO引脚
.pin_vsync
摄像机VSYNC线的GPIO引脚
.pin_href
摄像机HREF线的GPIO引脚
.pin_pclk
摄像机PCLK线的GPIO引脚
.xclk_freq_hz
用于生成XCLKLEDC计时器
.ledc_timer
用于生成XCLKLEDC通道
.ledc_channel
像素数据格式
PIXFORMAT_+YUV422|
GRAYSCALE|
RGB565|
JPEG
.fb_location
输出图像大小
FRAMESIZE_+QVGA|
CIF|
VGA|
SVGA|
XGA|
SXGA|
UXGA
.pixel_format
JPEG输出的质量。0-63更低意味着更高的质量
.frame_size
要分配的帧缓冲区数。如果不止一个,则将获取每个帧(双倍速度)
.jpeg_quality
何时应填充缓冲区
.fb_count
相机电源下降线的GPIO引脚
.grab_mode
摄像机复位线GPIO引脚
35.3.2.3 camera_config_t结构体参数值描述
完成上述结构体参数配置之后,可以将结构传递给 esp_camera_init () 函数,用以实例化CAMERA
2,获取摄像头图像传感器
该函数用于获取指向图像传感器控制结构的指针,其函数原型如下所示:
sensor_t * esp_camera_sensor_get(void);
该函数的形参描述,如下表所示:
形参
描述
35.3.2.4 函数esp_camera_sensor_get ()形参描述
该函数的返回值描述,如下表所示:
返回值
描述
NULL
返回:0,即空
&s_state->sensor
指向结构体参数camera_state_t
35.3.2.5 函数esp_camera_sensor_get()返回值描述
35.3.3 CAMERA驱动解析
IDF版的25_1_camera例程中,作者在25_1_camera \components\BSP路径下新增了一个CAMERA文件夹以及25_1_camera \components\esp32-camera路径下新增了一个乐鑫官方的esp32-camera驱动库,分别用于存放camera.ccamera.hesp32-camera库文件。其中,camera.h负责声明CAMERA相关的函数和变量,而camera.cesp32-camera库文件则实现了CAMERA的驱动。下面,我们将详细解析这几个文件的实现内容。
1camera.h文件
/* 引脚声明 */
#define CAM_PIN_PWDN     GPIO_NUM_NC
#define CAM_PIN_RESET    GPIO_NUM_NC
#define CAM_PIN_XCLK     GPIO_NUM_NC
#define CAM_PIN_SIOD     GPIO_NUM_39
#define CAM_PIN_SIOC     GPIO_NUM_38
#define CAM_PIN_D7       GPIO_NUM_18
#define CAM_PIN_D6       GPIO_NUM_17
#define CAM_PIN_D5       GPIO_NUM_16
#define CAM_PIN_D4       GPIO_NUM_15
#define CAM_PIN_D3       GPIO_NUM_7
#define CAM_PIN_D2       GPIO_NUM_6
#define CAM_PIN_D1       GPIO_NUM_5
#define CAM_PIN_D0       GPIO_NUM_4
#define CAM_PIN_VSYNC    GPIO_NUM_47
#define CAM_PIN_HREF     GPIO_NUM_48
#define CAM_PIN_PCLK     GPIO_NUM_45
#define CAM_PWDN(x)      do{ x ? \
                             (xl9555_pin_write(OV_PWDN_IO, 1)):  \
                             (xl9555_pin_write(OV_PWDN_IO, 0));  \
                         }while(0)
#define CAM_RST(x)       do{ x ? \
                             (xl9555_pin_write(OV_RESET_IO, 1)): \
                             (xl9555_pin_write(OV_RESET_IO, 0)); \
                         }while(0)
2camera.c文件
/* 摄像头配置 */
static camera_config_t camera_config = {
    /* 引脚配置 */
    .pin_pwdn = CAM_PIN_PWDN,
    .pin_reset = CAM_PIN_RESET,
    .pin_xclk = CAM_PIN_XCLK,
    .pin_sccb_sda = CAM_PIN_SIOD,
    .pin_sccb_scl = CAM_PIN_SIOC,
    .pin_d7 = CAM_PIN_D7,
    .pin_d6 = CAM_PIN_D6,
    .pin_d5 = CAM_PIN_D5,
    .pin_d4 = CAM_PIN_D4,
    .pin_d3 = CAM_PIN_D3,
    .pin_d2 = CAM_PIN_D2,
    .pin_d1 = CAM_PIN_D1,
    .pin_d0 = CAM_PIN_D0,
    .pin_vsync = CAM_PIN_VSYNC,
    .pin_href = CAM_PIN_HREF,
    .pin_pclk = CAM_PIN_PCLK,
    /* 图像配置 */
    .xclk_freq_hz = 24000000,
    .ledc_timer = LEDC_TIMER_0,
    .ledc_channel = LEDC_CHANNEL_0,
    .fb_location = CAMERA_FB_IN_PSRAM,
   
    /* 图像输出模式 */
    .pixel_format = PIXFORMAT_RGB565,
   
    /* 图像输出大小 */
    .frame_size = FRAMESIZE_QVGA,
   
    /* 0-63,对于OV系列相机传感器,数量越少意味着质量越高 */
    .jpeg_quality = 12,
   
    /* 当使用jpeg模式时,如果fb_count超过一个,则驱动程序将在连续模式下工作 */
    .fb_count = 2,
    .grab_mode = CAMERA_GRAB_WHEN_EMPTY,
};
/**
* @brief       摄像头初始化
* @param       cmd 传输的8位命令数据
* @retval      
*/
uint8_t camera_init(void)
{
    esp_err_t err = ESP_OK;
    if (CAM_PIN_PWDN == GPIO_NUM_NC)
    {
        CAM_PWDN(0);
    }
    if (CAM_PIN_RESET == GPIO_NUM_NC)
    {
        CAM_RST(0);
        vTaskDelay(20);
        CAM_RST(1);
        vTaskDelay(20);
    }
    /* 摄像头初始化 */
    err = esp_camera_init(&camera_config);
    if (err != ESP_OK)
    {
        return 1;
    }
    sensor_t * s = esp_camera_sensor_get();
    if (s->id.PID == OV3660_PID)
    {
        s->set_vflip(s, 1);          /* 向后翻转 */
        s->set_brightness(s, 1);     /* 亮度提高 */
        s->set_saturation(s, -2);    /* 降低饱和度 */
    }
    else if (s->id.PID == OV5640_PID)
    {
        s->set_vflip(s, 1);          /* 向后翻转 */
    }
    return err;
}
首先定义一个camera_config_t类型的局部结构体变量,然后给结构体中的成员赋值,再调用esp_camera_init(&camera_config)函数进行初始化。如果摄像头模块是OV3660或者是OV5640,还需要进行配置。
35.3.4 CMakeLists.txt文件
打开本实验BSP下的CMakeLists.txt文件,其内容如下所示:
set(src_dirs
            CAMERA
            IIC
            LCD
            LED
            SPI
            XL9555)
set(include_dirs
            CAMERA
            IIC
            LCD
            LED
            SPI
            XL9555)
set(requires
            driver
            esp_lcd
            esp32-camera)
idf_component_register(SRC_DIRS ${src_dirs}
INCLUDE_DIRS ${include_dirs} REQUIRES ${requires})
component_compile_options(-ffast-math -O3 -Wno-error=format=-Wno-format)
上述的红色CAMERA驱动以及esp_ camera依赖库需要由开发者自行添加,以确保CAMERA驱动能够顺利集成到构建系统中。这一步骤是必不可少的,它确保了CAMERA驱动的正确性和可用性,为后续的开发工作提供了坚实的基础。
35.3.5 实验应用代码
打开main/main.c文件,该文件定义了工程入口函数,名为app_main。该函数代码如下。
i2c_obj_t i2c0_master;
/**
* @brief       程序入口
* @param      
* @retval      
*/
void app_main(void)
{
    uint8_t x = 0;
    esp_err_t ret;
   
    ret = nvs_flash_init();              /* 初始化NVS */
    if (ret == ESP_ERR_NVS_NO_FREE_PAGES ||
         ret == ESP_ERR_NVS_NEW_VERSION_FOUND)
    {
        ESP_ERROR_CHECK(nvs_flash_erase());
        ret = nvs_flash_init();
    }
    led_init();                          /* 初始化LED */
    i2c0_master = iic_init(I2C_NUM_0);  /* 初始化IIC0 */
    spi2_init();                         /* 初始化SPI2 */
    xl9555_init(i2c0_master);            /* 初始化XL9555 */
    lcd_init();                          /* 初始化LCD */
    lcd_show_string(30, 50, 200, 16, 16, "ESP32", RED);
    lcd_show_string(30, 70, 200, 16, 16, "CAMERA TEST", RED);
    lcd_show_string(30, 90, 200, 16, 16, "ATOM@ALIENTEK", RED);
    /* 初始化摄像头 */
    while (camera_init())
    {
        lcd_show_string(30, 110, 200, 16, 16, "CAMERA Fail!", BLUE);
        vTaskDelay(500);
    }
    lcd_clear(BLACK);
    while (1)
    {
        camera_show(0,0);               /* 显示图像 */
        
        x++;
        if (x % 30 == 0)
        {
            LED_TOGGLE();
        }
        vTaskDelay(5);
    }
}
从上述源码可知,我们首先初始化各个外设,如IICSPIXL9555、摄像头和LCD等驱动,然后调用camera_show()函数在SPILCD显示屏上显示摄像头图像。
35.4 下载验证
程序下载到开发板后,LCD显示屏不断更新摄像头输出的图像数据,如下图所示。
图35.4.1 LCD显示效果图

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册 微信登录

x
您需要登录后才可以回帖 登录 | 立即注册 微信登录

本版积分规则

APP|手机版|小黑屋|关于我们|联系我们|法律条款|技术知识分享平台

闽公网安备35020502000485号

闽ICP备2021002735号-2

GMT+8, 2025-8-1 09:56 , Processed in 0.124800 second(s), 11 queries , Redis On.

Powered by Discuz!

© 2006-2025 MyDigit.Net

快速回复 返回顶部 返回列表