Foreword
Ov7670由于都是拆机货,质量太差了,所以找了个替换,GC0328C,不过GC0328C的资料比较少,很多地方没解释清楚,现成代码注释写的很少,大部分都要自己重新对一遍寄存器
GC0328C
参考仓库
https://github.com/RT-Thread-Studio/sdk-bsp-stm32h750-realthread-artpi/blob/master/libraries/drivers/include/drv_gc0328c.h
https://github.com/fukuen/Maixduino_GC0328/tree/master
https://github.com/Hengbote/RT-Thread_GC0308
可以参考的板子比较多,ART-Pi,MaixPy,K210,MT62xx,MT65xx,SC6531,SP7731
多数资料里都有一个类似的图
寄存器
GC0328C的寄存器比较复杂,比较多,所以他用了一个切页的方式来切换寄存器映射
所以可以看到手册里P0:xxx
P1:xxx
就是不同页的寄存器
读取和写入的时候都需要注意当前是哪一页
地址
一般GC0328地址有2种,一个是0x21,一个是0x42,其实都指同一个
21是主地址,42是加了写偏移的,43是读偏移后的地址
时钟
Timing 这里比较复杂,基本都是参考别人的设置
输出极性
输出极性,需要和配置的DMA或者DCMI,CSI等匹配上
HSYNC和VSYNC,一般设置的极性都是1有效
{0x46 , 0x03}, // SYNC_mode
在ST中这个极性和DCMI的极性设置是反过来的,需要注意一下
帧率控制
帧率主要是通过曝光时间来控制
const rt_uint8_t gc0328c_10pfs_talbe[][2] =
{
// all AEC_EXP_LEVEL_X set to 0x51e = 1310
{0xFE,0x01}, // page p1
{0x2B,0x05}, // AEC_EXP_LEVEL_0 [11:8]
{0x2C,0x1e}, // AEC_EXP_LEVEL_0 [7:0]
{0x2D,0x05}, // AEC_EXP_LEVEL_1
{0x2E,0x1e},
{0x2F,0x05}, // AEC_EXP_LEVEL_2
{0x30,0x1e},
{0x31,0x05}, // AEC_EXP_LEVEL_3
{0x32,0x1e},
//{0x33,0x25}, // // AEC_EXP_MIN
//{0x34,0x1e},
};
至于为什么1310
就是10fps,暂时我也不知道,但是基于此可以调整为20fps或者5fps
目前实测如果这里填的是512,fps大概是29-30
这里就具体计算和原因没有任何说明,只能用现有代码反推了
输出格式
输出格式主要是0x44控制,一般用的多的就是RGB565和YUV422,YUV其实就是Y Cb Y Cr
YUV444,每个分量都一样,所以没啥可说的
YUV422,实际数据返回是YuYv,两个Y分别代表了2个像素,但是他们共用了一组u和v,这种方式减少了数据量,但是会有一点点失真
YUV420,实际数据返回是YYYY...uvuvuvuv,16个Y分别代表了4个像素,但是他们共用了一组u和v,这种方式减少了数据量,失真比较厉害
还有一些其他变体
UYVY 这种等于YUV422的变体形式
VYUY 这种等于YUV422的变体形式
YVYU 这种等于YUV422的变体形式
同时还会选择average neighbor chroma
,会取平均色度
下面代码则是使用YUYV进行输出,并且取平均色度
{0x44 , 0x22}, // output format YUYV
输出分辨率
分辨率控制,主要是通过三个东西控制,window、crop、subsample,都会影响到最终的分辨率
Window
前面是设置行列数据的开始是什么
后面就是摄像头采样的窗口大小,下面代码中设置的大小就是0x1E8,0x288
转换过来就是488x648
,就是GC0328的像素矩阵大小
这个是由于Timing环节规定的,这个宽度一定是目标宽度+8
Crop
0x50控制的是否对窗口进行剪裁,默认0就是不剪裁,1是剪裁
x1和y1是指像素的剪裁起始点,后面的宽高则是剪裁大小,下面代码中的0x78,0xA0
对应的就是120x160
刚好是qqvga的大小
subsample
下采样模式,0x59控制下采样率,1/x,这个值越大,采样越少,代码中就是0x44
,下采样就是1/4
,默认值是1/1
就是全采,对应的就是分辨率是最大值的几分之几。qqvga就是最大的1/4
,如果是qvga则是1/2
0x5a,这个应该是采样方法,只是不知道具体是指什么
static const uint8_t qqvga_regs[][2] = {
{0xfe , 0x00}, // page 0
// window
//windowing mode
{0x09 , 0x00}, // Row start high
{0x0a , 0x00}, // Row start low
{0x0b , 0x00}, // Col start high
{0x0c , 0x00}, // Col start low
{0x0d , 0x01}, // Window height high
{0x0e , 0xe8}, // Window height low
{0x0f , 0x02}, // Window width high
{0x10 , 0x88}, // Window width low
//crop mode
{0x50 , 0x01}, // crop window mode enable
{0x51 , 0x00}, // Crop _win_y1[9:8]
{0x52 , 0x00}, // Crop _win_y1[7:0]
{0x53 , 0x00}, // Crop _win_x1[10:8]
{0x54 , 0x00}, // Crop _win_x1[7:0]
{0x55 , 0x00}, // Crop _win_height[8]
{0x56 , 0x78}, // Crop _win_height[7:0]
{0x57 , 0x00}, // Crop _win_width[9:8]
{0x58 , 0xA0}, // Crop _win_width[7:0]
//subsample 1/4
{0x59 , 0x44}, // subsample
{0x5a , 0x03}, // Sub mode
{0x5b , 0x00}, // Sub_row_N1
{0x5c , 0x00}, // Sub_row_N2
{0x5d , 0x00}, // Sub_row_N3
{0x5e , 0x00}, // Sub_row_N4
{0x5f , 0x00}, // Sub_col_N1
{0x60 , 0x00}, // Sub_col_N2
{0x61 , 0x00}, // Sub_col_N3
{0x62 , 0x00}, // Sub_col_N4
{0x00 , 0x00}
};
Summary
移植驱动主要就注意这几点,剩下大量的寄存器配置都是未知的,只能照搬
Quote
https://club.rt-thread.org/ask/question/7e46e3d50a1b6ab5.html
https://github.com/RT-Thread-Studio/sdk-bsp-stm32h750-realthread-artpi/blob/master/libraries/drivers/include/drv_gc0328c.h
https://github.com/fukuen/Maixduino_GC0328/tree/master
https://github.com/Hengbote/RT-Thread_GC0308
https://blog.csdn.net/rjszcb/article/details/118728264