ESP32-P4 摄像头画面实时上屏:基于 esp_video 与 MIPI-DSI 的 Video LCD Display 实战指南
【免费下载链接】esp-iot-solutionEspressif IoT Library. IoT Device Drivers, Documentations and Solutions.项目地址: https://gitcode.com/GitHub_Trending/es/esp-iot-solution
导读
本文以 esp-iot-solution 仓库中的 video_lcd_display 示例为主线,完整讲解如何在 ESP32-P4 开发板上把 MIPI-CSI 摄像头采集的画面通过 PPA 硬件加速处理后,实时显示到 7 英寸 1024×600 MIPI-DSI 触摸屏上。读完本文,你将掌握该示例的硬件接线、menuconfig 配置、编译烧录流程,以及从esp_video组件初始化、V4L2 式视频设备打开、双/三缓冲管理到 LCD 刷屏的完整数据通路与源码实现细节。
示例概述:摄像头 → 屏幕的完整链路
该示例基于 Espressif 的 esp_video)。它演示了从摄像头采集图像到 LCD 显示的全过程,核心数据链路为:
- MIPI-CSI 摄像头(SC2336 传感器)采集原始图像;
- esp_video组件完成 CSI 控制器、ISP 流水线的初始化,并向上层暴露类似 Linux V4L2 的字符设备接口(
/dev/video*); - 应用层通过标准的 V4L2 ioctl 流程(
VIDIOC_QUERYCAP/VIDIOC_REQBUFS/VIDIOC_QBUF/VIDIOC_DQBUF/VIDIOC_STREAMON)获取视频帧; - 若摄像头分辨率与 LCD 分辨率不一致,使用PPA(Pixel Processing Accelerator,像素处理加速器)的 SRM(Scale-Rotate-Mirror)算子做缩放/裁剪;
- 最终通过
esp_lcd_panel_draw_bitmap将帧数据写入MIPI-DSI 接口的 EK79007 LCD 驱动完成上屏。
工程目录结构如下(源码路径:main):
| 文件 | 职责 |
|---|---|
| main.c | 主流程:初始化 LCD、注册 PPA 客户端、打开摄像头、设置缓冲、启动采集任务 |
| app_lcd.c | LCD 初始化:LDO 上电、MIPI-DSI 总线、DBI 面板 IO、EK79007 面板驱动 |
| app_video.c | 摄像头初始化、V4L2 设备打开、缓冲管理、帧采集 FreeRTOS 任务 |
| app_lcd.h / app_video.h | 对外 API 与宏定义 |
| Kconfig.projbuild | 示例级菜单配置项 |
| sdkconfig.defaults | 目标芯片与默认配置 |
| idf_component.yml | 组件依赖声明 |
环境要求与版本前提
- 支持的芯片:仅支持 ESP32-P4(
sdkconfig.defaults中通过CONFIG_IDF_TARGET="esp32p4"固定)。 - ESP-IDF 版本:支持
release/v5.4及更新分支,默认按release/v5.4构建(sdkconfig.defaults注释中也标明由 ESP-IDF 5.4.0 生成)。请先按 ESP-IDF 编程指南 配置好开发环境,建议先完成 "Build Your First Project" 熟悉流程。 - 组件依赖(见 idf_component.yml):
esp_video0.8.*(公共依赖,负责摄像头视频通路);espressif/esp_lcd_ek790071.*(公共依赖,EK79007 面板驱动);idf >= 5.3。
需要说明:示例支持 ESP-IDF release/v5.4 及以后版本,因此若使用更高版本的 IDF,部分驱动 API 或默认配置可能略有差异,请以实际环境编译输出为准。
硬件准备与接线步骤
官方推荐的硬件组合为:
- 一块ESP32-P4-Function-EV-Board开发板;
- 一块7 英寸 1024×600 LCD 屏,主控 IC 为 EK79007,搭配 32-pin FPC 的适配底板;
- 一个MIPI-CSI 摄像头,传感器 IC 为 SC2336,同样搭配 32-pin FPC 适配底板;
- 一根USB-C 线,用于供电与串口监视。
接线分为五个步骤:
- Step 1:按下表把屏幕适配底板背面的引脚接到开发板对应引脚(注意屏幕背光 PWM 与复位脚必须接对):
| Screen Adapter Board | ESP32-P4-Function-EV-Board |
|---|---|
| 5V (任意一个) | 5V (任意一个) |
| GND (任意一个) | GND (任意一个) |
| PWM | GPIO26 |
| LCD_RST | GPIO27 |
- Step 2:将 LCD 的 FPC 排线插入开发板的
MIPI_DSI接口; - Step 3:将摄像头的 FPC 排线插入开发板的
MIPI_CSI接口; - Step 4:用 USB-C 线连接开发板
USB-UART口到 PC(供电 + 查看串口输出); - Step 5:打开开发板电源开关。
值得对照源码的一点:复位引脚 GPIO27 在 app_lcd.c 中以EXAMPLE_PIN_NUM_LCD_RST (27)定义,而背光 PWM 的 GPIO26 则由屏的硬件配置决定,与接线表一一对应,接线前务必核对。
配置项目:menuconfig 关键选项
在工程根目录运行idf.py menuconfig,进入Example Configuration菜单即可配置引脚与示例相关选项。所有示例级选项均定义在 Kconfig.projbuild 中,主要分四类:
1. MIPI-CSI 摄像头传感器配置
Example Configuration → Enable MIPI CSI Camera Sensor(默认开启,依赖SOC_MIPI_CSI_SUPPORTED)。开启后可配置:
EXAMPLE_MIPI_CSI_SCCB_I2C_PORT:SCCB(摄像头控制总线)I2C 端口号,默认0,范围0~1;EXAMPLE_MIPI_CSI_SCCB_I2C_SCL_PIN:SCCB SCL 引脚,默认34,范围-1~56;EXAMPLE_MIPI_CSI_SCCB_I2C_SDA_PIN:SCCB SDA 引脚,默认31,范围-1~56;EXAMPLE_MIPI_CSI_SCCB_I2C_FREQ:SCCB I2C 频率,默认100000,范围100000~400000。帮助文本明确指出:增大该值可缩短摄像头传感器的初始化时间,但需参考传感器手册在允许范围内调整;EXAMPLE_MIPI_CSI_CAM_SENSOR_RESET_PIN:传感器复位引脚,默认-1(不接);EXAMPLE_MIPI_CSI_CAM_SENSOR_PWDN_PIN:传感器掉电引脚,默认-1。
注意:sdkconfig.defaults中针对该示例把 SCL/SDA 实际改为8/7,即默认配置下 SCCB 走 GPIO8(SCL)与 GPIO7(SDA),与 Kconfig 中的通用默认值不同,若自行接线需以实际硬件为准调整。
2. 摄像头传感器选型(Espressif Camera Sensors 配置)
README 要求在Espressif Camera Sensors Configurations中选择传感器型号及输出格式:
Component config ---> Espressif Camera Sensors Configurations ---> [*] SC2336 ----> Default format select for MIPI (RAW8 1280x720 30fps, MIPI 2lane 24M input) ---> (X) RAW8 1280x720 30fps, MIPI 2lane 24M input对应到sdkconfig.defaults的两项开关:CONFIG_CAMERA_SC2336=y与CONFIG_CAMERA_SC2336_MIPI_RAW8_1024x600_30FPS=y。后者的 "1024x600" 表明示例默认让 SC2336 输出与 LCD 同分辨率(1024×600)的 RAW8 数据,从而避免 PPA 缩放带来的帧率损失。
3. 图像处理与显示相关选项
EXAMPLE_ENABLE_PRINT_FPS_RATE_VALUE:是否周期打印帧率(FPS),默认开启;EXAMPLE_USE_MEMORY_MAPPING:是否用内存映射(MMAP)方式分配摄像头缓冲,默认关闭。开启后app_video_set_bufs传入NULL,由驱动通过mmap自动分配(对应 app_video.c 中V4L2_MEMORY_MMAP分支);关闭时使用用户定义缓冲(V4L2_MEMORY_USERPTR);EXAMPLE_CAM_BUF_COUNT:摄像头缓冲数量,默认2,范围2~3。该值同时决定 LCD 的帧缓冲数量(见app_lcd.h中EXAMPLE_LCD_BUF_NUM (CONFIG_EXAMPLE_CAM_BUF_COUNT)),即摄像头缓冲与 LCD 显示缓冲一一对应复用;LCD_PIXEL_FORMAT_RGB565/LCD_PIXEL_FORMAT_RGB888:LCD 颜色格式选择,默认 RGB565(16bpp),可选 RGB888(24bpp)。该选择会同时驱动 app_lcd.h 中EXAMPLE_LCD_BIT_PER_PIXEL、EXAMPLE_MIPI_DPI_PX_FORMAT以及 app_video.h 中APP_VIDEO_FMT的取值,保证摄像头输出格式与屏幕格式一致;EXAMPLE_ENABLE_CAM_SENSOR_PIC_VFLIP/EXAMPLE_ENABLE_CAM_SENSOR_PIC_HFLIP:是否对画面做垂直/水平镜像翻转,均默认开启。
此外,sdkconfig.defaults还启用了CONFIG_ESP_VIDEO_ENABLE_ISP_PIPELINE_CONTROLLER=y(ISP 流水线控制器)与CONFIG_IDF_EXPERIMENTAL_FEATURES=y,并配置了 200MHz SPIRAM 与 1000Hz FreeRTOS 节拍,这些是保证高帧率采集与显示的基础。
编译、烧录与监视
在工程目录(examples/camera/video_lcd_display)下执行:
idf.py -p PORT flash monitor其中PORT替换为开发板对应的串口名。该命令会一次性完成编译、烧录并打开串口监视器;退出监视器按Ctrl-]。完整的环境配置与工程构建步骤可参考 ESP-IDF Getting Started Guide。
运行成功后,串口会打印摄像头设备的能力信息(driver、card、bus 等),并在开启 FPS 打印时每 50 帧输出一次当前帧率与帧尺寸,形如:
I (xxxx) app_main: fps: 29.xxx I (xxxx) app_main: camera_buf_hes: 1024, camera_buf_ves: 600, camera_buf_len: 1228 KB源码级剖析:从初始化到逐帧上屏
1. 主流程编排(main.c)
main.c 中app_main的执行顺序清晰展示了"先屏后摄"的初始化策略:
app_lcd_init(&display_panel)初始化 EK79007 LCD 面板;- 注册PPA SRM 客户端(
PPA_OPERATION_SRM),并查询 SPIRAM 对齐要求(esp_cache_get_alignment),为后续对齐分配缓冲做准备; app_video_main(NULL)初始化 esp_video(摄像头通路);app_video_open(EXAMPLE_CAM_DEV_PATH, APP_VIDEO_FMT)打开 MIPI-CSI 视频设备(设备路径宏为ESP_VIDEO_MIPI_CSI_DEVICE_NAME);- 获取 LCD 帧缓冲(
esp_lcd_dpi_panel_get_frame_buffer),缓冲数量与EXAMPLE_LCD_BUF_NUM(即摄像头缓冲数 2 或 3)一致; - 根据是否开启内存映射,选择
app_video_set_bufs(..., NULL)(MMAP 自动分配)或传入用户缓冲(USERPTR):- 若传感器输出恰好为 1024×600(
CONFIG_CAMERA_SC2336_MIPI_RAW8_1024x600_30FPS),直接复用 LCD 帧缓冲作为摄像头缓冲,实现零拷贝; - 否则用
heap_caps_aligned_calloc在 SPIRAM 中按缓存行对齐分配独立缓冲;
- 若传感器输出恰好为 1024×600(
- 注册帧操作回调
camera_video_frame_operation; - 启动摄像头采集任务
app_video_stream_task_start(video_cam_fd0, 0, NULL)(固定绑定到 core 0)。
2. LCD 初始化(app_lcd.c)
app_lcd.c 的初始化要点:
- LDO 上电:先通过
esp_ldo_acquire_channel为 MIPI PHY 供电(通道 3,2500mV); - DSI 总线:使用 EK79007 驱动预置的
EK79007_PANEL_BUS_DSI_2CH_CONFIG()创建 2-lane MIPI-DSI 总线; - DBI 面板 IO:
EK79007_PANEL_IO_DBI_CONFIG()创建 DBI(命令通道); - DPI 面板:
EK79007_1024_600_PANEL_60HZ_CONFIG(EXAMPLE_MIPI_DPI_PX_FORMAT)生成 1024×600@60Hz 的 DPI 配置,并将num_fbs设为EXAMPLE_LCD_BUF_NUM(多帧缓冲是实现无撕裂刷新的关键); - 面板配置中
reset_gpio_num = 27、rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB、bits_per_pixel依据 RGB565/RGB888 自动取值,随后esp_lcd_new_panel_ek79007创建面板并reset+init。
3. 摄像头通路与 V4L2 流程(app_video.c)
app_video.c 把 esp_video 的上层封装成了类 V4L2 的标准流程,是理解该示例的关键:
app_video_main:构造esp_video_init_csi_config_t(SCCB 的 I2C 端口/引脚/频率、复位与掉电引脚),若外部传入 I2C 总线句柄则复用该总线,最终调用esp_video_init;app_video_open:open设备 →VIDIOC_QUERYCAP查询能力(串口打印版本、驱动名、卡名、总线信息)→VIDIOC_G_FMT读取当前分辨率并记录到camera_buf_hes/ves→ 若像素格式与init_fmt(RGB565 或 RGB888)不一致则VIDIOC_S_FMT设置;若使能了翻转,则通过VIDIOC_S_EXT_CTRLS设置V4L2_CID_VFLIP/V4L2_CID_HFLIP;app_video_set_bufs:校验缓冲数(2~3 个,MAX_BUFFER_COUNT=3、MIN_BUFFER_COUNT=2)→VIDIOC_REQBUFS请求缓冲(传入fb时用V4L2_MEMORY_USERPTR,否则V4L2_MEMORY_MMAP)→ 逐个VIDIOC_QUERYBUF后mmap或登记userptr→VIDIOC_QBUF入队;- 采集任务
video_stream_task(4KB 栈、优先级 4、可固定到指定核):循环执行VIDIOC_DQBUF取帧 → 调用用户回调处理帧 →VIDIOC_QBUF还帧,形成生产者-消费者式的流水线;VIDIOC_STREAMON/VIDIOC_STREAMOFF负责开关流,app_video_stream_task_stop/restart提供停止与重启能力。
4. 帧处理回调:PPA 缩放与上屏(main.c)
camera_video_frame_operation回调(main.c)是"从摄像头到屏幕"的最后一公里:
- FPS 统计:每 50 帧基于
esp_timer_get_time()计算一次平均帧率,并打印帧的宽高与字节数; - 分辨率匹配分支:
- 摄像头分辨率大于LCD 分辨率时,构造
ppa_srm_oper_config_t:输入为摄像头帧,输出为 LCD 帧缓冲,按(camera - LCD)/2计算裁剪偏移实现居中裁剪,调用ppa_do_scale_rotate_mirror(PPA_TRANS_MODE_BLOCKING阻塞模式)完成缩放/旋转/镜像后,用esp_lcd_panel_draw_bitmap将结果刷到屏幕。代码注释也提醒:分辨率不匹配走 PPA 处理会带来一定帧率损失; - 摄像头分辨率不大于LCD 时,直接把摄像头缓冲(即复用的 LCD 帧缓冲)交给
esp_lcd_panel_draw_bitmap,实现零拷贝直通显示;
- 摄像头分辨率大于LCD 分辨率时,构造
- 颜色模式(
PPA_SRM_COLOR_MODE_RGB565/RGB888)与APP_VIDEO_FMT联动,保证 PPA 输入输出格式一致。
常见问题与调试建议
- 画面方向不对:示例默认开启 VFLIP/HFLIP(两个开关默认
y),若传感器安装方向不同导致画面镜像,可在 menuconfig 中关闭EXAMPLE_ENABLE_CAM_SENSOR_PIC_VFLIP或HFLIP后重新编译; - 初始化耗时偏长:可尝试提高
EXAMPLE_MIPI_CSI_SCCB_I2C_FREQ(范围 100kHz~400kHz),但务必确认传感器手册允许的频率上限; - 帧率低于预期:优先确认菜单中 SC2336 的输出格式是否为
RAW8 1024x600 30fps(与 LCD 同分辨率),避免触发 PPA 缩放;缓冲数建议保持 2~3,配合多帧缓冲(num_fbs)减少撕裂; - 需要零拷贝直通:确保摄像头分辨率与 LCD 分辨率一致(默认配置即为此设计),此时摄像头缓冲直接复用 LCD 帧缓冲,链路为纯直通模式;
- 串口无输出:检查 USB-UART 接线与
idf.py -p PORT monitor的端口号,确认开发板电源开关已打开。
小结
video_lcd_display 示例完整展示了 ESP32-P4 上"MIPI-CSI 摄像头 → esp_video/V4L2 → PPA 图像处理 → MIPI-DSI LCD"的端到端视频通路。通过 menuconfig 即可切换颜色格式、缓冲模式与镜像方向;在摄像头与屏幕同分辨率时,示例通过复用 LCD 帧缓冲实现零拷贝直通;分辨率不匹配时则借助 PPA 的 SRM 算子完成裁剪缩放。无论是快速评估"摄像头实时预览"类产品原型,还是作为自研视频采集方案的起点,本文梳理的接线、配置与源码调用链都能直接指导你的开发实践。
【免费下载链接】esp-iot-solutionEspressif IoT Library. IoT Device Drivers, Documentations and Solutions.项目地址: https://gitcode.com/GitHub_Trending/es/esp-iot-solution
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考