調(diào)試相機(jī)問(wèn)題總結(jié)
姓名:張猛
引用自:http://blog.csdn.net/tang_jin_chan/article/details/22584387
【嵌牛導(dǎo)讀】:上一周終于解決了hi3518e驅(qū)動(dòng)ov9712并能實(shí)時(shí)的傳輸視頻碳褒,經(jīng)歷了一周多的調(diào)試看疗,總結(jié)一下這個(gè)心酸的過(guò)程睦授。主要是參考了網(wǎng)上的一個(gè)博客去枷,在這里分享給大家竖螃。
【嵌牛鼻子】:硬件、測(cè)試、相機(jī)啥繁、行同步菜职、場(chǎng)同步
【嵌牛提問(wèn)】:拿到一個(gè)陌生的相機(jī)應(yīng)該怎么去認(rèn)識(shí)它适室,并能控制調(diào)試控制它罪帖。
【嵌牛正文】:
1-1.DVP接口:
官方提供的硬件參考原理圖是10根數(shù)據(jù)線的DVP,而這邊的硬件是8根數(shù)據(jù)線的DVP.并且在官方提供的datasheet并沒(méi)有找到DVP配置的寄存器.OV好多東西進(jìn)行了保留,有些寄存器數(shù)據(jù)手冊(cè)寫著是保留的,但是從其提供過(guò)來(lái)的sample〔こ荨code卻是有所配置的.后來(lái)驗(yàn)證了其提供的sample〖部谩code是支持8bit的DVP;
1-2.SCCB通訊失敗:
SCCB兼容IIC協(xié)議,因此這邊直接通過(guò)IIC總線操作.之所以出現(xiàn)SCCB通訊失敗的原因,我這邊主要是因?yàn)镺V9712的SCCB操作之前需要有MCLK,而MCLK是由CIM(CAMERA控制器)提供.這邊的CIM輸出的MCLK時(shí)鐘的使能是受控的,在open的時(shí)候使能MCLK輸出.通過(guò)SCCB操作OV9712之前使能MCLK輸出即可.基本上,要進(jìn)行CMOS操作之前都需要進(jìn)行MCLK輸出,如格科威GC0308;
1-3.是否正確出圖難以判斷:
這邊要求的OV9712輸出為WXGA(1280x800),而且硬件是新布的,沒(méi)有鏡頭調(diào)焦距,并且手頭只有2.8寸屏(分辨率為320x240),直接鋪屏雖然手在CMOS上晃lcd有所反應(yīng),但是不能作為正確出圖的依據(jù),而且DVP接口屏蔽掉低兩位,圖像的完整性更無(wú)從談起.后面通過(guò)將OV9712出來(lái)的Bayer格式通過(guò)軟件編程分別轉(zhuǎn)換成8位位圖殉了、RGB565恩溅、RGB888保存圖片并通過(guò)兩次的跳行跳列把Bayer轉(zhuǎn)換為RGB565數(shù)據(jù)處理顯示在320x240LCD上才得以驗(yàn)證圖像的完整性.相關(guān)代碼參考網(wǎng)上,但是都或多或少有問(wèn)題并存在兼容性可移植性問(wèn)題,這邊已經(jīng)完善修復(fù),后續(xù)提供修正后的相關(guān)源代碼;
1-4.HERF模式:
一般比較復(fù)雜的設(shè)備都是通過(guò)兩大部件和主控完成通訊的.一個(gè)部件是操作設(shè)備內(nèi)部的功能單元,如配置內(nèi)部寄存器,這些功能單元都是通過(guò)一定的協(xié)議完成的.如OV9712通過(guò)SCCB配置其圖像效果,聲卡UDA1341通過(guò)L3協(xié)議調(diào)節(jié)音量;另一部件則是有效數(shù)據(jù)的交互,如CMOS通過(guò)VSYNC窒典、HSYNC、PCLK稽莉、DATA PORT來(lái)配合完成圖像數(shù)據(jù),聲卡UDA1341則通過(guò)IIS總線完成音頻數(shù)據(jù)的傳輸.OV9712默認(rèn)就是采用HERF模式(見(jiàn)datasheet),在一幀圖像傳輸過(guò)程中HERF腳為低,而不像HSYNC(行同步信號(hào))在一幀圖像傳輸過(guò)程中有電平變化(這當(dāng)然了,一幀圖像是有多個(gè)行數(shù)據(jù)組成的).在HERF模式下,主控端需要配置HSYNC腳為下降沿有效;
1-5.別扭的datasheet:
格科威的datasheet比較簡(jiǎn)單明了,比如要配置圖像的寬度高度DVP位數(shù)都有明確的寄存器.而OV9712,是直接"位"操作.比如配置WXGA(1280x800)的寄存器,根據(jù)datasheet說(shuō)明如下:0x58是Vertical Size MSBs的高8位,這里寫0xc8,還有低兩位在0x57寄存bit[1:0](值為0),一共10位,拼成10bit就是1100100000b,轉(zhuǎn)換成10進(jìn)制就是800;0x59Output Horizontal Size MSBs,這里寫0xA0,還有低三位在0x57寄存器bit[4:2](值為0),拼成11位就是10100000000b,轉(zhuǎn)換成10進(jìn)制就是1280.提外話,更為復(fù)雜的是美光的MI367,提供了兩種地址訪問(wèn).
2-1.圖像輸出格式:
CMOS都有圖像輸出格式的,如BAYER(BGGR),YUV422(平鋪)等.這將可能涉及到主控平臺(tái)CIM端的接收數(shù)據(jù)的順序還有上層針對(duì)CMOS圖像格式處理的編程.如某CMOS輸出的圖像格式是YUV422打包格式,我們可以通過(guò)設(shè)置CIM端FIFO的對(duì)數(shù)據(jù)的接收順序控制,使得FIFO端的YUV422打包格式到了DMA層變成了YUV422平鋪格式,這一步是硬件完成的,這時(shí)候再到達(dá)用戶空間的圖像數(shù)據(jù)必然是YUV422平鋪格式了.針對(duì)此圖像格式需要通過(guò)編程實(shí)現(xiàn)轉(zhuǎn)換成RGB565或RGB888.因此,用戶空間程序處理明確你要處理的圖像數(shù)據(jù)是什么格式,否則就是亂七八糟的圖像顯示(這一點(diǎn)可以自行補(bǔ)充一下圖像相關(guān)的知識(shí))瀑志;
2-2.極性匹配:
CMOS和主控端的VSYNC、HSYNC和PCLK的極性要一致,比如VSYNC是上升沿有效還是下降沿有效.參考主控平臺(tái)和CMOS的數(shù)據(jù)手冊(cè)可以實(shí)現(xiàn)配置兩者極性一致.否則有可能出現(xiàn)圖像丟數(shù)據(jù)或色素偏差甚至獲取不了圖像(DMA計(jì)數(shù)達(dá)不到預(yù)期數(shù)量);
2-3.圖像數(shù)據(jù)接收順序:
一般而言,如果CPU有支持?jǐn)?shù)據(jù)打包方式,即把sensor端接收過(guò)來(lái)的4個(gè)8字節(jié)拼成32位的一個(gè)字的排序,需要選擇或者嘗試多種拼接方式.
新拿到的硬件,是好是壞,或者有沒(méi)有一些大意或細(xì)節(jié)的錯(cuò)誤,當(dāng)然需要驅(qū)動(dòng)程序并結(jié)合一些電氣工具如(示波器)去檢測(cè).
1.SCCB:
當(dāng)然這是最首檢測(cè)也是必須檢測(cè)的.這里我是用iic-tools工具(LINUX平臺(tái)支持用戶空間驅(qū)動(dòng)的項(xiàng)目,需要內(nèi)核編譯相關(guān)的支持).源碼可以網(wǎng)上搜索移植.后續(xù)會(huì)提供我這邊提供整理簡(jiǎn)化的IIC-TOOLS源碼.iic-tools是LINUX平臺(tái)調(diào)試IIC設(shè)備的利器.一共有i2cdetect,i2cset,i2cget,i2cdump四個(gè)工具,可以遍歷iic總線上的設(shè)備.其具體用法可網(wǎng)上搜索.OV9712標(biāo)識(shí)了其SCCB設(shè)備地址為0x60,如果i2cdetect出來(lái)的結(jié)果和其設(shè)備地址有出入,就需要檢查一下硬件了.當(dāng)然,前期是可以用iic-tools工具大體檢測(cè),如果是有特殊接口API要求,則就需要具體的API編程.例如下面是我獲取OV9712的PID的函數(shù):
unsigned short ov9712GetId(int iic_fd)
{unsigned short pid = 0;
unsigned char tmp = 0;
iic_set_addr(iic_fd,OV9712ADDR);
tmp =iic_read(iic_fd,PIDHADDR);
pid =tmp;
pid = pid<< 8;
tmp =iic_read(iic_fd,PIDLADDR);
pid = pid |tmp;
if(0x9711== pid)
printf("Found Sensor OV9712.So Lucky!\n");
else
printf("Oops:Miss OV9712.\n");
returnpid;
}
0x9711是OV9712的產(chǎn)品ID,可以查看其數(shù)據(jù)手冊(cè).
這里曾遇到個(gè)問(wèn)題,就是SCCB通訊失敗,原因是OV9712必須有MCLK才可以SCCB通訊的.
2.初始化OV9712:
確認(rèn)SCCB通訊是沒(méi)問(wèn)題的,就直接往OV9712堆sample∥鄹选code吧.把原廠提供的初始化代碼通過(guò)SCCB協(xié)議,往里面塞.塞完寄存器后大體量一下MCLK劈猪、VSYNC、HSYNC良拼、PCLK及DATA引腳,都有信號(hào)輸出并且是正常的.截取了一部分原始數(shù)據(jù)鋪在320x240的屏上顯示只有一些彩條亂七八糟的.出現(xiàn)這種情況當(dāng)時(shí)就往兩個(gè)方向想了:一個(gè)是極性問(wèn)題;第二個(gè)對(duì)出來(lái)的圖像數(shù)據(jù)直接鋪屏(RGB565)的問(wèn)題.
2-1.極性匹配:
廠家提供的代碼里面間沒(méi)有對(duì)VSYNC战得、HSYNC和PCLK的極性進(jìn)行重新配置,就是采用默認(rèn)的.于是查找OV9712數(shù)據(jù)手冊(cè)找到VSYNC、HSYNC庸推、PCLK的極性控制寄存器.如下:
可見(jiàn),OV9712的VSYNC常侦、HSYNC默認(rèn)的極性是Positive,即上升沿有效.
注意,這里不要這里的寄存器坑了,HSYNC默認(rèn)確實(shí)是positive,但是前提是你選定的是HSYNC模式.OV9712支持三種模式:HREF、HSYNC贬媒、CCIR565.默認(rèn)的就是HERF模式而不是HSYNC模式.HERF和HSYNC是同一個(gè)pin腳,不同的是,HERF模式下,HERF引腳為低的時(shí)候VSYNC引腳輸出才有效.見(jiàn)OV9712的數(shù)據(jù)手冊(cè)的時(shí)序圖,如下:
因此,在HREF模式下,是下降沿有效的.在這種模式下主控端需要配置HSYNC引腳為下降沿有效.我把JZ4776主控端配置成上升沿有效的時(shí)候,是獲取不了圖片的.既然廢棄了HSYNC行同步,那么會(huì)不會(huì)出現(xiàn)行同步不一致而導(dǎo)致主控拒絕接收數(shù)據(jù)呢?個(gè)人認(rèn)為,有VSYNC足夠了,它引發(fā)了中斷,就意味著一幀圖像傳輸完畢,主控端就可以去處理數(shù)據(jù)了,HSYNC是可以被忽略的.如果遇到一些平臺(tái)比較嚴(yán)格的話,還需要處理HSYNC同步的話,就具體處理了.
PCLK的極性如下:
因此,我們可以確定HREF模式下PIN腳VSYNC聋亡、HREF(HSYNC)、PCLK的極性分別為:
VSYNC:上升沿;
HERF(HSYNC):下降沿;
PCLK:上升沿.
因此,再根據(jù)設(shè)備去配置主控端的相應(yīng)極性:
默認(rèn)的VSYN和PCLK極性是一致的,主要是把HSP配置為1(即下降沿有效).
2-2.接收?qǐng)D像的順序:
一般CPU的CIM控制器都有從SENSOR端過(guò)來(lái)的接收到的數(shù)據(jù)進(jìn)行重組排序處理的.一般而言,SENSOR端輸出的是YUV或RAWR(shí)GB,一般而言,數(shù)據(jù)手冊(cè)都可以找到明確其明確格式,比如OV9712的圖像輸出格式就是BAYER(RAW〖食恕DATA)中的一種.從其數(shù)據(jù)手冊(cè)可以看到如下字樣:
The color filters are arranged in a Bayer pattern. Theprimary color BG/GR array is arranged in line-alternating fashion.
「小技巧:」無(wú)論是YUV還是RAW DATA坡倔,如果是接收順序反了的話,一般都有輪廓.可以適當(dāng)嘗試一下別的字節(jié)重組順序.JZ4775對(duì)從SENSOR接收過(guò)來(lái)的4個(gè)字節(jié)拼成32位的字,有下面8種方式:
這里選擇第五種方式,即3'b100.高低位調(diào)轉(zhuǎn)的方式.核對(duì)了上述兩點(diǎn)之外,出來(lái)的圖像依然看不出圖像的完整性.配置依然可能存在問(wèn)題,鏡頭也沒(méi)調(diào)焦距,上層轉(zhuǎn)換函數(shù)也有可能存在問(wèn)題.這三個(gè)方面的因素都有可能導(dǎo)致同樣的現(xiàn)象.于是想了下有沒(méi)有更好更直接的快捷方式.通過(guò)查閱OV9712的數(shù)據(jù)手冊(cè),發(fā)現(xiàn)其提供了個(gè)test pattern模式.進(jìn)入這種模式下,顯示8段彩條.如下:
當(dāng)然,還要設(shè)置寄存器0xca進(jìn)入TestPattern模式.代碼如下:
void ov9712TestPattern(int iic_fd)
{
iic_write(iic_fd,0xca,0x24);
iic_write(iic_fd,0x12,0x02);
iic_write(iic_fd,0x97,0x88);
}
然后把SENSOR端過(guò)來(lái)的數(shù)據(jù)轉(zhuǎn)RGB565保存起來(lái),發(fā)現(xiàn)圖片有斷層情況.后來(lái)檢查發(fā)現(xiàn)是轉(zhuǎn)換函數(shù)的bmp頭構(gòu)造得有問(wèn)題.修復(fù)后效果和test pattern一致.為了調(diào)試方便,決定把轉(zhuǎn)換出來(lái)的RGB565(1280∽锼X⊥恫酢800)顯示在2.8寸屏(320 x≌骺啊240)上.通過(guò)跳行跳列實(shí)現(xiàn).代碼如下:
Function:
Skip OneRow And One Column.
Date:
2014-3-29
Author:
SE7EN
void skipPiexl1(const u16 *inBuf,u16 *outBuf,const u32width,const u32 height,u32 div)
{
assert((inBuf && outBuf && (0 == (width % 4) &&(0 == (height % 4)) && (0 == (div % 4)))));
const u16*pInW = inBuf;
u16 *pOut =outBuf;
u32 i = 0,j= 0,k = 0,sum = 0,aver = 0;
for(i = 0;i < height; i+=2)
{
for(j = 0; j < width; j+=2)
{
*pOut = *pInW;
pOut++;
pInW +=2;
}
pInW = pInW + width;
}
}
因?yàn)槲业氖秦Q屏,因此還需要把兩次縮放的像素buf旋轉(zhuǎn)90度,代碼如下:
Function:
OperationFor RGB.
Date:
2014-3-29
Author:
SE7EN
*/
#include "skippiexl.h"
void rgb565_rotate90(const u16 *input, u16 *output,u32width_in,u32 height_in)
{const u16*pIn=input;
u16*pOut=output;
inti,j;
for(i=0;i
{
for(j=0; j
{*pOut = *pIn++;
pOut = output+height_in*j + i;
}
}
}
3.小結(jié):
SENSOR其實(shí)是挺復(fù)雜的一個(gè)東西,很多過(guò)中涉及的概念都只是有個(gè)籠統(tǒng)的概念.在此作錄備忘,后續(xù)還需要調(diào)試圖像質(zhì)量,這個(gè)只能靠技術(shù)支持了.