Skip to content

摄像头应用

1. 文档概述

1.1 文档目的

本文档旨在详细说明模组外接camera 的硬件连接、软件接口及使用的注意事项。功能覆盖拍照/预览/图片压缩/扫码/数据存储/数据传输等场景,如智能扫码设备、智能水表/电表/气表等

功能 状态 备注
拍照 已实现 支持YUV和ONLY Y格式
预览 开发中
图片压缩(JPEG) 已实现 支持YUV/ONLY Y数据编码成jpeg
扫码 (ZBAR) 已实现 支持一维码(CODE128 EAN-13)、 二维码(QR CODE)识别
扫码 (QY-ZXING) 已实现 商用扫码库,支持多种码制识别

1.2 开发板框图

2. 引脚定义

摄像头接口

引脚号 信号名称 对应模块管脚号 说明
1 GND
2 CAM_VDD 摄像头电源
3 CAM_VDDIO 24 摄像头数字电源
4 CAM_I2C_SCL 57 摄像头I2C时钟信号
5 CAM_I2C_SDA 58 摄像头I2C数据信号
6 GND
7 CAM_SPI_CLK 80 摄像头SPI时钟信号
8 GND
9 CAM_MCLK 54 摄像头主时钟信号
10 CAM_SPI_D0 55 摄像头SPI数据信号0
11 CAM_SPI_D1 56 摄像头SPI数据信号1
12 CAM_PWDN 81 摄像头POWER DOWN控制信号
13 PIN39 39 预留功能
14 PIN40 40 预留功能
15 VBAT 42 闪光灯电源

3. 软件环境

下载yopen代码

git clone https://gitee.com/yuge-info/yopen.git

关键代码

  • 围绕 Camera 功能搭建多组件协同的软件架构,各组件功能及关联接口如下:
组件/头文件 功能 相关接口定义
components\camera camera组件、提供拍照、预览(开发中),支持 YUYV、ONLY Y、RGB565 数据格式输出 cameraDev.h
components\lcd lcd组件、支持 Camera 数据预览显示(开发中) lcdDrv.h
components\zbar zbar开源组件、默认支持指定一维 / 二维码识别,可配置编码格式 zbar.h、zbar_config.h
components\qy_zxing 擎亚商用扫码库、支持多种码制识别,需license授权 qy_zxing.h
components\jpeg jpeg组件、支持 YUYV/ONLY Y 格式转 JPEG yopen_jpeg.h
components\ftp ftp组件、实现压缩后图片向服务器终端设备的上传 ftpClient.h
yopen_fs.h 文件系统接口、用于存储压缩后的图片
yopen_uart.h 串口接口、用于传输数据在PC显示
yopen_power.h pwrkey接口、通过pwrkey按键触发拍照功能
  • 文档提供 3 个核心 Demo,覆盖 Camera 核心场景的实现逻辑:
  • demo_camera.c:pwrkey 按键触发拍照 → JPEG 压缩 → FTP 上传压缩数据 + 本地文件系统同步保存。
  • demo_zbar.c:拍照采集条码数据 → 传入 zbar 解码接口 → 解析并输出编码类型、编码内容。
  • demo_qy_zxing.c:拍照采集条码数据 → 传入擎亚扫码库解码 → 获取解码结果并通过串口输出。

demo_camera.c 介绍

  • 打开camera, 采集yuyv数据
cameraDrvFunc_t* drv =  CamOpen("gc032a_2ddr", NULL, false);
  • 拍照,获取一帧数据
char* pic = camTakePicture(drv); 
  • jpeg编码, 保存到文件系统中

使用 yopen_jpeg 硬件编码器进行JPEG编码,支持YUYV格式输入:

#define CONFGI_JPG_PATH "output.jpg"

jpeg_encode(pic, CONFGI_JPG_PATH);

static bool jpeg_encode(char *src, char *output_path)
{
    void *hJpeg = NULL;
    YOPEN_JPEG_ENC_PARAM enc_param;
    YOPEN_JPEG_IMAGE_BUF img_buf;
    unsigned int suggested_buf_len = 0;
    unsigned int actual_buf_len = 0;
    unsigned char *jpeg_buf = NULL;
    QFILE fd;
    int ret;
    uint32_t start_tick, end_tick, encode_time_ms;

    hJpeg = yopen_jpegE_create();
    if (hJpeg == NULL)
    {
        DEMO_CAMERA_TRACE("yopen_jpegE_create fail");
        return false;
    }

    memset(&enc_param, 0, sizeof(YOPEN_JPEG_ENC_PARAM));
    enc_param.eFmt = YOPEN_JPEG_COLOR_FMT_YUYV;
    enc_param.uWidth = IMG_WIDTH;
    enc_param.uHeight = IMG_HEIGHT;
    enc_param.uQuality = IMG_ENCODE_QUALITY;

    ret = yopen_jpegE_set_param(hJpeg, &enc_param, &suggested_buf_len);
    if (ret != 0)
    {
        DEMO_CAMERA_TRACE("yopen_jpegE_set_param fail ret(%d)", ret);
        yopen_jpegE_destroy(hJpeg);
        return false;
    }

    jpeg_buf = (unsigned char *)malloc(suggested_buf_len);
    if (jpeg_buf == NULL)
    {
        DEMO_CAMERA_TRACE("malloc jpeg buf fail");
        yopen_jpegE_destroy(hJpeg);
        return false;
    }

    memset(&img_buf, 0, sizeof(YOPEN_JPEG_IMAGE_BUF));
    img_buf.eFmt = YOPEN_JPEG_COLOR_FMT_YUYV;
    img_buf.uWidth = IMG_WIDTH;
    img_buf.uHeight = IMG_HEIGHT;
    img_buf.pData[0] = (void *)src;

    actual_buf_len = suggested_buf_len;

    start_tick = yopen_rtos_get_system_tick();
    ret = yopen_jpegE_encode(hJpeg, &img_buf, jpeg_buf, &actual_buf_len);
    end_tick = yopen_rtos_get_system_tick();
    encode_time_ms = end_tick - start_tick;

    if (ret != 0)
    {
        DEMO_CAMERA_TRACE("yopen_jpegE_encode fail ret(%d)", ret);
        free(jpeg_buf);
        yopen_jpegE_destroy(hJpeg);
        return false;
    }

    DEMO_CAMERA_TRACE("jpeg encode done: %d bytes in %d ms", actual_buf_len, encode_time_ms);

    fd = yopen_fopen(output_path, "wb+");
    if (fd < YOPEN_FS_OK)
    {
        DEMO_CAMERA_TRACE("open output file fail fd(%d)", fd);
        free(jpeg_buf);
        yopen_jpegE_destroy(hJpeg);
        return false;
    }

    ret = yopen_fwrite(jpeg_buf, 1, actual_buf_len, fd);
    yopen_fclose(fd);

    free(jpeg_buf);
    yopen_jpegE_destroy(hJpeg);

    return true;
}

yopen_jpeg 编码接口说明

接口函数 功能描述 参数说明 返回值
yopen_jpegE_create 创建JPEG编码器句柄 成功返回句柄指针,失败返回NULL
yopen_jpegE_set_param 设置编码参数 hJpeg:编码器句柄; pParam:编码参数结构; pSuggBufLen:建议缓冲区大小(输出) 0成功,<0失败
yopen_jpegE_encode 执行JPEG编码 hJpeg:编码器句柄; pIbuf:图像缓冲区; pBuf:输出缓冲区; pBufLen:缓冲区大小/实际输出长度 0成功,<0失败
yopen_jpegE_destroy 销毁JPEG编码器句柄 hJpeg:编码器句柄

YOPEN_JPEG_ENC_PARAM 参数说明

字段 类型 说明
eFmt YOPEN_JPEG_COLOR_FMT 输入图像格式:YOPEN_JPEG_COLOR_FMT_YUYV/YOPEN_JPEG_COLOR_FMT_Y等
uWidth unsigned int 图像宽度(像素)
uHeight unsigned int 图像高度(像素)
uQuality unsigned int 编码质量,1~100,值越大质量越高
  • ftp 上传
ftp_upload(CONFGI_JPG_PATH);

void ftp_upload(char *filename)
{
    static NetBuf_t* ftpClientNetBuf = NULL;
    yopen_nw_reg_status_info_s nw_status;

    FtpClient* ftpClient = getFtpClient();

    yopen_nw_get_reg_status(0, &nw_status);

    if(nw_status.data_reg.state != YOPEN_NW_REG_STATE_HOME_NETWORK &&
        nw_status.data_reg.state != YOPEN_NW_REG_STATE_ROAMING)
    {
        yopen_trace("=== ftp upload network not ready ===");
        return;
    }

    yopen_trace("=== ftp upload ftpClient %x ===", ftpClient);

    int connect = ftpClient->ftpClientConnect(CONFIG_FTP_SERVER, CONFIG_FTP_PORT, &ftpClientNetBuf);
    yopen_trace("=== ftp upload connect %d ===", connect);

    int login = ftpClient->ftpClientLogin(CONFIG_FTP_USER, CONFIG_FTP_PASSWD, ftpClientNetBuf);
    yopen_trace("=== ftp upload login %d ===", login);

    int put = ftpClient->ftpClientPut(filename, filename, FTP_CLIENT_BINARY, ftpClientNetBuf);
    yopen_trace("=== ftp upload put %d ===", put);

    ftpClient->ftpClientQuit(ftpClientNetBuf);
    yopen_trace("=== ftp upload quit %d ===");
}

demo_zbar.c介绍

  • 打开camera, 采集ONLY Y数据
cameraDrvFunc_t* drv =  CamOpen("gc032a_2ddr", NULL, true);
  • 拍照, 获取一维码、二维码数据
char* pic = camTakePicture(drv); 
  • 解析,输出编码格式和内容
prvZbarScannerRun(CAMERA_WIDTH, CAMERA_HEIGHT, CAMERA_WIDTH*CAMERA_HEIGHT, (unsigned char *)pic);

static void prvZbarScannerRun(int width, int height, int size, unsigned char *dataInput)
{
    int len;
    char *data;

    int handle = zbar_scanner_open(width, height, size, (unsigned char *)dataInput);

    if (handle)
    {
        do
        {   
            char *temp = malloc(4096); 
            data = zbar_get_data(handle, &len);
            data[len] = 0;

            yopen_trace("zbar_scan: %s,%d,%s", zbar_get_type(handle), len, data);

            sprintf(temp, "type:%s,len=%d,data:\r\n%s\r\n", zbar_get_type(handle), len, data); 
            uart_write((char *)temp, strlen(temp));
            free(temp);

        }while(zbar_find_nextData(handle) > 0);

        zbar_scanner_close((int *)handle);
    }
    else
    {
        yopen_trace("zbar_scan: no data");
    }
}

zbar 解码接口说明

接口函数 功能描述 参数说明 返回值
zbar_create 创建zbar解码器 成功返回zbar_t指针,失败返回NULL
zbar_run 执行条码/二维码解码 zbar:解码器指针; width:图像宽度; height:图像高度; data:图像数据(灰度) >0成功,<=0失败
zbar_get_data_ptr 获取解码结果数据指针 zbar:解码器指针; len:结果长度(输出) 返回数据指针
zbar_symbol_get_type 获取条码类型 symbol:条码符号指针 返回zbar_symbol_type_t类型
zbar_get_symbol_name 获取条码类型名称 typ:条码类型 返回类型名称字符串
zbar_find_next_data 查找下一个条码数据 zbar:解码器指针 >0成功找到,<=0未找到
zbar_destory 销毁zbar解码器 zbar:解码器指针

demo_qy_zxing.c介绍(商用扫码库)

  • 简介

demo_qy_zxing.c 演示了使用擎亚(QY)商用扫码库进行条码/二维码识别。该库基于ZXing算法优化,支持多种码制,识别率高,性能优异。

支持码制: - 一维码:CODE-128 - 二维码:QR Code

授权方式: 该库为商用授权版本,使用前需要获取license授权。支持两种授权方式: 1. HTTP在线授权:通过 am_http_get_license() 接口在线获取license 2. NVM离线授权:通过 am_nvmWriteLicense() 接口写入预先获取的license

  • 打开camera, 采集ONLY Y数据
cameraDrvFunc_t* drv =  CamOpen("gc032a_2ddr", NULL, true);
  • 获取license授权(HTTP方式)
if(!am_http_get_license("6dcb09a23ef54d929b2a85371c6df1bb"))
{
    DEMO_QYZXING_TRACE("am_http_get_license failed");
    goto exit;
}
  • 初始化解码器
if(!Initial_Decoder())
{
    DEMO_QYZXING_TRACE("Initial_Decoder failed");
    goto exit;
}
  • 拍照并解码
char* pic = camTakePicture(drv); 
if (pic)
{
    ret = Decoding_Image((unsigned char*)pic, CAMERA_WIDTH, CAMERA_HEIGHT);
    unsigned int result_len = GetResultLength();

    if(ret && result_len > 0)
    {
        char *result = malloc(result_len+1);
        memset(result, 0, result_len+1);
        GetDecoderResult((unsigned char*)result);
        uart_write(result, result_len);
        free(result);
    }
}

qy_zxing 解码接口说明

接口函数 功能描述 参数说明 返回值
am_http_get_license 通过HTTP获取license授权(在线方式) license_key:授权密钥 true成功,false失败
am_nvmWriteLicense 写入license授权(离线方式) data:license数据 0成功,<0失败
Initial_Decoder 初始化解码器,只需调用一次 1成功,0失败
Decoding_Image 解码图像数据 img_buffer:灰度图像数据指针; width:图像宽度; height:图像高度 1成功,0失败
GetResultLength 获取解码结果长度 成功返回结果长度,0表示失败或无数据
GetDecoderResult 获取解码结果内容 result:存储结果的缓冲区(需外部申请足够空间) 1成功,0失败

注意事项

  1. 图像格式:输入图像必须为灰度图像(ONLY Y格式),通过 CamOpen 的第三个参数 true 指定:

    cameraDrvFunc_t* drv = CamOpen("bf30a2_1sdr", NULL, true);
    

  2. 网络要求:使用HTTP授权方式时,需要确保网络已注册成功(HOME_NETWORK或ROAMING状态)。

  3. 内存管理:解码结果缓冲区需要调用者自行分配和释放。

工程编译

# 命令行下执行  demo描述:按键触发拍照 → JPEG 压缩 → FTP 上传压缩数据 + 本地文件系统同步保存。
build.bat YM310_X09S.U62 camera

# 命令行下执行 demo描述:拍照采集条码数据 → 传入 zbar 解码接口 → 解析并输出编码类型、编码内容。
build.bat YM310_X09S.U62 zbar

# 命令行下执行 demo描述:拍照采集条码数据 → 传入擎亚扫码库解码 → 获取解码结果并通过串口输出。
build.bat YM310_X09S.U62 qy_zxing