news 2026/9/20 2:13:15

ESP32-P4 摄像头画面实时上屏:基于 esp_video 与 MIPI-DSI 的 Video LCD Display 实战指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
ESP32-P4 摄像头画面实时上屏:基于 esp_video 与 MIPI-DSI 的 Video LCD Display 实战指南

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 显示的全过程,核心数据链路为:

  1. MIPI-CSI 摄像头(SC2336 传感器)采集原始图像;
  2. esp_video组件完成 CSI 控制器、ISP 流水线的初始化,并向上层暴露类似 Linux V4L2 的字符设备接口(/dev/video*);
  3. 应用层通过标准的 V4L2 ioctl 流程(VIDIOC_QUERYCAP/VIDIOC_REQBUFS/VIDIOC_QBUF/VIDIOC_DQBUF/VIDIOC_STREAMON)获取视频帧;
  4. 若摄像头分辨率与 LCD 分辨率不一致,使用PPA(Pixel Processing Accelerator,像素处理加速器)的 SRM(Scale-Rotate-Mirror)算子做缩放/裁剪;
  5. 最终通过esp_lcd_panel_draw_bitmap将帧数据写入MIPI-DSI 接口的 EK79007 LCD 驱动完成上屏。

工程目录结构如下(源码路径:main):

文件职责
main.c主流程:初始化 LCD、注册 PPA 客户端、打开摄像头、设置缓冲、启动采集任务
app_lcd.cLCD 初始化: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 BoardESP32-P4-Function-EV-Board
5V (任意一个)5V (任意一个)
GND (任意一个)GND (任意一个)
PWMGPIO26
LCD_RSTGPIO27
  • 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=yCONFIG_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.hEXAMPLE_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_PIXELEXAMPLE_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的执行顺序清晰展示了"先屏后摄"的初始化策略:

  1. app_lcd_init(&display_panel)初始化 EK79007 LCD 面板;
  2. 注册PPA SRM 客户端PPA_OPERATION_SRM),并查询 SPIRAM 对齐要求(esp_cache_get_alignment),为后续对齐分配缓冲做准备;
  3. app_video_main(NULL)初始化 esp_video(摄像头通路);
  4. app_video_open(EXAMPLE_CAM_DEV_PATH, APP_VIDEO_FMT)打开 MIPI-CSI 视频设备(设备路径宏为ESP_VIDEO_MIPI_CSI_DEVICE_NAME);
  5. 获取 LCD 帧缓冲(esp_lcd_dpi_panel_get_frame_buffer),缓冲数量与EXAMPLE_LCD_BUF_NUM(即摄像头缓冲数 2 或 3)一致;
  6. 根据是否开启内存映射,选择app_video_set_bufs(..., NULL)(MMAP 自动分配)或传入用户缓冲(USERPTR):
    • 若传感器输出恰好为 1024×600(CONFIG_CAMERA_SC2336_MIPI_RAW8_1024x600_30FPS),直接复用 LCD 帧缓冲作为摄像头缓冲,实现零拷贝;
    • 否则用heap_caps_aligned_calloc在 SPIRAM 中按缓存行对齐分配独立缓冲;
  7. 注册帧操作回调camera_video_frame_operation
  8. 启动摄像头采集任务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 面板 IOEK79007_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 = 27rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGBbits_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_openopen设备 →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=3MIN_BUFFER_COUNT=2)→VIDIOC_REQBUFS请求缓冲(传入fb时用V4L2_MEMORY_USERPTR,否则V4L2_MEMORY_MMAP)→ 逐个VIDIOC_QUERYBUFmmap或登记userptrVIDIOC_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_mirrorPPA_TRANS_MODE_BLOCKING阻塞模式)完成缩放/旋转/镜像后,用esp_lcd_panel_draw_bitmap将结果刷到屏幕。代码注释也提醒:分辨率不匹配走 PPA 处理会带来一定帧率损失
    • 摄像头分辨率不大于LCD 时,直接把摄像头缓冲(即复用的 LCD 帧缓冲)交给esp_lcd_panel_draw_bitmap,实现零拷贝直通显示;
  • 颜色模式(PPA_SRM_COLOR_MODE_RGB565/RGB888)与APP_VIDEO_FMT联动,保证 PPA 输入输出格式一致。

常见问题与调试建议

  • 画面方向不对:示例默认开启 VFLIP/HFLIP(两个开关默认y),若传感器安装方向不同导致画面镜像,可在 menuconfig 中关闭EXAMPLE_ENABLE_CAM_SENSOR_PIC_VFLIPHFLIP后重新编译;
  • 初始化耗时偏长:可尝试提高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),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/20 2:13:07

双闭环晶闸管直流调速系统:PI整定与Python仿真复现

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/20 2:12:57

AI+无代码5天交付小程序MVP:从需求到上线的完整路径

1. MVP选型第一课:为什么小程序适合用AI无代码快速验证上个月,一个做社区餐饮的老板找到我,说想上一个小程序做点餐,预算不高、时间又急,最好两周内能拿出一个能给别人演示的东西。以前接到这种需求,我的第…

作者头像 李华
网站建设 2026/9/20 2:10:32

蓝牙GFSK频谱深度解析:从BR/EDR到BLE 5.x的版本差异与测试要点

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/20 2:08:15

401 invalid_api_key?TaoToken + Roo Code 这样核对该模型 ID

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华