Arduino-ESP32 ESP_Video 库实战指南:基于 MIPI-CSI 与 DVP 接口的 V4L2 风格摄像头采集
【免费下载链接】arduino-esp32Arduino core for the ESP32 family of SoCs项目地址: https://gitcode.com/GitHub_Trending/ar/arduino-esp32
ESP_Video 是 arduino-esp32 核心中面向 ESP32-S3 与 ESP32-P4 的摄像头采集库,它封装了 ESP-IDF 的esp_video组件,以 V4L2 风格 API 屏蔽 MIPI-CSI(含 ISP)与 DVP 两种底层接口的差异。读完本文,你将掌握视频设备节点的选择、像素格式与分辨率的映射关系、MIPI-CSI / DVP 两套完整初始化与取帧流程,以及如何通过传感器控制接口调节增益、曝光与镜像翻转,可直接基于 示例工程 与 DVP 示例 快速搭建预览、抓帧或 JPEG 采集应用。
库定位与适用前提
该库封装 ESP-IDFesp_video组件,对外暴露 V4L2 风格的采集 API,用于受支持 SoC 上的摄像头传感器。它完成MIPI-CSI(带 ISP)与DVP两种接口的底层初始化后,让应用可以打开视频设备节点、分配缓冲区并取出帧数据。典型用途包括预览流水线、面向计算机视觉的抓帧、JPEG 采集,以及传感器调参(增益、曝光、翻转等控制)。
使用该库有三个硬性前提(见 ESP_Video.h 头部的条件编译):
- ESP-IDF 5.4.0 或更高版本,且目标芯片为ESP32-S3 或 ESP32-P4;
- IDF 配置中至少开启
CONFIG_ESP_VIDEO_ENABLE_MIPI_CSI_VIDEO_DEVICE或CONFIG_ESP_VIDEO_ENABLE_DVP_VIDEO_DEVICE其中之一,否则ESP_Video.h不暴露任何公共 API; - 示例分别面向ESP32-P4(MIPI-CSI + DVP)与ESP32-S3(DVP)。
在草图中包含头文件即可:
#include "ESP_Video.h"从源码结构看,ESP_Video.h在最外层用#if (CONFIG_ESP_VIDEO_ENABLE_MIPI_CSI_VIDEO_DEVICE || CONFIG_ESP_VIDEO_ENABLE_DVP_VIDEO_DEVICE)和#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 4, 0)双重条件包裹全部类定义,这正是文档所述"无配置则无 API"的代码级体现。库的元信息见 library.properties(当前版本 3.3.11,类别 Signal Input/Output)。
视频设备节点:用文件路径操作摄像头
硬件初始化完成后,采集通过esp_video_device.h中定义的标准设备路径进行:
| 设备路径宏 | 实际节点 | 含义 |
|---|---|---|
ESP_VIDEO_MIPI_CSI_DEVICE_NAME | /dev/video0 | MIPI-CSI 摄像头 |
ESP_VIDEO_ISP_DVP_DEVICE_NAME | /dev/video1 | ISP + DVP |
ESP_VIDEO_DVP_DEVICE_NAME | /dev/video2 | 无 ISP 路径的 DVP |
| 其他节点 | — | 在 IDF 配置中启用 SPI、USB UVC、JPEG/H264 编解码、ISP 设备时追加 |
节点路径只是入口,真正的工作由ESPVideoCaptureDevClass完成:它以open()打开设备,经VIDIOC_G_FMT读取驱动当前格式、VIDIOC_S_FMT重新应用格式,再请求 MMAP 捕获缓冲区(对应源码 open()/applyFormat())。
API 总览:七层设计
Arduino-ESP32 的 ESP Video API 组织为七层,从像素格式到传感器控制逐层递进:
- 像素格式——
esp_video_format_t与ESPVideoFormatClass - 分辨率——
ESPVideoSolutionClass(帧宽高) - 硬件配置——
ESPVideoCamConfigClass、ESPVideoCSIConfigClass、ESPVideoDVPPinsConfigClass、ESPVideoDVPConfigClass - 硬件初始化——
ESPVideoClass::begin() - 采集设备——
ESPVideoCaptureDevClass(继承格式与分辨率基类) - 缓冲区——
ESPVideoBufferClass(同样继承格式与分辨率基类) - 传感器控制——
ESPVideoCaptureDevClass::setSensor*()系列方法
值得注意的设计细节(均有源码佐证):
- 配置对象是值类型,只保存引脚与总线设置,可复制、可赋值;引脚通过
periman的占用/释放由ESPVideoClass::begin()完成,在end()或析构函数中释放。 - CSI 与 DVP 可共存(例如 ESP32-P4),每种接口由内部标志位独立跟踪,并在
end()或析构时释放。 - 采集设备打开是统一的:
begin()打开设备、读取并重放当前 V4L2 格式(VIDIOC_G_FMT/VIDIOC_S_FMT)、保存宽高并请求捕获缓冲区。 - 格式与分辨率是共享基类,采集设备和每一帧缓冲区都携带元数据。
- 像素格式是 Arduino 枚举,
setFormat()在startCapture()前调用;若缓冲区分配后格式改变,驱动缓冲区会被自动重新请求(见setFormat()中requestBuffer(buf_count_)的回调逻辑)。 - 资源持有类不可复制(
ESPVideoClass、ESPVideoCaptureDevClass),ESPVideoBufferClass仅可移动。
像素格式与 V4L2 fourcc 映射
esp_video_format_t是 Arduino 侧的像素格式标识符,ESPVideoCaptureDevClass::setFormat()在发出VIDIOC_S_FMT前将每个枚举值映射为 V4L2 fourcc;格式元数据存放在ESPVideoFormatClass中,被采集设备与每个缓冲区继承。枚举定义(见 ESP_Video.h):
typedef enum { ESP_VIDEO_FORMAT_UNKNOWN = 0, ESP_VIDEO_FORMAT_RAW8, ESP_VIDEO_FORMAT_RAW10, ESP_VIDEO_FORMAT_RAW12, ESP_VIDEO_FORMAT_RGB565, ESP_VIDEO_FORMAT_RGB888, ESP_VIDEO_FORMAT_YUV420, ESP_VIDEO_FORMAT_YUV422_YUYV, ESP_VIDEO_FORMAT_YUV422_UYVY, ESP_VIDEO_FORMAT_GRAY8, ESP_VIDEO_FORMAT_JPEG, ESP_VIDEO_FORMAT_MAX } esp_video_format_t;支持的格式及其 V4L2 映射(映射函数video_format_to_v4l2_format()见 ESP_Video.cpp):
esp_video_format_t | 名称字符串 | V4L2 fourcc |
|---|---|---|
ESP_VIDEO_FORMAT_RAW8 | RAW8 | V4L2_PIX_FMT_SRGGB8 |
ESP_VIDEO_FORMAT_RAW10 | RAW10 | V4L2_PIX_FMT_SGRBG10 |
ESP_VIDEO_FORMAT_RAW12 | RAW12 | V4L2_PIX_FMT_SGRBG12 |
ESP_VIDEO_FORMAT_RGB565 | RGB565 | V4L2_PIX_FMT_RGB565 |
ESP_VIDEO_FORMAT_RGB888 | RGB888 | V4L2_PIX_FMT_RGB24 |
ESP_VIDEO_FORMAT_YUV420 | YUV420 | V4L2_PIX_FMT_YUV420 |
ESP_VIDEO_FORMAT_YUV422_YUYV | YUV422_YUYV | V4L2_PIX_FMT_YUYV |
ESP_VIDEO_FORMAT_YUV422_UYVY | YUV422_UYVY | V4L2_PIX_FMT_UYVY |
ESP_VIDEO_FORMAT_GRAY8 | GRAY8 | V4L2_PIX_FMT_GREY |
ESP_VIDEO_FORMAT_JPEG | JPEG | V4L2_PIX_FMT_JPEG |
ESP_VIDEO_FORMAT_UNKNOWN与ESP_VIDEO_FORMAT_MAX是哨兵值,不能传给setFormat()。实际可用格式取决于传感器驱动与当前视频设备;若驱动在begin()时报告无法识别的 fourcc,getFormat()会返回ESP_VIDEO_FORMAT_UNKNOWN(对应源码v4l2_format_to_video_format()的 default 分支)。
分辨率与格式元数据基类
ESPVideoSolutionClass:分辨率
存储当前帧宽高,被ESPVideoCaptureDevClass(begin()期间经VIDIOC_G_FMT填充)与ESPVideoBufferClass(取帧时从采集设备复制)继承:
ESPVideoSolutionClass(); // 空对象,宽高为 0 ESPVideoSolutionClass(const ESPVideoSolutionClass &config); // 复制宽高 ESPVideoSolutionClass &operator=(const ESPVideoSolutionClass &config); void begin(uint32_t width, uint32_t height); // 存储帧尺寸 uint32_t getWidth() const; uint32_t getHeight() const;ESPVideoFormatClass:格式元数据
存储当前像素格式类型及其可读名称,同样被采集设备与缓冲区继承:
ESPVideoFormatClass(); // 空对象,格式为 UNKNOWN ESPVideoFormatClass(const ESPVideoFormatClass &config); ESPVideoFormatClass &operator=(const ESPVideoFormatClass &config); void begin(esp_video_format_t format_type, const std::string &format_name = ""); esp_video_format_t getFormat() const; const char *getFormatName() const;当begin()传入空format_name时,getFormatName()会根据format_type推导名称并在首次访问时缓存(源码中format_name_被声明为mutable以支持惰性填充)。
摄像头配置(SCCB / I2C)
ESPVideoCamConfigClass保存 CSI 与 DVP 共用的 SCCB(I2C)设置。创建实例后调用begin()填充设置,再传给ESPVideoCSIConfigClass或ESPVideoDVPConfigClass。默认构造创建空对象,复制构造/赋值复制 SCCB 端口或句柄、引脚号与 I2C 频率,但不保留 GPIO,引脚所有权归ESPVideoClass::begin()。
begin(Arduino 引脚号版本)
bool begin(i2c_port_num_t port, int8_t scl_pin, int8_t sda_pin, uint32_t i2c_freq = i2c_freq_hz, int8_t reset_pin = -1, int8_t pwdn_pin = -1);port—— 库初始化总线时用于 SCCB 的 I2C 端口;scl_pin/sda_pin—— SCCB 时钟与数据引脚;i2c_freq—— SCCB 频率(Hz),默认 100 kHz(源码中i2c_freq_hz = 100 * 1000);reset_pin/pwdn_pin—— 可选的传感器复位与掉电 GPIO,不用时传-1。
begin(复用已有 I2C 主总线)
bool begin(i2c_master_bus_handle_t i2c_handle, uint32_t i2c_freq = i2c_freq_hz, int8_t reset_pin = -1, int8_t pwdn_pin = -1);当 SCCB 复用应用已创建的 I2C 总线时使用此重载,此时库不会为 SCCB 初始化新的 I2C 驱动(源码通过needInitI2C()判断i2c_handle == nullptr来决定是否自建总线,并在getSccbConfig()中相应设置init_sccb标志)。
其他成员
esp_video_init_sccb_config_t getSccbConfig() const—— 返回供 ESP-IDFesp_video初始化结构使用的 SCCB 段;gpio_num_t getResetPin() const/gpio_num_t getPwdnPin() const—— 可选传感器控制 GPIO 的只读访问;bool acquirePins(void *bus)/bool releasePins()—— 通过periman保留或释放 SCCB 及复位/掉电 GPIO,由ESPVideoClass::begin()/end()自动调用,应用通常无需直接调用。DVP 场景下periman的占用类型包括ESP32_BUS_TYPE_VIDEO_CAM_RESET、ESP32_BUS_TYPE_VIDEO_SCCB_SCL/SDA以及ESP32_BUS_TYPE_LCDCAM_CAM_*系列(见 setPinsBus/clearPinsBus 实现)。
MIPI-CSI 配置
ESPVideoCSIConfigClass继承ESPVideoCamConfigClass,用于 MIPI-CSI + ISP 初始化,仅在启用CONFIG_ESP_VIDEO_ENABLE_MIPI_CSI_VIDEO_DEVICE时可用。复制构造会同时复制基类摄像头配置与 LDO 初始化标志。
bool begin(const ESPVideoCamConfigClass &config, bool dont_init_ldo = false);config—— 基础摄像头 / SCCB 配置;dont_init_ldo—— 为true时跳过 CSI 驱动内的 LDO 初始化(外部供电时使用)。
getCsiInitConfig()从存储的配置构建 ESP-IDF CSI 初始化结构;getDontInitLdo()返回 LDO 跳过标志。
DVP 引脚配置与 DVP 配置
ESPVideoDVPPinsConfigClass:并行引脚
描述 DVP 并行数据与同步引脚,仅在启用CONFIG_ESP_VIDEO_ENABLE_DVP_VIDEO_DEVICE时可用;begin()固定配置 8 位数据宽度(D0–D7)。
bool begin(int8_t vsync_pin, int8_t de_pin, int8_t pclk_pin, int8_t xclk_pin, int8_t data0_pin, int8_t data1_pin, int8_t data2_pin, int8_t data3_pin, int8_t data4_pin, int8_t data5_pin, int8_t data6_pin, int8_t data7_pin);vsync_pin/de_pin/pclk_pin/xclk_pin—— 同步与时钟引脚;data0_pin…data7_pin—— 8 条并行数据线。
源码中该begin()会将dvp_pin.data_width固定为CAM_CTLR_DATA_WIDTH_8,并把各引脚填入esp_cam_ctlr_dvp_pin_config_t。getDvpPin()返回原生 ESP-IDF DVP 引脚结构。
ESPVideoDVPConfigClass:组合配置
同时继承ESPVideoCamConfigClass与ESPVideoDVPPinsConfigClass,单个实例携带完整 DVP 设置(SCCB + 引脚 + XCLK 频率):
bool begin(const ESPVideoCamConfigClass &config, const ESPVideoDVPPinsConfigClass &dvp_pin, uint32_t xclk_freq);config—— 基础摄像头 / SCCB 配置;dvp_pin—— DVP 数据、同步与时钟引脚映射(参见 ESP-IDF camera controller 文档);xclk_freq—— 传感器外部时钟(XCLK)频率(Hz)。
getDvpInitConfig()构建 ESP-IDF DVP 初始化结构,getXclkFreq()返回 XCLK 频率。其acquirePins()/releasePins()依次调用基类实现,同时管理 SCCB、复位/掉电与 DVP 并行引脚。
ESPVideoClass:硬件初始化与清理
ESPVideoClass初始化 CSI 或 DVP 的esp_video栈,每个应用创建一个实例(或使用静态/全局实例)。析构函数调用end()停止已初始化的子系统并释放保留的引脚。
void end();通过esp_video_deinit_with_flags()停止子系统、释放begin()期间保留的引脚并清空存储的配置。
begin(MIPI-CSI)
bool begin(const ESPVideoCSIConfigClass &config);初始化 MIPI-CSI 与 ISP(ESP_VIDEO_INIT_FLAGS_MIPI_CSI | ESP_VIDEO_INIT_FLAGS_ISP)。流程为:通过periman保留引脚 → 调用esp_video_init_with_flags()→ 保存配置供清理。初始化成功或已完成时返回true;失败时在返回false前释放已保留引脚(源码中的回滚逻辑见 begin(CSI))。isCSIInitialized()返回 CSI 与 ISP 标志是否生效。
begin(DVP)
bool begin(const ESPVideoDVPConfigClass &config);初始化 DVP 视频设备(ESP_VIDEO_INIT_FLAGS_DVP),遵循与 CSI 相同的引脚保留与回滚规则。isDVPInitialized()返回 DVP 子系统是否已初始化。isActive()则返回是否有任何子系统标志处于活动状态。
ESPVideoCaptureDevClass:采集设备与帧循环
该类打开 V4L2 采集设备、管理缓冲区并取出帧,继承ESPVideoSolutionClass与ESPVideoFormatClass提供分辨率与格式元数据。类本身不可复制、不可移动,请使用单一长生命周期实例或显式管理生命周期。析构函数调用end()停止采集、解除 MMAP 映射、释放驱动缓冲区并关闭文件描述符。
begin / end
bool begin(const char *path, size_t buf_count = 2); void end();begin()打开path指定的设备(若未打开),读取驱动格式(VIDIOC_G_FMT)、重新应用(VIDIOC_S_FMT)、保存宽高与像素格式,并请求buf_count个 MMAP 捕获缓冲区;检测到的格式与分辨率可通过getFormat()、getFormatName()、getWidth()、getHeight()获取。设备已打开时直接返回true而不改变路径;任何失败都会关闭设备并使实例保持未打开状态(源码 begin())。
requestBuffer / startCapture / stopCapture
bool requestBuffer(size_t buf_count); bool startCapture(); bool stopCapture();requestBuffer(buf_count)—— 释放既有缓冲区,向驱动请求新的 MMAP 缓冲区并映射到用户空间,buf_count通常取 2 以实现双缓冲;失败时回滚部分已分配缓冲区。源码中会依次执行VIDIOC_REQBUFS→ 逐个VIDIOC_QUERYBUF+mmap()(见 requestBuffer())。startCapture()—— 将所有缓冲区入队并启动视频流(VIDIOC_STREAMON),要求先完成缓冲区设置。stopCapture()—— 若采集已启动则停止流(VIDIOC_STREAMOFF);未启动或已停止时返回false。
captureBuffer 与状态查询
ESPVideoBufferClass captureBuffer(); bool isOpened() const; bool isCaptureStarted() const;captureBuffer()取出一个已填充缓冲区(VIDIOC_DQBUF);采集未运行或取帧失败时返回无效缓冲区。isOpened()判断设备文件描述符是否有效,isCaptureStarted()判断startCapture()是否成功且流未停止。
setFormat
bool setFormat(esp_video_format_t format);在采集开始前选择像素格式,或在设备打开后更改格式。内部以format对应的 V4L2 fourcc 执行VIDIOC_G_FMT/VIDIOC_S_FMT;若格式改变且已分配捕获缓冲区,会释放既有 MMAP 缓冲区并按上次begin()/requestBuffer()的缓冲区数量重新请求。对不支持的枚举值、I/O 错误或缓冲区重分配失败返回false。典型应用在begin()之后、startCapture()之前调用。注意源码中若采集已启动(capture_started_),setFormat()会直接拒绝执行。
传感器控制
以下方法映射到 V4L2 扩展控制(VIDIOC_S_EXT_CTRLS),可用性取决于传感器驱动与当前格式,每个控制方法在驱动接受值时才返回true:
| 方法 | 对应的 V4L2 控制 |
|---|---|
bool setSensorGain(int32_t gain) | V4L2_CID_GAIN |
bool setSensorExposure(int32_t exposure) | V4L2_CID_EXPOSURE |
bool setSensorExposureTime(int32_t exposure_time) | V4L2_CID_EXPOSURE_ABSOLUTE |
bool setSensorAETargetLevel(int32_t target_level) | V4L2_CID_CAMERA_AE_LEVEL |
bool setSensorJPEGQuality(int32_t quality) | V4L2_CID_JPEG_COMPRESSION_QUALITY |
bool setSensorVFlip(bool vflip) | V4L2_CID_VFLIP |
bool setSensorHFlip(bool hflip) | V4L2_CID_HFLIP |
bool setSensorTestPattern(bool test_pattern) | V4L2_CID_TEST_PATTERN |
所有方法统一经setExtCtrlValue()构造v4l2_ext_control/v4l2_ext_controls并下发ioctl(fd, VIDIOC_S_EXT_CTRLS, ...)(见 ESP_Video.cpp)。
ESPVideoBufferClass:RAII 帧缓冲
一帧已取出数据的 RAII 包装。继承ESPVideoSolutionClass与ESPVideoFormatClass,因此每帧自带格式与分辨率元数据。对象被销毁、被移动,或调用end()时,缓冲区会被重新入队(VIDIOC_QBUF)以便采集继续。该类仅可移动(复制已删除)。
ESPVideoBufferClass(ESPVideoBufferClass &&other) noexcept; // 转移所有权,源对象清空 ESPVideoBufferClass &operator=(ESPVideoBufferClass &&other) noexcept; bool valid() const; // data() 非空且 size() > 0 uint8_t *data() const; // MMAP 模式下的像素数据指针 size_t size() const; // V4L2 的 bytesused,有效字节数 int index() const; // 驱动缓冲区索引,重新入队后为 -1 uint32_t getWidth() const; uint32_t getHeight() const; // 取帧时从采集设备复制的宽高 const char *formatName() const; // getFormatName() 的别名 esp_video_format_t formatType() const; // getFormat() 的别名 void end(); // 立即将缓冲区归还驱动重要提示:只在处理一帧期间持有ESPVideoBufferClass。销毁、移动或调用end()都会把缓冲区归还驱动;不及时释放缓冲区会导致captureBuffer()停滞(缓冲区耗尽)。同时,data()返回的指针不可超过ESPVideoBufferClass对象的生命周期保存。
端到端示例:MIPI-CSI 采集(ESP32-P4)
完整示例见 mipi_csi_camera.ino,核心流程如下:
#include "esp_video_device.h" ESPVideoClass video; ESPVideoCamConfigClass cam_config; cam_config.begin(port, scl, sda); ESPVideoCSIConfigClass csi_config; csi_config.begin(cam_config); if (!video.begin(csi_config)) { // handle error } ESPVideoCaptureDevClass capture; if (!capture.begin(ESP_VIDEO_MIPI_CSI_DEVICE_NAME, 2)) { // handle error } if (!capture.setFormat(ESP_VIDEO_FORMAT_RGB565)) { // handle error } if (!capture.startCapture()) { // handle error } ESPVideoBufferClass frame = capture.captureBuffer(); if (frame.valid()) { uint8_t *pixels = frame.data(); size_t nbytes = frame.size(); const char *format_name = frame.formatName(); // e.g. "JPEG", "RGB565" uint32_t width = frame.getWidth(); uint32_t height = frame.getHeight(); // use frame; buffer is returned to the driver when `frame` is destroyed }示例工程的引脚定义以 ESP32-P4-Function-EV-Board V1.5 为默认(SCCB I2C 端口 0、SCL GPIO 8、SDA GPIO 7),并保护性地用#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 4, 0)与#if CONFIG_IDF_TARGET_ESP32P4包裹,版本或芯片不符时给出明确编译错误或运行提示。示例 CI 配置(ci.yml)还要求PartitionScheme=esp_sr_16, FlashSize=16M与CONFIG_ESP_VIDEO_ENABLE_MIPI_CSI_VIDEO_DEVICE=y,可作为你配置开发环境时的参考。
端到端示例:DVP 采集(ESP32-S3 / ESP32-P4)
完整示例见 dvp_camera.ino,核心流程如下:
#include "esp_video_device.h" ESPVideoClass video; ESPVideoCamConfigClass cam_config; cam_config.begin(port, scl, sda); ESPVideoDVPPinsConfigClass dvp_pins; dvp_pins.begin(vsync, de, pclk, xclk, d0, d1, d2, d3, d4, d5, d6, d7); ESPVideoDVPConfigClass dvp_config; dvp_config.begin(cam_config, dvp_pins, xclk_freq_hz); if (!video.begin(dvp_config)) { // handle error } ESPVideoCaptureDevClass capture; if (!capture.begin(ESP_VIDEO_DVP_DEVICE_NAME, 2)) { // handle error } if (!capture.startCapture()) { // handle error } ESPVideoBufferClass frame = capture.captureBuffer(); if (frame.valid()) { uint8_t *pixels = frame.data(); size_t nbytes = frame.size(); const char *format_name = frame.formatName(); uint32_t width = frame.getWidth(); uint32_t height = frame.getHeight(); // use frame; buffer is returned to the driver when `frame` is destroyed }示例为两种芯片提供了可直接套用的默认引脚与 XCLK 频率:
- ESP32-S3(ESP32-S3-EYE):SCCB I2C 端口 0、SCL GPIO 5、SDA GPIO 4;XCLK GPIO 15、PCLK GPIO 13、VSYNC GPIO 6、DE GPIO 7、D0–D7 为 GPIO 11/9/8/10/12/18/17/16;XCLK 频率10 MHz。
- ESP32-P4(ESP32-P4-Function-EV-Board V1.5):SCCB I2C 端口 0、SCL GPIO 8、SDA GPIO 7;XCLK GPIO 20、PCLK GPIO 4、VSYNC GPIO 37、DE GPIO 22、D0–D7 为 GPIO 2/32/33/23/3/6/5/21;XCLK 频率20 MHz。
两个示例的loop()都采用"取帧 → 校验 → 打印指针/大小/格式/宽高 → 帧对象析构归还缓冲区"的循环模式,Serial 波特率 115200;kCaptureBufferCount = 2即双缓冲,可避免帧丢失。示例同样要求CONFIG_ESP_VIDEO_ENABLE_DVP_VIDEO_DEVICE=y。
配置 Kconfig 与开发环境要点
- 库整体在 library.properties 中声明为
architectures=esp32的标准 Arduino 库,安装后通过#include <ESP_Video.h>使用。 - 必须按接口类型开启对应 Kconfig:MIPI-CSI 用
CONFIG_ESP_VIDEO_ENABLE_MIPI_CSI_VIDEO_DEVICE=y,DVP 用CONFIG_ESP_VIDEO_ENABLE_DVP_VIDEO_DEVICE=y;两者可同时开启(ESP32-P4 支持 CSI 与 DVP 共存)。 - 示例 CI 额外使用
PartitionScheme=esp_sr_16, FlashSize=16M,在资源紧张的工程中可作为分区间隔的参考。 - 若板级引脚与示例不同,只需改写
EXAMPLE_*引脚宏;引脚冲突会在periman保留阶段被检测并打印日志(源码中videoDetachBus会提示先调用video.end()再复用摄像头引脚)。
【免费下载链接】arduino-esp32Arduino core for the ESP32 family of SoCs项目地址: https://gitcode.com/GitHub_Trending/ar/arduino-esp32
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考