6.12. 如何调试一款新摄像头
本节旨在让用户快速调试新型号(dvp/spi接口)摄像头出图;
AC79 有两个 ISC (图像传感器控制模块)(ISC0/1),用于接收片外 Image CMOS Sensor 的图像数据,完成数据重排和处理;
其支持传统 8bit 的 DVP、BT601、BT656 接口,除此之外还支持以上接口的串行化,如 4/2/1bit 的 DVP、BT601、BT656,支持 SPI 模式;
推荐使用ISC接收,兼容DVP和SPI模式,用户不需要关心底层是如何收数据,仅需根据需求修改接口配置及摄像头寄存器配置,加快工程的开发进度。
6.12.1. 必要说明
板载硬件说明
板载摄像头型号及接口:
camera0-gc2145-dvp
camera1-gc0310-SPI
AC79最大支持 96Mhz-pclk 输入(考虑稳定性,不建议pclk大于60Mhz),最大像素为1280×720
调试新的摄像头驱动建议以已经适配的摄像头驱动作为参考调试,硬件电路参照AC79_DevKitBoard原理图,开源板引出了摄像头复用IO
调试摄像头期间建议:准备 1 台逻辑分析仪、1 台示波器
摄像头出图流程:检验摄像头(check ID)->向摄像头发送寄存器配置->主控接收数据处理->推送到屏幕显示
dvp和spi摄像头调试过程类似,区别在于硬件接口、接收模式上,请参考适配例程中的摄像头型号驱动进行配置
6.12.2. 环境配置方法
调试DVP-8bit、1bit、2bit及4bit摄像头建议在
apps/common/example/video/camera/dvp/main.c
环境下进行(使用ISC接收)调试SPI-1/2bit摄像头可以在
apps/common/example/video/camera/spi/main.c
环境下进行(SPI接收)选择
demo/demo_DevKitBoard
工程运行
apps/demo/demo_DevKitBoard/include/demo_config.h
中打开对应的宏(确保其余宏全部关闭)//SPI: #define CONFIG_SPI_VIDEO_ENABLE //DVP(ISC): #define USE_CAMERA_DVP_SHOW_TO_LCD_DEMO //如果demo_config.h没有对应的宏,请在对应的main.c中#define以使能即可跑对应的main.c
6.12.3. 调试步骤
第一步:摄像头引脚与芯片IO正确连接,板级配置对应IO
若硬件连接与板载摄像头一致,请暂时取下板载摄像头(避免通讯冲突)
板级配置文件路径:
apps/demo/demo_DevKitBoard/board/wl82/DevKitBoard.c
主要配置IIC、SPI(针对SPI摄像头)及摄像头数据IO、时钟IO//*********************************************************************************// // IIC模块配置 // //*********************************************************************************// #ifdef CONFIG_IIC_ENABLE //板载摄像头默认使用iic0 SW_IIC_PLATFORM_DATA_BEGIN(sw_iic0_data)//软件iic .clk_pin = IO_PORTH_00,//SCL_IO .dat_pin = IO_PORTH_01,//SDA_IO .sw_iic_delay = 50, SW_IIC_PLATFORM_DATA_END() #endif //**********************************END*******************************************// //*********************************************************************************// // SPI模块配置 // //*********************************************************************************// #ifdef CONFIG_SPI_ENABLE //spi/main.c默认使用spi2 SPI2_PLATFORM_DATA_BEGIN(spi2_data) .clk = 40000000, .mode = SPI_STD_MODE,//SPI_1WIRE_MODE(单线模式) SPI_STD_MODE(双线模式) SPI_DUAL_MODE(全双工模式) SPI_QUAD_MODE(四线模式) .attr = SPI_MODE_SLAVE | SPI_SCLK_L_UPH_SMPH | SPI_UNIDIR_MODE,//从机,CLK高 更新数据高,单向模式 .port = 'C', SPI2_PLATFORM_DATA_END() #endif //**********************************END*******************************************// //*********************************************************************************// // 摄像头模块配置 // //*********************************************************************************// #ifdef CONFIG_VIDEO_ENABLE //*****************************************camera0-ISC0接收(DVP-8bit配置为例)****************************************// static const struct camera_platform_data camera0_data = { .xclk_gpio = IO_PORTH_02,//注意: 如果硬件xclk接到芯片IO,则会占用OUTPUT_CHANNEL1 .reset_gpio = IO_PORTH_03,//复位IO,一般该引脚可以直接接3.3V的高电平(根据数据手册),可不需要特定IO来控制 .online_detect = NULL,//默认NULL即可 .pwdn_gpio = -1,//pwdn引脚可以配合引脚写具体IO如IO_PORTC_04,一般摄像头pwdn引脚直接接地即可,具体参考摄像头数据手册 .power_value = 0,//pwdn引脚使用IO控制时的正常工作pwdn引脚电平 .interface = SEN_INTERFACE0,//SEN_INTERFACE_CSI2,//默认即可 .dvp={ //dvp_IO配置 .pclk_gpio = IO_PORTA_08, .hsync_gpio = IO_PORTA_09, .vsync_gpio = IO_PORTA_10, .group_port = ISC_GROUPA, .data_gpio = { IO_PORTA_07, IO_PORTA_06, IO_PORTA_05, IO_PORTA_04, IO_PORTA_03, IO_PORTA_02, IO_PORTA_01, IO_PORTA_00, -1, -1, }, } }; static const struct video_subdevice_data video0_subdev_data[] = {//镜头设备参数 { VIDEO_TAG_CAMERA, (void *)&camera0_data }, }; static const struct video_platform_data video0_data = {//video0参数,设备列表参数需要该参数 .data = video0_subdev_data, .num = ARRAY_SIZE(video0_subdev_data), }; //*****************************************camera1-SPI接收****************************************// static const struct camera_platform_data camera1_data = { .xclk_gpio = -1,//IO_PORTB_02,//IO_PORTC_08,//IO_PORTC_06,//注意: 如果硬件xclk接到芯片IO,则会占用OUTPUT_CHANNEL1 .reset_gpio = IO_PORTH_03, .online_detect = NULL, .pwdn_gpio = -1, .power_value = 0, .interface = -1, .dvp={ .group_port = -1, .pclk_gpio = -1, .hsync_gpio = -1, .vsync_gpio = -1, .data_gpio={-1}, } }; static const struct video_subdevice_data video1_subdev_data[] = {//镜头设备参数 { VIDEO_TAG_CAMERA, (void *)&camera1_data }, }; static const struct video_platform_data video1_data = {//video1参数,设备列表参数需要该参数 .data = video1_subdev_data, .num = ARRAY_SIZE(video1_subdev_data), }; #endif //**********************************END*******************************************//
第二步:摄像头驱动配置,check摄像头ID,检验是否成功与摄像头通信
Device Address、Sensor_ID请在相应摄像头的datasheet中查询
以gc2145为例:
//GC2145.C #define GC2145_DVP_WRCMD 0x78//Device Address #define GC2145_DVP_RDCMD 0x79 s32 GC2145_ID_check(void)//check摄像头ID { u8 pid = 0x00; u8 ver = 0x00; u8 i ; for (i = 0; i < 3; i++) { rdGC2145Reg(0xf0, &pid);//Sensor_ID_Address rdGC2145Reg(0xf1, &ver); } puts("Sensor PID \n"); puts("\n"); if (pid != 0x21 || ver != 0x45) { //Sensor_ID_DefaultValue puts("\n----not GC2145_DVP-----\n"); return -1; } puts("\n----hello GC2145_DVP-----\n");//打印此行说明成功check到摄像头ID通讯成功 return 0; }
第三步:根据摄像头官方驱动例程更改寄存器配置及注册配置
以DVP-8bit为例
//GC2145.C #define GC2145_DEVP_INPUT_W 1280//摄像头输出分辨率,需要与摄像头实际输出分辨率一致 #define GC2145_DEVP_INPUT_H 720 static const struct reginfo sensor_init_data[] = { //寄存器配置(配置重点),主要关注输出接口、输出数据格式、输出线数、输出分辨率和pclk频率等相关寄存器 //{Address,Value} //sensor数据输出正确是接收正确的前提 {0xfe, 0xf0}, {0xfe, 0xf0}, {0xfe, 0xf0}, {0xfc, 0x06}, {0xf6, 0x00}, {0xf7, 0x1d}, //省略... }; REGISTER_CAMERA(GC2145) = { //ISC接收摄像头注册在REGISTER_CAMERA;SPI接收摄像头注册在REGISTER_CAMERA1 .logo = "GC2145", .isp_dev = ISP_DEV_NONE, //ISP_DEV_NONE 或 ISP_DEV_0,对应”iic0”设备 .in_format = SEN_IN_FORMAT_YUYV,//YUV排列顺序,与摄像头输出顺序一致 .mbus_type = SEN_MBUS_PARALLEL, //数据格式配置,与摄像头输出格式一致,详见isp_dev.h .mbus_config = SEN_MBUS_DATA_WIDTH_8B | SEN_MBUS_HSYNC_ACTIVE_HIGH | \ SEN_MBUS_PCLK_SAMPLE_FALLING | SEN_MBUS_VSYNC_ACTIVE_HIGH, //线数配置及采样配置,详见isp_dev.h #if CONFIG_CAMERA_H_V_EXCHANGE .sync_config = SEN_MBUS_SYNC0_VSYNC_SYNC1_HSYNC,//WL82/AC791才可以H-V SYNC互换,请留意 #endif //省略... } };
第四步:参考摄像头数据手册修改寄存器配置,根据需求调整输出效果。
输出分辨率的大小:裁剪窗口相关寄存器
输出帧率提高:提高pclk频率、缩小输出数据帧间距行间距
…
6.12.4. 适配例程
- ISC接收
1bit-SPI-bt656:参考byd20a6.c 1bit 配置
2bit-SPI-bt656:参考byd20a6.c 2bit 配置
4bit-SPI-bt656:参考byd20a6.c 4bit 配置
8bit-DVP:参考GC2145.c 配置(上述第一、三步举例)
使用ISC接收配置举例:
1/2/4bit接收时.data_gpio的第一个IO配置必须是最低位的对应IO,以下为4bit:PA0-PA3接收配置举例:
//DevKitBoard.c static const struct camera_platform_data camera0_data = { .xclk_gpio = IO_PORTH_02,//xclk .reset_gpio = IO_PORTH_03, .online_detect = NULL, .pwdn_gpio = -1, .power_value = 0, .interface = SEN_INTERFACE0, .dvp={ .pclk_gpio = IO_PORTA_08,//pclk .hsync_gpio = -1, .vsync_gpio = -1, .group_port = ISC_GROUPA, .data_gpio = { //接收数据IO配置,按此.data_gpio配置的接收IO为PA0-PA3,对应sensor的D0-D3 IO_PORTA_00,//低 IO_PORTA_01, IO_PORTA_02, IO_PORTA_03,//高 -1, -1, -1, -1, -1, -1, }, } };//byd20a6.c REGISTER_CAMERA(BYD20a6) = { .isp_dev = ISP_DEV_NONE, .in_format = SEN_IN_FORMAT_YVYU,//与摄像头输出格式一致 .mbus_type = SEN_MBUS_BT656,//与摄像头输出数据格式一致(此例程1/2/4bit帧协议均为:帧头:ff0000ab,帧尾:ff0000b6,行头:ff000080, 行尾:ff00009d) //.mbus_config = SEN_MBUS_DATA_WIDTH_1B | SEN_MBUS_PCLK_SAMPLE_FALLING,//1bit接收|下降沿采样 //.mbus_config = SEN_MBUS_DATA_WIDTH_2B | SEN_MBUS_PCLK_SAMPLE_FALLING,//2bit接收|下降沿采样 .mbus_config = SEN_MBUS_DATA_WIDTH_4B | SEN_MBUS_PCLK_SAMPLE_FALLING,//4bit接收|下降沿采样 //省略... };
- SPI接收
SPI-1bit:参考GC0310.c 1bit 配置
SPI-2bit:参考GC0310.c 2bit 配置
板级配置参考上述第一步配置
6.12.5. IO反转接收功能配置说明
.data_gpio按照正常正序配置,在摄像头驱动中的.mbus_config添加
SEN_MBUS_DATA_WIDTH_REVERSE
即可以下配置为4bit:PA4-PA7、IO反转接收举例,即D0-PA7,D1-PA6,D2-PA5,D3-PA4对应
//DevKitBoard.c .data_gpio = { IO_PORTA_04, //按照正常正序配置 IO_PORTA_05, IO_PORTA_06, IO_PORTA_07, -1, -1, -1, -1, -1, -1, },//byd20a6.c .mbus_config = SEN_MBUS_DATA_WIDTH_4B | SEN_MBUS_PCLK_SAMPLE_FALLING | SEN_MBUS_DATA_WIDTH_REVERSE ,//4bit接收|下降沿采样|反转接收
6.12.6. 报错总结
- IIC读取ID不匹配:
驱动里面的 iic 设备不对应(“iic0”还是“iic1”),原因为:.isp_dev = xx 不对;
board.c 的 iic 的 IO 不对;
摄像头的 xmclk 引脚没有时钟输入,检查 board.c 的 xclk 时钟引脚;
摄像头的 power_down 引脚的电平没接对,一般正常工作低电平(要看数据手册,看看是低电平还是高电平);
摄像头的 reset 引脚的电平是否正确;
检查Device Address、Sensor_ID配置是否正确。
- 出现 video_ioct: err = 11 或 yuv recv timeout:
硬件没有收到时钟,检查 pclk 的有没有时钟输出(示波器看下有没有时钟);
pclk频率配置过高,镜头输出时钟不稳定,尝试降低频率;
接线问题:确定 PCLK 和 DATA 数据正确接对在对应 IO,连接没有断线可能;
VDDIO电压错误;
协议不正确:逻辑分析仪 100M 采样率抓数据进行解析帧头帧尾、行头行尾;
ISC 接收情况下检查帧协议是否正确:帧头:ff0000ab,帧尾:ff0000b6,行头:ff000080, 行尾:ff00009d。
- 报错 isc line err 行出错,原因可能有:
初始化 bt656 分辨率和实际摄像头输出的分辨率不一致;
在 2/4/8bit 模式下,可能因为数据位 IO 反接(isc line err 打印很猛下大部分因为这个原因);
协议不符合。
- 报错 isc bandwith err,带宽不够,原因可能有:
数据瑕疵;
性能带宽不足,如果能正常出图可忽略。
- 使用 SPI 接收,出现—->SPI_FSTART = 0x%x , 0x%x ,recv data err , reinit spi camera :
数据头出现问题,用逻辑分析仪解析spi数据是否正确。若数据不正确,检查接线及数据格式配置;若数据正确,spi接收不正确,则大部分原因为:配置的边沿采样不符合,尝试更换边沿采样配置。
- 图像显示异常:
数据瑕疵;
出现大片绿色:YUV格式顺序错误,在摄像头驱动.c中配置YUV格式顺序;
出现图像条纹、显示分格:采样边沿出错、分辨率设置与镜头实际输出分辨率不一致;
出现蓝色条纹、噪点:检查电源供电
以上报错可能来源于电压不稳定、数据线时钟线毛刺,请确保硬件的稳定性。