Skip to content

概念先知道

  • DVP:并行摄像头接口,数据线多、速度快,配合行/场同步信号传图像。
  • 传感器(Sensor):摄像头核心芯片(如 GC0308),通过 I2C 配置寄存器,例程先自动扫描识别型号。
  • 裁剪(Crop):只取画面的一部分(例程 416×240),减少数据处理量,适合只关心局部画面的场景。

例程功能简介

本页对应博流官方 SDK 的 cam_crop 例程(examples/peripherals/cam/cam_crop),演示 DVP 摄像头采集与裁剪

  • 通过 I2C 自动扫描识别图像传感器(image_sensor_scan);
  • bflb_cam_crop_hsync/vsync 把画面裁剪为 416×240
  • 配置 DMA 输出缓冲区后启动采集,循环取帧(bflb_cam_get_frame_count / get_frame_info / pop_one_frame)并统计 50 帧。
  • 同族例程examples/peripherals/cam/):cam_normal(常规采集)、cam_int(中断模式)、cam_yuv420(YUV420 输出)、cam_lcd(摄像头直接接屏显示)。

操作步骤

1
硬件准备

接一个 DVP 接口的摄像头模块(通过 I2C 配置传感器)。按 board_dvp_gpio_init() 的引脚连接 DVP 数据/时钟/行场同步线,摄像头 I2C 接开发板 I2C0,供电 3.3V。

2
进入例程目录

在终端进入 SDK 的 CAM 例程目录(前提:已按快速开始(Linux)Windows搭建好环境):

cd examples/peripherals/cam/cam_crop
3
编译工程

执行编译命令。Ai-M62(BL616)与 Ai-M61(BL618)同属一个系列,统一填写引脚最少的 bl616 即可:

make CHIP=bl616 BOARD=bl616dk
4
烧录固件

用 USB 线连接开发板,按住 BOOT 键(Ai-M61-32S-Kit 为 IO2)不放、短按 EN/RST 进入下载模式,然后执行烧录(把串口号换成实际值):

make flash CHIP=bl616 COMX=/dev/ttyUSB0
5
运行验证

打开串口助手(波特率 2000000)。例程先扫描并打印传感器型号(Sensor name: xxx),然后以裁剪分辨率 416×240 连续采集 50 帧,每帧打印帧信息;采集完成进入死循环。

代码执行流程

例程从启动到运行的完整流程如下(图中的循环箭头表示反复执行):

例程调用的 API 介绍

image_sensor_scan(i2c0, &sensor_config)

通过 I2C 扫描识别摄像头传感器,返回传感器配置(分辨率、寄存器初始化序列等)。

参数

  • i2c:I2C 设备句柄
  • sensor_configstruct image_sensor_config_s * 输出传感器配置

返回值:成功返回 1;识别失败返回 0

bflb_cam_crop_hsync / bflb_cam_crop_vsync(cam, start, end)

设置行/场方向裁剪范围(必须在 bflb_cam_init 之前调用)。

参数

  • cam:CAM 设备句柄(bflb_device_get_by_name("cam0")
  • start / end:裁剪起止像素

返回值:成功返回 0;失败返回负值错误码

bflb_cam_init / bflb_cam_start(...)

按配置初始化 CAM(输入源 DVP、输出格式/缓冲区)并启动采集。

参数struct bflb_cam_config_s 配置

返回值:成功返回 0;失败返回负值错误码

bflb_cam_get_frame_count / get_frame_info / pop_one_frame(...)

查询可用帧数、获取帧数据指针与大小、弹出已处理帧,配合 DMA 输出缓冲区实现连续取帧。

参数:CAM 设备句柄、帧信息输出

返回值:成功返回 0;帧数/帧信息按输出参数返回

完整代码

以下为 cam_crop/main.c 完整源码,与官方示例(examples/peripherals/cam/cam_crop)一致;点灯引脚已适配 Ai-M61/62-32S-Kit 板载 RGB 灯,默认折叠,点击展开:

📜 点击展开 cam_crop/main.c 完整代码
c
#include "bflb_mtimer.h"
#include "bflb_i2c.h"
#include "bflb_cam.h"
#include "image_sensor.h"
#include "board.h"
#include "malloc.h"

#define CROP_WQVGA_X           416
#define CROP_WQVGA_Y           240
#define CAM_OUTPUT_BUFFER_SIZE (CROP_WQVGA_X * CROP_WQVGA_Y * 2 * 2)
#define CAM_FRAME_COUNT_USE    50

static struct bflb_device_s *i2c0;
static struct bflb_device_s *cam0;

int main(void)
{
    uint32_t i, pic_size;
    uint8_t *pic;
    struct bflb_cam_config_s cam_config;
    struct image_sensor_config_s *sensor_config;

    board_init();
    board_dvp_gpio_init();

    i2c0 = bflb_device_get_by_name("i2c0");
    cam0 = bflb_device_get_by_name("cam0");

    if (image_sensor_scan(i2c0, &sensor_config)) {
        printf("\r\nSensor name: %s\r\n", sensor_config->name);
    } else {
        printf("\r\nError! Can't identify sensor!\r\n");
        while (1) {}
    }

    /* Crop resolution_x, should be set before init */
    bflb_cam_crop_hsync(cam0, 112, 112 + CROP_WQVGA_X);
    /* Crop resolution_y, should be set before init */
    bflb_cam_crop_vsync(cam0, 120, 120 + CROP_WQVGA_Y);

    memcpy(&cam_config, sensor_config, IMAGE_SENSOR_INFO_COPY_SIZE);
    cam_config.with_mjpeg = false;
    cam_config.input_source = CAM_INPUT_SOURCE_DVP;
    cam_config.output_format = CAM_OUTPUT_FORMAT_AUTO;
    cam_config.output_bufaddr = (uint32_t)memalign(32, CAM_OUTPUT_BUFFER_SIZE);
    if (cam_config.output_bufaddr == 0) {
        printf("\r\nError! Can't allocate memory!\r\n");
        while (1) {}
    }
    cam_config.output_bufsize = CAM_OUTPUT_BUFFER_SIZE;

    bflb_cam_init(cam0, &cam_config);
#if defined(BL618DG)
    bflb_cam_int_mask(cam0, CAM_INTMASK_NORMAL, false);
#endif
    bflb_cam_start(cam0);

    for (i = 0; i < CAM_FRAME_COUNT_USE; i++) {
        while (bflb_cam_get_frame_count(cam0) == 0) {}
        pic_size = bflb_cam_get_frame_info(cam0, &pic);
#if defined(BL618DG)
        bflb_cam_int_clear(cam0, CAM_INTCLR_NORMAL);
#else
        bflb_cam_pop_one_frame(cam0);
#endif
        printf("pop picture %d: 0x%08x, len: %d\r\n", i, (uint32_t)pic, pic_size);
    }

    bflb_cam_stop(cam0);

    //for (i = 0; i < pic_size; i++) {
    //    printf("%02x", pic[i]);
    //}
    //printf("\r\n");

    printf("end\r\n");

    while (1) {
        bflb_mtimer_delay_ms(1000);
    }
}

FAQ

提示 Can't identify sensor

摄像头 I2C 地址或接线不对:确认传感器型号在 image_sensor 组件支持列表内,I2C SDA/SCL 接对且共地供电。

帧计数不增长

确认 DVP 数据/时钟/行场同步线接对、传感器已输出;确认输出缓冲区分配成功(memalign)且大小足够 416×240×2×2。

想采集其他分辨率

修改 CROP_WQVGA_X/Y 与裁剪范围,并同步调整 CAM_OUTPUT_BUFFER_SIZE

遇到问题?

如有其他问题,请到统一的提问与讨论区:Ai-Thinker Discussions

Released under the MIT License. Build Time 2026-09-11 14:52:23