LCD_CAM控制块CAMERA模块则用于接收并行视频数据信号,支持DVP8-/16-bit模式。ESP32S3开发板板载了一个摄像头接口(P2),该接口可以用来连接原子OV5640/OV2640/OV7725等摄像头模块。本章将使用ESP32-S3驱动原子OV2640摄像头模块,实现摄像头功能。
本章分为如下几个小节:
35.1 OV5640 和 CAMERA 模块简介
35.2 硬件设计
35.3 程序设计
35.4 下载验证
35.1 OV5640 和 CAMERA 模块简介
本节将分为两个部分,分别学习 OV5640 简介和 ESP32S3 LCD_CAM 接口简介。另外,所有 OV5640/OV2640 的相关资料,都在光盘: A 盘→7,硬件资料文件夹中。
35.1.1 OV5640 简介
OV5640 是 OmniVision公司生产的一颗 1/4 寸的 CMOS QSXGA(2592*1944)图像传感器,提供了一个完整的 500W 像素摄像头解决方案,并且集成了自动对焦(AF)功能,具有非常高的性价比。
该传感器体积小、工作电压低,提供单片 QSXGA 摄像头和影像处理器的所有功能。通过SCCB 总线控制,可以输出整帧、子采样、缩放和取窗口等方式的各种分辨率 8/10 位影像数据。该产品 QSXGA 图像最高达到 15 帧/秒(1080P 图像可达 30 帧, 720P 图像可达 60 帧, QVGA 分辨率时可达 120 帧)。用户可以完全控制图像质量、数据格式和传输方式。所有图像处理功能过程包括伽玛曲线、白平衡、对比度、色度等都可以通过 SCCB 接口编程。 OmmiVision 图像传感器应用独有的传感器技术,通过减少或消除光学或电子缺陷如固定图案噪声、拖尾、浮散等,提高图像质量,得到清晰稳定的彩色图像。
OV5640有以下特点:
- 采用 1.4μm*1.4μm 像素大小,并且使用 OmniBSI 技术以达到更高性能(高灵敏度、低串扰和低噪声);
- 自动图像控制功能:自动曝光(AEC)、自动白平衡(AWB)、自动消除灯光条纹、自动黑电平校准(ABLC)和自动带通滤波器(ABF)等;
- 支持图像质量控制:色饱和度调节、色调调节、 gamma 校准、锐度和镜头校准等;
- 标准的 SCCB 接口,兼容 IIC 接口;
- 支持 RawRGB、 RGB(RGB565/RGB555/RGB444)、 CCIR656、 YUV(422/420)、 YCbCr(422)和压缩图像(JPEG)输出格式;
- 支持 QSXGA(500W)图像尺寸输出,以及按比例缩小到其他任何尺寸;
- 支持闪光灯;
- 支持图像缩放、平移和窗口设置;
- 支持图像压缩,即可输出 JPEG 图像数据;
- 支持数字视频接口(DVP)和 MIPI 接口;
- 支持自动对焦;
- 自带嵌入式微处理器。
OV5640 的功能框图如图 35.1.1.1 所示:

图 35.1.1.1 OV5640 功能框图
其中 image array 部分的尺寸, OV5640 的官方数据并没有给出具体的数字,其最大的有效
输出尺寸为:2592*1944,即 500W 像素,根据官方提供的一些应用文档,发现其设置的image array最大为:2632*1951,所以,在接下来的介绍,设定其image array最大为2632*1951。
(1)DVP 接口说明
OV5640支持数字视频接口(DVP)和 MIPI接口,因为ESP32S3使用的 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,本次实验使用OV2640,主要内容相似,下来了解下两者差异:
特性参数 | OV5640 | OV2640 | 差异解读 |
---|---|---|---|
最大分辨率 | 500万像素 (2592x1944) | 200万像素 (1600x1200) | OV5640能捕获更清晰的细节,适合需要裁剪或放大的场景。 |
主要输出接口 | MIPI CSI-2, DVP | DVP | OV5640的MIPI接口更适合高速数据传输,常见于现代处理器。 |
数据总线地址 | 16位寄存器地址 | 8位寄存器地址 | 驱动开发时,OV5640的寄存器配置更复杂。 |
JPEG压缩 | 支持硬件JPEG压缩 | 支持硬件JPEG压缩 | 两者都支持,能有效减少传输数据量,节省带宽。 |
自动对焦(AF) | 支持 | 不支持 | 这是OV5640的一项高级功能,能确保图像持续清晰。 |
典型应用场景 | 智能手机、高端监控、工业检测 | 智能家居、视频通话、基础监控 | OV5640面向高画质需求,OV2640满足基础成像和成本控制。 |
表 35.1.1.2 OV5640与OV2640比较
原子 OV2640摄像头模块:
本实验,将使用 DNESP32S3 开发板的 DCMI 接口连接正点原子 OV2640 摄像头模块。原子 OV5640 摄像头模块外观如图 35.1.1.6 所示:

图 35.1.1.6 ALIENTEK OV2640 摄像头模块外观图
模块原理图如图 35.1.1.7 所示:

图 35.1.1.7 原子 OV2640 摄像头模块原理图
从上图可以看出,原子 OV2640 摄像头模块自带了有源晶振,用于产生 12M 时钟作为OV2640 的 XCLK 输入。自带了稳压芯片,用于提供 OV2640 稳定的 2.8V 和 1.3V 工作电压,模块通过一个2*9 的双排排针(P1)与外部通信,与外部的通信信号如表 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.3 OV2640 模块信号及其作用描述
35.1.2 CAMERA 模块简介
前面讲解到, ESP32-S3 的 LCD_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),用于控制摄像头的接收;一个接收异步 FIFO(Async Rx FIFO),用于与外部设备交互,接收数据;一个 LCD_Clock Generator 时钟生成模块,用于生成对应模块的时钟;以及一个格式转换模块,即RGB/YCbCr Converter,用于各种格式的视频数据互相转换。这些模块协同工作,确保系统能够高效、稳定地处理和传输视频数据。
(1)CAMERA 模块信号描述
CAMERA 模块信号对应了上图右上角的几个信号,它们的具体作用如下所示。
工作模式 | 信号 | 方向 | 功能 |
---|---|---|---|
Camera 从机接收模式 | CAM_PCLK | 输入 | 像素时钟输入信号 |
Camera 从机接收模式 | CAM_V_SYNC | 输入 | 帧同步输入信号 (VSYNC) |
Camera 从机接收模式 | CAM_H_SYNC | 输入 | 行同步输入信号 (HSYNC) |
Camera 从机接收模式 | CAM_H_ENABLE | 输入 | 行有效输入信号 (DE) |
Camera 从机接收模式 | CAM_Data_in[N:0] | 输入 | 数据总线,支持 8/16 位并行数据输入 |
Camera 主机接收模式 | CAM_PCLK | 输入 | 像素时钟输入信号 |
Camera 主机接收模式 | CAM_CLK | 输出 | 主机时钟输出信号 |
Camera 主机接收模式 | CAM_V_SYNC | 输入 | 帧同步输入信号 (VSYNC) |
Camera 主机接收模式 | CAM_H_SYNC | 输入 | 行同步输入信号 (HSYNC) |
Camera 主机接收模式 | CAM_H_ENABLE | 输入 | 行有效输入信号 (DE) |
Camera 主机接收模式 | CAM_Data_in[N:0] | 输入 | 数据总线,支持 8/16 位并行数据输入 |
表 35.1.2.1 CAMERA 模块信号描述
从上表可以看到, CAMERA 模块工作模式分为两种,分别为从机接收模式和主机接收模式。一般使用主机接收模式开启动摄像头模组。
在启动 CAMERA 模块时,信号的位宽是一个关键参数。根据所接入的 CAMERA 的位宽,N 的值会有所不同。如果使用位宽为 16 位,则 N 的值为 15。相反,如果使用 8 位的位宽,则 N的值为 7。因此,根据 CAMERA 的位宽,可以确定 N 的具体值。
(2)CAMERA 时钟选择
CAMERA 模块的时钟 LCD 模块时钟选择是一样的配置流程,请读者参考第三十五章的35.1.2 小节。
35.2 硬件设计
35.2.1. 例程功能
本章实验功能简介:程序下载完成,摄像头的图像数据在 SPILCD 显示屏上显示。
35.2.2. 硬件资源
- XL9555
IIC_SDA-IO41
IIC_SCL-IO42
- SPILCD
CS-IO21
SCK-IO12
SDA-IO11
DC-IO40(在 P5 端口,使用跳线帽将 IO_SET 和 LCD_DC 相连)
PWR- IO1_3(XL9555)
RST- IO1_2(XL9555)
- 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_5(XL9555)
PWDN-IO0_4(XL9555)
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 兼容的图像传感器驱动程序。此外,它还提供了一些工具,允许将捕获的帧数据转换为更常见的 BMP和 JPEG 格式。要使用此功能,需要导入必要的头文件:
#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 引脚 |
camera_config_t | .pin_reset | 摄像机复位线 GPIO 引脚 |
camera_config_t | .pin_xclk | 相机 XCLK 线的 GPIO 引脚 |
camera_config_t | .pin_sccb_sda | 相机 SDA 线的 GPIO 引脚 |
camera_config_t | .pin_sccb_scl | 相机 SCL 线的 GPIO 引脚 |
camera_config_t | .pin_d0~pin_d7 | 摄像机 D0~D7 线的 GPIO 引脚 |
camera_config_t | .pin_vsync | 摄像机 VSYNC 线的 GPIO 引脚 |
camera_config_t | .pin_href | 摄像机 HREF 线的 GPIO 引脚 |
camera_config_t | .pin_pclk | 摄像机 PCLK 线的 GPIO 引脚 |
camera_config_t | .xclk_freq_hz | 用于生成 XCLK 的 LEDC 计时器 |
camera_config_t | .ledc_timer | 用于生成 XCLK 的 LEDC 通道 |
camera_config_t | .ledc_channel | 像素数据格式 PIXFORMAT_+YUV422| GRAYSCALE| RGB565| JPEG |
camera_config_t | .fb_location | 输出图像大小 FRAMESIZE_+QVGA| CIF| VGA| SVGA| XGA| SXGA| UXGA |
camera_config_t | .pixel_format | JPEG 输出的质量。 0-63 更低意味着更 高的质量 |
camera_config_t | .frame_size | 要分配的帧缓冲区数。如果不止一 个,则将获取每个帧(双倍速度) |
camera_config_t | .jpeg_quality | 何时应填充缓冲区 |
camera_config_t | .fb_count | 相机电源下降线的 GPIO 引脚 |
camera_config_t | .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 驱动解析
通过添加camera组件,方法见第九章,在 IDF 版StandardExampleIDF(v5.3.x)的 25_1_camera 例程中,在25_1_camera路径下新增了一个managed_components\espressif__esp32-camera文件夹,新增了乐鑫官方的esp32-camera驱动库。下面将详细解析实现内容。
(1)main.c 文件
/* 引脚配置 */
#define CAM_PIN_PWDN GPIO_NUM_NC
#define CAM_PIN_RESET GPIO_NUM_NC
#define CAM_PIN_VSYNC GPIO_NUM_47
#define CAM_PIN_HREF GPIO_NUM_48
#define CAM_PIN_PCLK GPIO_NUM_45
#define CAM_PIN_XCLK GPIO_NUM_NC
#define CAM_PIN_SIOD GPIO_NUM_39
#define CAM_PIN_SIOC GPIO_NUM_38
#define CAM_PIN_D0 GPIO_NUM_4
#define CAM_PIN_D1 GPIO_NUM_5
#define CAM_PIN_D2 GPIO_NUM_6
#define CAM_PIN_D3 GPIO_NUM_7
#define CAM_PIN_D4 GPIO_NUM_15
#define CAM_PIN_D5 GPIO_NUM_16
#define CAM_PIN_D6 GPIO_NUM_17
#define CAM_PIN_D7 GPIO_NUM_18
#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)
/* 摄像头配置 */
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 20MHz or 10MHz for OV2640 double FPS (Experimental) */
.xclk_freq_hz = 24000000,
.ledc_timer = LEDC_TIMER_0,
.ledc_channel = LEDC_CHANNEL_0,
.pixel_format = PIXFORMAT_RGB565, /* YUV422,GRAYSCALE,RGB565,JPEG */
.frame_size = FRAMESIZE_QVGA, /* QQVGA-UXGA, For ESP32, do not use sizes above QVGA when not JPEG. The performance of the ESP32-S series has improved a lot, but JPEG mode always gives better frame rates */
.jpeg_quality = 12, /* 0-63, for OV series camera sensors, lower number means higher quality */
.fb_count = 2, /* When jpeg mode is used, if fb_count more than one, the driver will work in continuous mode */
.fb_location = CAMERA_FB_IN_PSRAM,
.grab_mode = CAMERA_GRAB_WHEN_EMPTY,
};
/**
* @brief 摄像头初始化
* @param 无
* @retval esp_err_t
*/
static esp_err_t init_camera(void)
{
if (CAM_PIN_PWDN == GPIO_NUM_NC)
{
CAM_PWDN(0);
}
if (CAM_PIN_RESET == GPIO_NUM_NC)
{
CAM_RST(0);
vTaskDelay(pdMS_TO_TICKS(20));
CAM_RST(1);
vTaskDelay(pdMS_TO_TICKS(20));
}
/* 摄像头初始化 */
esp_err_t err = esp_camera_init(&camera_config);
if (err != ESP_OK)
{
ESP_LOGE("TAG", "Camera Init Failed");
return err;
}
sensor_t * s = esp_camera_sensor_get();
/* 如果摄像头模块是OV3660或者是OV5640,则需要以下配置 */
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 ESP_OK;
}
首先定义一个 camera_config_t 类型的局部结构体变量,然后给结构体中的成员赋值,再调用 esp_camera_init(&camera_config)函数进行初始化。如果摄像头模块是 OV3660或者是OV5640,还需要进行配置。
35.3.4 实验应用代码
打开 main/main.c 文件,该文件定义了工程入口函数,名为 app_main。该函数代码如下。
/**
* @brief 程序入口
* @param 无
* @retval 无
*/
void app_main(void)
{
esp_err_t ret;
camera_fb_t *fb = NULL;
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());
ESP_ERROR_CHECK(nvs_flash_init());
}
led_init(); /* LED初始化 */
my_spi_init(); /* SPI初始化 */
myiic_init(); /* MYIIC初始化 */
xl9555_init(); /* XL9555初始化 */
spilcd_init(); /* SPILCD初始化 */
init_camera(); /* 初始化摄像头 */
spilcd_show_string(30, 50, 200, 16, 16, "ESP32-S3", RED);
spilcd_show_string(30, 70, 200, 16, 16, "CAMERA TEST", RED);
spilcd_show_string(30, 90, 200, 16, 16, "ATOM@ALIENTEK", RED);
vTaskDelay(pdMS_TO_TICKS(1500));
while(1)
{
fb = esp_camera_fb_get();
esp_lcd_panel_draw_bitmap(panel_handle, 0, 0, fb->width, fb->height, fb->buf);
esp_camera_fb_return(fb);
}
}
35.4 下载验证
程序下载到开发板后, LCD 显示屏不断更新摄像头输出的图像数据,如下图所示。

图 35.4.1 LCD 显示效果图