第三十五章 ESP32S3 摄像头实验

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. 硬件资源
  1. XL9555

IIC_SDA-IO41

IIC_SCL-IO42

  1. SPILCD

CS-IO21

SCK-IO12

SDA-IO11

DC-IO40(在 P5 端口,使用跳线帽将 IO_SET 和 LCD_DC 相连)

PWR- IO1_3(XL9555)

RST- IO1_2(XL9555)

  1. 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 显示效果图

相关推荐
진영_3 小时前
深度学习打卡第N8周:使用Word2vec实现文本分类
人工智能·深度学习·word2vec
飞哥数智坊3 小时前
Linus 眼中,编程 AI 的真实价值如何?
人工智能·ai编程
用户5191495848454 小时前
Oracle云基础设施强势崛起:AI驱动的新一代云计算竞争格局
人工智能·aigc
盼小辉丶4 小时前
视频生成技术Deepfake
人工智能·深度学习·计算机视觉·keras·生成模型
CV-杨帆4 小时前
复现 Qwen3Guard 实时安全,逐词响应
人工智能·语言模型
人工智能技术派5 小时前
LTU-AS:一种具备音频感知、识别、理解的大模型架构
人工智能·语言模型·语音识别
youcans_5 小时前
【AGI使用教程】Meta 开源视觉基础模型 DINOv3(1)下载与使用
人工智能·计算机视觉·agi·基础模型·dino
要做朋鱼燕6 小时前
【OpenCV】图像处理实战:边界填充与阈值详解
图像处理·笔记·opencv·计算机视觉
DevYK6 小时前
企业级Agent开发教程(三)基于LangGraph开发低代码 AI Agent 轻量级开发框架
人工智能·agent