完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>
標簽 > OV7620
ov7620是一款CMOS攝像頭器件,是彩色CMOS型圖像采集集成芯片,提供高性能的單一小體積封裝,該器件分辨率可以達到640X480,傳輸速率可以達到30幀。
ov7620是一款CMOS攝像頭器件,是彩色CMOS型圖像采集集成芯片,提供高性能的單一小體積封裝,該器件分辨率可以達到640X480,傳輸速率可以達到30幀。
OV7620
HQ7620攝像頭模塊是基于Omnivision公司的CMOS圖像傳感器--- OV7620的方案設計;1/3英寸數字式CMOS圖像傳感器OV7620,總有效像素單元為664(水平方向)×492(垂直方向)像素;內置10位雙通道A/D轉換器,輸出8位圖像數據;具有自動增益和自動白平衡控制,能進行亮度、對比度、飽和度、γ校正等多種調節功能;其視頻時序產生電路可產生行同步、場同步、混合視頻同步等多種同步信號和像素時鐘等多種時序信號;5V電源供電,工作時功耗《120mW,待機時功耗《10μW。可應用于數碼相機、電腦攝像頭、可視電話、第三代網絡攝像機、手機、智能型安全系統、汽車倒車雷達、玩具,以及工業、醫療等多種用途。OV7620是1/3”CMOS彩色/黑白圖像傳感器。它支持連續和隔行兩種掃描方式,VGA與QVGA兩種圖像格式;最高像素為664×492,幀速率為30fps;數據格式包括YUV、YCrCb、RGB三種,能夠滿足一般圖像采集系統的要求。
ov7620是一款CMOS攝像頭器件,是彩色CMOS型圖像采集集成芯片,提供高性能的單一小體積封裝,該器件分辨率可以達到640X480,傳輸速率可以達到30幀。
OV7620
HQ7620攝像頭模塊是基于Omnivision公司的CMOS圖像傳感器--- OV7620的方案設計;1/3英寸數字式CMOS圖像傳感器OV7620,總有效像素單元為664(水平方向)×492(垂直方向)像素;內置10位雙通道A/D轉換器,輸出8位圖像數據;具有自動增益和自動白平衡控制,能進行亮度、對比度、飽和度、γ校正等多種調節功能;其視頻時序產生電路可產生行同步、場同步、混合視頻同步等多種同步信號和像素時鐘等多種時序信號;5V電源供電,工作時功耗《120mW,待機時功耗《10μW。可應用于數碼相機、電腦攝像頭、可視電話、第三代網絡攝像機、手機、智能型安全系統、汽車倒車雷達、玩具,以及工業、醫療等多種用途。
OV7620是1/3”CMOS彩色/黑白圖像傳感器。它支持連續和隔行兩種掃描方式,VGA與QVGA兩種圖像格式;最高像素為664×492,幀速率為30fps;數據格式包括YUV、YCrCb、RGB三種,能夠滿足一般圖像采集系統的要求。
基本參數:
大 小:33x27x24(mm)電 源:DC+5V ±5%掃描方式:逐行/隔行掃描最低照度:2.5 lux at f1.4 (3000k)信 噪 比:》 48 dB最大像素:(H)664 x (V)492; 缺省有效像素:(H)640 x (V)480數據輸出格式:YCrCb 16bit/8bit selectable60Hz 16 Bit YCrCb 4:2:2 - 640x48060Hz 8 Bit YCrCb 4:2:2 - 640x480RGB Raw Data Digital Output 16Bit/8Bit selectableCCIR601, CCIR656, ZV 端口:支持8/16 位視頻數據SCCB接口:最大速率支持400 kBit/sYCrCB或YUV輸出格式:支持TV或監視器顯示
OV7620掃描方式
OV7620是CMOS彩色/黑白圖像傳感器。它支持連續和隔行兩種掃描方式,VGA與QVGA兩種圖像格式;最高像素為664492,幀速率為30fp8;數據格式包括YUV、YCrCb、RGB三種,能夠滿足一般圖像采集系統的要求。OV7620內部可編程功能寄存器的設置有上電模式和SCCB編程模式。OV7620的控制采用SCCB(SeriaI Camera ControlBus)協議。SCCB是簡化的I2C協議,SIO-l是串行時鐘輸入線,SIO-O是串行雙向數據線,分別相當于I2C協議的SCL和SDA。SCCB的總線時序與I2C基本相同,它的響應信號ACK被稱為一個傳輸單元的第9位,分為Don’t care和NA。Don’t care位由從機產生;NA位由主機產生,由于SCCB不支持多字節的讀寫,NA位必須為高電平。另外,SCCB沒有重復起始的概念,因此在SCCB的讀周期中,當主機發送完片內寄存器地址后,必須發送總線停止條件。不然在發送讀命令時,從機將不能產生Don’t care響應信號。由于I2C和SCCB的一些細微差別,所以采用GPIO模擬SCCB總線的方式。SCL所連接的引腳始終設為輸出方式,而SDA所連接的引腳在數據傳輸過程中,通過設置IODIR的值,動態改變引腳的輸入/輸出方式。SCCB的寫周期直接使用I2C總線協議的寫周期時序;而SC-CB的讀周期,則增加一個總線停止條件。OV7620功能寄存器的地址為0x00~0x7C(其中,不少是保留寄存器)。通過設置相應的寄存器,可以使OV7620工作于不同的模式。例如,設置OV7620為連續掃描、RGB原始數據16位輸出方式,需要進行如下設置:I2CSendByte()為寫寄存器函數,它的第1個參數OV7620為宏定義的芯片地址0x42,第2個參數為片內寄存器地址,第3個參數為相應的寄存器設定值。OV7620有4個同步信號:VSYNC(垂直同步信號)、FODD(奇數場同步信號)、HSYNC(水平同步信號)和PCLK(像素同步信號)。當采用連續掃描方式時,只使用VSYNC和HSYNC、PCLK三個同步信號,還引入了HREF水平參考信號。LPC2210的3個外部中斷引腳分別作為3個同步信號的輸入,相應的中斷服務程序分別為Vsync_IRQ()、Hsync_IRQ()和Pclk_IRQ()。在內存中定義一個二維數組存儲圖像數據,一維用變量y表示,用于水平同步信號計數;二維用變量x表示,用于像素同步信號計數。圖像采集的基本流程當用SCCB初始化好OV7620后,使能VSYNC對應的中斷,在Vsync_IRQ()中斷服務程序中判斷是否已取得一幀數據。若是,則在主程序的循環體中進行數據處理;若不是,則使能HSYNC對應的中斷,并將y置為O。在Hsync_IRQ()中斷服務程序中,判斷HREF的有效電平,若有效,則y加1,x置為O,并使能PCLK對應的中斷。在Pclk_IRQ()中斷服務程序中,判斷HREF的有效電平,若有效,則z增加,同時采集一個像素點的圖像數據。在OV7620的3個同步信號中,PCLK的周期最短。當OV7620使用27 MHz的系統時鐘時,默認的PCLK的周期為74 ns。而LPC2210的中斷響應時間遠遠大于這個值。LPC2210的最大中斷延遲時問為27個處理器指令周期,最小延遲時問為4個指令周期,再加上中斷服務時間、現場恢復時間等,完成一次中斷響應的時問要大于7~30個指令周期。當LPC2210使用最高系統頻率60 MHz時,它的中斷響應時間遠大于O.2~0,6 μs,所以只能將OV7620的PCLK降頻。通過設置時鐘頻率控制寄存器,可將PCLK的周期設為4μs左右。
OV7620作為主設備的工作方式
當OV7620工作于主設備方式時,它的YUV通道將連續不斷地向總線上輸出數據。如果將OV7620的YUV通道直接接在LPC2210的DO~D15數據總線上,則會干擾數據總線,使LPC2210不能正常運行;如果使用74HC244等隔離,分時使用數據總線的方法,則會大大降低系統的運行速度,使得LPC2210不能及時取走總線上的數據,造成圖像數據不完整。由于LPC2210的數據總線寬度為32位,而Flash和SRAM僅占用了低16位數據線D0~D15,因此可以采用圖l中的方法,將空閑的高16位數據線D16~D31設為GPIO,用于采集OV7620輸出的16位圖像數據。OV7620采用16位輸出方式時,Y通道和UV通道的數據輸出格式如表l所列。從表l中可以看出,每一行Y通道和UV通道交替輸出上一行的重復數據和本行的新數據。而在一行之內,B數據只在奇數列出現,R數據只在偶數列出現。
OV7620應用舉例
下面以一個55的像素點陣為例,詳細介紹圖像數據的恢復。首先定義一個515的字節型數組,在Pclk_IRQ()中斷服務程序中讀取55個像素點的圖像數據;然后對圖像數據進行插值,奇數點則在數組的連續3個字節中存入B、G、0,偶數點則存入O、G、R;最后對當前行的每一個字節與下一行對應列的每一個字節求平均值,即可算出當前行的RGB值。而在每一行內,奇數點的R數據和偶數點的B數據可通過分別對其兩側的2個點的R和B數據求平均值得到。這樣,一幅圖像就恢復好了。可以直接存成二進制文件(本系統采用串口輸出到PC進行顯示),或者增加BMP位圖文件頭信息,存成biBitCouNt=24的DIB位圖文件;也可用LPC2210對此圖像數據進行進一步的處理,如指紋識別等。如果采用帶有DMA控制器,并且具有更高處理速度的ARM芯片,可大大提高整個圖像采集系統的速度。例如,采用具有ARM9內核的S3C2410,其最高系統頻率達203 MHz,完成一次DMA傳送的時間約為30 ns。小于默認的PCLK的周期74 ns,可以實現30 fps的圖像采集速度。 與搭配OV511+或CPLD/FPGA的圖像采集系統相比,此圖像采集系統極大地簡化了系統結構,降低了系統設計成本,縮短了開發周期;圖像數據的采集與處理均由ARM芯片完成,因而降低了數據中轉過程中傳輸錯誤的幾率,提高了系統的可靠性。
OV7620的使用
有人會奇怪為什么使用OV系列的攝像頭每次都要進行SCCB的操作呢?難道它自己不會保存上次的操作結果嗎?
原因是:OV系列的攝像頭的寄存器是EEPROM,不穩定,數據很容易丟失,因此程序每次初始化時我們都要重新寫入寄存器設置。
PS:常見需要修改的寄存器有,PCLK速率,幀率、圖像亮度、對比度、色飽和度、鏡像等功能。
智能車攝像頭組的初期學習中,雖然有不少攝像頭優于OV7620,但是相信大部分的車友第一個接觸的都是OV7620。下面從其特性和性能等角度,剖析攝像頭的特點。
攝像頭的輸出格式有RGB565,YUY422等格式,我所接觸的第一個攝像頭OV7620的輸出格式是YUV422。下面給大家介紹一下YUV422。
什么是YUV422?
人的眼睛對低頻信號比對高頻信號具有更高的敏感度,事實上,人的眼睛對明視度的改變比對色彩的改變要敏感的多。因此,人們將RGB三色信號改為YUV來表示,其中Y為灰度,UV為色差。如果是表示一副彩色圖像,同樣的道理,YUV444是無損的存儲方式,但是需要3個字節,存儲空間開銷很大。由于Y分量比UV分量重要的多,因此人們用YUV422來表示。這樣一來圖像被壓縮了很多,一個字節就可以表示其彩色的信息。
對于OV7620,它有2 組并行的數據口Y[7..0]和UV[7..0],其中對于數據口Y[7..0],輸出的是灰度值Y,對于UV[7..0]輸出的色度信號UV。下圖給出了k 個像素(K 個字節)輸出的格式。
OV762的控制采用SCCB(Serial Camera ControlBus)協議。SCCB的簡化的I2C協議,SIO-I是串行時鐘輸入線,SIO-O是串行雙向數據線,分別相當于I2C協議的SCL和SDA。SCCB的總線時序與I2C基本相同,他的響應信號ACK被陳偉一個傳輸單元的第9位,分別Do not care和NA.Do not care位由從機產生;NA位由主機產生,由于SCCB不支持多字節的讀寫,NA位必須為高電平。另外SCCB沒有重復起始的概念,因此在SCCB的讀周期中,當主機發送讀命令時,從機將不能產生Do not care響應信號。
由于I2C和SCCB的一些細微差別,所以采用GPIO模擬SCCB總線的方式,SCL所連接的引腳始終設為輸出方式,而SDA所連接的引腳在數據傳輸過程中,通過設置IODIR的值,動態改變引腳的輸入/輸出方式。SCCB的寫周期直接使用I2C總線協議的寫周期時序;而SC-CB的讀周期,則增加一個總線停止條件。
OV7620的幾個優點:
第一,OV7620的電平兼容3.3V和5V。目前智能車用戶用到的處理器基本上可以分為XS128和K60和KL25三種控制器,而這三種控制器的工作電平分別是5V和3.3V和3.3V。OV7620可以完全適應這兩種電平,XS128和K60和KL25可以隨性切換,無需做電平匹配。(要注意的是當OV7620接5v和3.3v的時候,輸出的效果是不同的,建議在5v的電壓下使用,因為在3.3v的電壓下使用比較難調,輸出的16進制數據清一色偏小。)
同樣的情況下:
3.3V下: 5v下:
第二,OV7620的幀率是60幀/s。新手學習攝像頭的時候,誤以為攝像頭幀率越快越好,其實不然。就拿OV7620來說,其PCLK(像素中斷)的周期是73ns,該頻率下的PCLK很容易被K60的IO捕捉,如果幀率更快的攝像頭,其PCLK的周期就會更小,該頻率下PCLK不易被K60的IO捕捉到。(但是鷹眼攝像頭不然,火哥的鷹眼攝像頭理論上宣傳的是150幀每秒,但是他并不是通過PCLK的周期減小從而獲得效果的,鷹眼攝像頭的高明之處在于它在硬件二值化之后,每一次PCLK中斷對外輸出了8個像素,而不是1個像素。鷹眼攝像頭已經買來了,以后有機會會試試效果。)
第三:OV7620的分辨率也是非常合適的,在第三篇也提到OV7620是隔行掃描,采集VSYN的話,其輸出分辨率是640*240。如果改為QVGA格式,默認輸出分辨率是320*120,該分辨率下非常適合采集賽道,數據容量有限又不會失真圖像。(OV7620的分辨率可以通過SCCB修改,有興趣修改的可以去查看OV7620的寄存器配置,然后通過SCCB修改。)
只有掌握了OV7620的時序,才能靈活得使用OV7620。下面開始本篇的重點:OV7620時序分析。
對于OV7620,我們只關心場中斷信號VSYN、行中斷信號HREF、像素中斷信號PCLK的波形。用示波器去監控這三個波形,可以看到一下關系。
VSYN 的周期是16.64ms,高電平時間為換場時間,約80us;低電平時間內像素輸出。我們在采集VSYN脈沖時,既可以采集上升沿,也可以采集下降沿,采集下降沿更準確些,這也是一場的開始。從VSYN的周期可以算出,1s/16.64ms=60幀,OV7620的幀率是60幀/s。
HREF的周期63.6us,高電平時間為像素輸出時間,約47us;低電平時間為換行時間,因此采集HREF一定要采集其上升沿,下降沿后的數據是無效的。從HREF的周期可以算出,16.64ms/63.6us≈261,除去期間的間隙時間,可以算出每場圖像有240行。
PCLK的周期是73ns,高電平輸出像素,低電平像素無效。PCLK是一直輸出的,因此一定要在觸發VSYN并且觸發HREF以后,再去捕捉PCLK才能捕捉到像素數據。從PCLK的周期可以算出,47us/73ns≈640,可以算出每行圖像中有640個像素點。
介紹完基本知識之后,下面開始寫程序了(Keil--K60--C語言):
在這我分成兩部分著重介紹7620的時序程序和貼上SCCB的協議程序(其實原理和處理情況和I2C差不多):
First :
首先要對使用到的一些IO口進行初始化處理,四個部分的初始化,
A.像素中斷PCLK
B.行中斷HREF
C.場中斷VSYNC
D.DMA
程序如下:
[objc] view plain copy//初始化OV7620模塊
void OV7620_Init()
{
//像素中斷 PCLK
GPIO_InitStruct1.GPIO_Pin = OV7620_PCLK_PIN;
GPIO_InitStruct1.GPIO_InitState = Bit_SET;
GPIO_InitStruct1.GPIO_IRQMode = GPIO_IT_DMA_RISING;
GPIO_InitStruct1.GPIO_Mode = GPIO_Mode_IPD;
GPIO_InitStruct1.GPIOx = OV7620_PCLK_PORT;
GPIO_Init(&GPIO_InitStruct1);
//行中斷 HREF
GPIO_InitStruct1.GPIO_Pin = OV7620_HREF_PIN;
GPIO_InitStruct1.GPIO_InitState = Bit_SET;
GPIO_InitStruct1.GPIO_IRQMode = GPIO_IT_RISING;
GPIO_InitStruct1.GPIO_Mode = GPIO_Mode_IPD;
GPIO_InitStruct1.GPIOx = OV7620_HREF_PORT;
GPIO_Init(&GPIO_InitStruct1);
// 場中斷 VSYNC
GPIO_InitStruct1.GPIO_Pin = OV7620_VSYNC_PIN;
GPIO_InitStruct1.GPIO_InitState = Bit_SET;
GPIO_InitStruct1.GPIO_IRQMode = GPIO_IT_RISING; //GPIO_IT_RISING
GPIO_InitStruct1.GPIO_Mode = GPIO_Mode_IPD; //GPIO_Mode_IPD
GPIO_InitStruct1.GPIOx = OV7620_VSYNC_PORT;
GPIO_Init(&GPIO_InitStruct1);
//配置DMA
DMA_InitStruct1.Channelx = DMA_CH1; //DMA 1通道
DMA_InitStruct1.PeripheralDMAReq =PORTC_DMAREQ; //C端口(PCLK) 上升呀觸發
DMA_InitStruct1.MinorLoopLength = 170; //傳輸次數 超過攝像頭每行像素數即可
DMA_InitStruct1.TransferBytes = 1; //每次傳輸1個字節
DMA_InitStruct1.DMAAutoClose = ENABLE; //連續采集
DMA_InitStruct1.EnableState = ENABLE; //初始化后立即采集
DMA_InitStruct1.SourceBaseAddr =(uint32_t)&PTD-》PDIR;//攝像頭端口接D0-D7
DMA_InitStruct1.SourceMajorInc = 0; //地址不增加
DMA_InitStruct1.SourceDataSize = DMA_SRC_8BIT; //8BIT數據
DMA_InitStruct1.SourceMinorInc = 0;
DMA_InitStruct1.DestBaseAddr =(uint32_t)DMABuffer; //DMA 內存 //uint8_t DMABuffer[400];
DMA_InitStruct1.DestMajorInc = 0;
DMA_InitStruct1.DestDataSize = DMA_DST_8BIT;
DMA_InitStruct1.DestMinorInc = 1; //每次傳輸 +1個字節
DMA_Init(&DMA_InitStruct1);
}
然后開始編寫場中斷函數,編寫之前我們需要在心里理一下思緒,在場中斷函數里我們要按照順序,做以下幾件事情:
A.確認是否是場中斷,確認之后進入處理。
B.清除標志位Flag。(Flag是用來觀察是否處理完一場圖像的標志)
C.清除中斷標志。
D.計數全部清零。(因為新的一場已經開始)
E.打開行中斷,關閉場中斷。
[objc] view plain copyvoid PORTB_IRQHandler(void)//功 能:PORTB 外部中斷服務 //V
{
u8 i=9;
if((PORTB-》ISFR》》i)==1)
{
Flag = 0;
PORTB-》ISFR|=(1《《9);
Row = 0;
Row_Num = 0;
NVIC_EnableIRQ(PORTA_IRQn);//行
NVIC_DisableIRQ(PORTB_IRQn);//場
}
接著編寫行中斷函數,在行中斷中,我們要做以下幾件事情:
A.確認是否是行中斷。
B.關閉DMA中斷,防止提前進入PCLK的采集。
C.跳過消隱區。(消隱區:消隱區的出現,在電視機原理上,是因為電子束結束一行掃描,從一行尾換到另一行頭,期間的空閑期,這叫做行消隱信號;同理,從一場尾換到另一場尾,期間也會有空閑期,這叫做場消隱信號。)
D.進入行采集處理。
E.配置DMA,并且打開DMA中斷。
F.行計數加1,表示已經采集完了一行。(因為PCLK的中斷周期遠遠小于HREF的中斷周期,所以不需要杞人憂天,擔心中斷搞得混亂。)
G.當采集完了自己的目標行數之后,標志位Flag修改。并關閉行中斷,打開場中斷,等待下一次的場中斷。
[objc] view plain copyvoid PORTA_IRQHandler(void)//功 能:PORTA 外部中斷服務//Herf
{
u8 i=14;
DMA_SetEnableReq(DMA_CH1,DISABLE); //close DMA ISr
if((PORTA-》ISFR》》i)==1);
{
PORTA-》ISFR|=(1《《14);
if(Row_Num++ 》 15) //消隱區啦
{
if(Row_Num%5) //進入行采集
{
//配置DMA
DMA_InitStruct1.Channelx = DMA_CH1; //DMA 1通道
DMA_InitStruct1.PeripheralDMAReq =PORTC_DMAREQ; //C端口(PCLK) 上升呀觸發
DMA_InitStruct1.MinorLoopLength = 170; //傳輸次數 超過攝像頭每行像素數即可
DMA_InitStruct1.TransferBytes = 1; //每次傳輸1個字節
DMA_InitStruct1.DMAAutoClose = ENABLE; //連續采集
DMA_InitStruct1.EnableState = ENABLE; //初始化后立即采集
DMA_InitStruct1.SourceBaseAddr =(uint32_t)&PTD-》PDIR;//攝像頭端口接D0-D7
DMA_InitStruct1.SourceMajorInc = 0; //地址不增加
DMA_InitStruct1.SourceDataSize = DMA_SRC_8BIT; //8BIT數據
DMA_InitStruct1.SourceMinorInc = 0;
DMA_InitStruct1.DestBaseAddr =(uint32_t)Image[Row]; //DMA 內存 //uint8_t DMABuffer[400];
DMA_InitStruct1.DestMajorInc = 0;
DMA_InitStruct1.DestDataSize = DMA_DST_8BIT;
DMA_InitStruct1.DestMinorInc = 1; //每次傳輸 +1個字節
DMA_Init(&DMA_InitStruct1);
///////////////////////////////////////////////////////
Row ++;
if(Row==MAX_ROW)
{
Flag = 1;
NVIC_DisableIRQ(PORTA_IRQn);//行
NVIC_EnableIRQ(PORTB_IRQn);//場
}
}
}
}
}
最后給大家看一下,DMA的初始化函數,這個函數是超核的庫里面的,不是我寫的,但是上面的解釋很詳細了,相信都能看懂。
[objc] view plain copyvoid DMA_Init(DMA_InitTypeDef *DMA_InitStruct)
{
//參數檢查
assert_param(IS_DMA_REQ(DMA_InitStruct-》PeripheralDMAReq));
assert_param(IS_DMA_ATTR_SSIZE(DMA_InitStruct-》SourceDataSize));
assert_param(IS_DMA_ATTR_DSIZE(DMA_InitStruct-》DestDataSize));
assert_param(IS_DMA_CH(DMA_InitStruct-》Channelx));
assert_param(IS_DMA_MINOR_LOOP(DMA_InitStruct-》MinorLoopLength));
//打開DMA0和DMAMUX時鐘源
SIM-》SCGC6 |= SIM_SCGC6_DMAMUX_MASK;
SIM-》SCGC7 |= SIM_SCGC7_DMA_MASK;
//配置DMA觸發源
DMAMUX-》CHCFG[DMA_InitStruct-》Channelx] = DMAMUX_CHCFG_SOURCE(DMA_InitStruct-》PeripheralDMAReq);
//設置源地址信息
DMA0-》TCD[DMA_InitStruct-》Channelx].SADDR = DMA_InitStruct-》SourceBaseAddr;
//執行完源地址操作后,是否在源地址基礎上累加
DMA0-》TCD[DMA_InitStruct-》Channelx].SOFF = DMA_SOFF_SOFF(DMA_InitStruct-》SourceMinorInc);
//設置源地址傳輸寬度
DMA0-》TCD[DMA_InitStruct-》Channelx].ATTR = 0;
DMA0-》TCD[DMA_InitStruct-》Channelx].ATTR |= DMA_ATTR_SSIZE(DMA_InitStruct-》SourceDataSize);
//主循環進行完后 是否更改源地址
DMA0-》TCD[DMA_InitStruct-》Channelx].SLAST = DMA_InitStruct-》SourceMajorInc;
//設置目的地址信息
DMA0-》TCD[DMA_InitStruct-》Channelx].DADDR = DMA_InitStruct-》DestBaseAddr;
//執行完源地址操作后,是否在源地址基礎上累加
DMA0-》TCD[DMA_InitStruct-》Channelx].DOFF = DMA_DOFF_DOFF(DMA_InitStruct-》DestMinorInc);
//設置目的地址傳輸寬度
DMA0-》TCD[DMA_InitStruct-》Channelx].ATTR |= DMA_ATTR_DSIZE(DMA_InitStruct-》DestDataSize);
//主循環進行完后 是否更改源地址
DMA0-》TCD[DMA_InitStruct-》Channelx].DLAST_SGA = DMA_InitStruct-》DestMajorInc;
//設置計數器長度 循環次數
//設置數據長度 長度每次遞減 也被稱作當前主循環計數 current major loop count
DMA0-》TCD[DMA_InitStruct-》Channelx].CITER_ELINKNO = DMA_CITER_ELINKNO_CITER(DMA_InitStruct-》MinorLoopLength );
//起始循環計數器 當主循環計數器為0 時候 將裝載起始循環計數器的值
DMA0-》TCD[DMA_InitStruct-》Channelx].BITER_ELINKNO = DMA_BITER_ELINKNO_BITER(DMA_InitStruct-》MinorLoopLength);
//設置每一次傳輸字節的個數 個數到達上限時 DMA便將數據存入RAM
DMA0-》TCD[DMA_InitStruct-》Channelx].NBYTES_MLNO = DMA_NBYTES_MLNO_NBYTES(DMA_InitStruct-》TransferBytes);
//設置DMA TCD控制寄存器
DMA0-》TCD[DMA_InitStruct-》Channelx].CSR = 0;
if(DMA_InitStruct-》DMAAutoClose == ENABLE)
{
DMA0-》TCD[DMA_InitStruct-》Channelx].CSR |=DMA_CSR_DREQ_MASK;
}
else
{
DMA0-》TCD[DMA_InitStruct-》Channelx].CSR &=(~DMA_CSR_DREQ_MASK);
}
//使能此寄存器DMA開始工作
DMA_SetEnableReq(DMA_InitStruct-》Channelx,DMA_InitStruct-》EnableState);
//DMA 通道使能
DMAMUX-》CHCFG[DMA_InitStruct-》Channelx] |= DMAMUX_CHCFG_ENBL_MASK;
}
Second:
講完OV7620的一些中斷處理函數之后,我們來看看SCCB的庫程序,這個庫可以通用,需要的車友可以直接添加,只需要對照自己使用的庫,在IO口初始化里面做出相應的修改即可。
[objc] view plain copy#ifndef __SCCB_H
#define __SCCB_H
#define SCL_HIGH PEout(1) = 1 //設置為輸出后輸出1
#define SCL_LOW PEout(1) = 0 //設置為輸出后輸出0
#define SCL_OUT PTE-》PDDR|=(1《《1) //設置為輸出
//#define SCL_DDR_IN() PTE-》PDDR&=~(1《《1)//輸入
#define SDA_HIGH PEout(0)= 1 //設置為輸出后輸出1
#define SDA_LOW PEout(0)= 0 //設置為輸出后輸出0
#define SDA_DATA PEin(0)
#define SDA_OUT PTE-》PDDR|=(1《《0) //設置為輸出
#define SDA_IN PTE-》PDDR&=~(1《《0) //設置為輸入
#define u8 unsigned char
#define u16 unsigned short
//#define ADDR_OV7725 0x42
void sccb_init(void); //初始化SCCB端口為GPIO
void sccb_wait(void); //SCCB時序延時
void sccb_start(void); //起始標志
void sccb_stop(void); //停止標志
u8 sccb_sendByte(u8 data);
void sccb_regWrite(u8 device,u8 address,u8 data);
#endif
#include “sys.h”
#include “gpio.h”
#include “sccb.h”
#include “delay.h”
#include “stdio.h”
/*************************************************************************
* 函數名稱:sccb_init
* 功能說明:初始化SCCB 其中SCL接PE1 SDA接PTE0
*************************************************************************/
void sccb_init(void)
{
int i ;
GPIO_InitTypeDef GPIO_InitStruct1;
for(i=0;i《8;i++)
{
GPIO_InitStruct1.GPIO_Pin = i;
GPIO_InitStruct1.GPIO_InitState = Bit_RESET; //change as Bit_Set , it will shut.
GPIO_InitStruct1.GPIO_IRQMode = GPIO_IT_DISABLE;
GPIO_InitStruct1.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStruct1.GPIOx = PTD;
GPIO_Init(&GPIO_InitStruct1);
}
GPIO_InitStruct1.GPIO_Pin = 0;
GPIO_InitStruct1.GPIO_InitState = Bit_RESET;
GPIO_InitStruct1.GPIO_IRQMode = GPIO_IT_DISABLE;
GPIO_InitStruct1.GPIO_Mode = GPIO_Mode_OPP;
GPIO_InitStruct1.GPIOx = PTE;
GPIO_Init(&GPIO_InitStruct1);
GPIO_InitStruct1.GPIO_Pin = 1;
GPIO_InitStruct1.GPIO_InitState = Bit_RESET;
GPIO_InitStruct1.GPIO_IRQMode = GPIO_IT_DISABLE;
GPIO_InitStruct1.GPIO_Mode = GPIO_Mode_OPP;
GPIO_InitStruct1.GPIOx = PTE;
GPIO_Init(&GPIO_InitStruct1);
}
/************************************************************************
* 函數名稱:sccb_wait
* 功能說明:SCCB延時,不應太小
*************************************************************************/
void sccb_wait(void)
{
u8 i;
u16 j;
for( i=0; i《100; i++)
{
j++;
}
}
/************************************************************************
* 函數名稱:sccb_start
* 功能說明:SCCB啟動位
*************************************************************************/
void sccb_start(void)
{
SCL_OUT;
SDA_OUT;
SDA_HIGH;
//sccb_wait();
SCL_HIGH;
sccb_wait();
SDA_LOW;
sccb_wait();
SCL_LOW;
}
/************************************************************************
* 函數名稱:sccb_stop
* 功能說明:SCCB停止位
*************************************************************************/
void sccb_stop(void)
{
SCL_OUT;
SDA_OUT;
SDA_LOW;
sccb_wait();
SCL_HIGH;
sccb_wait();
SDA_HIGH;
sccb_wait();
}
/************************************************************************
* 函數名稱:sccb_sendByte
* 功能說明:在SCCB總線上發送一個字節
* 參數說明:data 要發送的字節內容
*************************************************************************/
u8 sccb_sendByte(u8 data)
{
u8 i;
u8 ack;
SDA_OUT;
for( i=0; i《8; i++)
{
if(data & 0x80)
SDA_HIGH;
else
SDA_LOW;
data 《《= 1;
sccb_wait();
SCL_HIGH;
sccb_wait();
SCL_LOW;
sccb_wait();
}
SDA_HIGH;
SDA_IN;
sccb_wait();
SCL_HIGH;
sccb_wait();
ack = SDA_DATA;
SCL_LOW;
sccb_wait();
return ack;
}
/************************************************************************
* 函數名稱:sccb_regWrite
* 功能說明:通過SCCB總線向指定設備的指定地址發送指定內容
* 參數說明:device---設備號 讀寫有區別 42是寫,43是寫
* address---寫數據的寄存器
* data---寫的內容
* 函數返回:ack=1未收到應答(失敗) ack=0收到應答(成功)
*************************************************************************/
void sccb_regWrite(u8 device,u8 address,u8 data)
{
// u8 i;
u8 ack;
// for( i=0; i《20; i++)
// {
sccb_start();
ack = sccb_sendByte(device);
while( ack )
{
ack = sccb_sendByte(device);
// printf(“device\n\r”);
}
ack = sccb_sendByte(address);
while( ack )
{
ack = sccb_sendByte(address);;
// printf(“address\n\r”);
}
ack = sccb_sendByte(data);
while( ack )
{
ack = sccb_sendByte(data);
// printf(“data\n\r”);
}
sccb_stop();
// if( ack == 0 ) break;
// }
}
貼上使用的SCCB的庫之后,給大家看一下對SCCB的一段實例操作程序。程序上有詳細的解釋,我就不贅述了。
[objc] view plain copysccb_init();
sccb_regWrite(0x42,0x11,0x01); //地址0X11-中斷四分頻(1280*480) PCLK:166ns HREF:254.6us VSYN:133.6ms
sccb_regWrite(0x42,0x14,0x24); //地址0X14-QVGA(320*240) PCLK:332ns HREF:509.6us VSYN:133.6ms
sccb_regWrite(0x42,0x28,0x40); //地址0X28-黑白模式(320*240 PCLK:332ns HREF:127us VSYN:33.6ms
sccb_wait();
以上就是關于OV7620的使用了,看完之后大家是不是會使用了呢。關于后期圖像的處理和調試,我目前正在使用一款智能車調試助手,感覺非常好用,完全免費,并且可以配合Visual Studio,在Visual Studio里面用C#編寫一些圖像處理的算法,生成dll文件,然后在調試助手的界面里面直接觀察。非常好非常好。給大家看看圖。
ov7620作為一款CMOS攝像頭器件目前已經得到廣泛運用。本文開始介紹了OV7620基本參數,其次介紹了攝像頭工作原理,最后介紹了OV7620的使用。
本文開始介紹了OV7620的基本參數,其次介紹了ov7620硬件結構,最后闡述了ov7620的具體實現以及Ov7620的硬件連接。
本文開始對OV7620進行了介紹,其中包括了OV7620基本參數和OV7620應用實例,其次介紹了OV7670的參數與功能,最后分析了ov7620與ov...
編輯推薦廠商產品技術軟件/工具OS/語言教程專題
電機控制 | DSP | 氮化鎵 | 功率放大器 | ChatGPT | 自動駕駛 | TI | 瑞薩電子 |
BLDC | PLC | 碳化硅 | 二極管 | OpenAI | 元宇宙 | 安森美 | ADI |
無刷電機 | FOC | IGBT | 逆變器 | 文心一言 | 5G | 英飛凌 | 羅姆 |
直流電機 | PID | MOSFET | 傳感器 | 人工智能 | 物聯網 | NXP | 賽靈思 |
步進電機 | SPWM | 充電樁 | IPM | 機器視覺 | 無人機 | 三菱電機 | ST |
伺服電機 | SVPWM | 光伏發電 | UPS | AR | 智能電網 | 國民技術 | Microchip |
開關電源 | 步進電機 | 無線充電 | LabVIEW | EMC | PLC | OLED | 單片機 |
5G | m2m | DSP | MCU | ASIC | CPU | ROM | DRAM |
NB-IoT | LoRa | Zigbee | NFC | 藍牙 | RFID | Wi-Fi | SIGFOX |
Type-C | USB | 以太網 | 仿真器 | RISC | RAM | 寄存器 | GPU |
語音識別 | 萬用表 | CPLD | 耦合 | 電路仿真 | 電容濾波 | 保護電路 | 看門狗 |
CAN | CSI | DSI | DVI | Ethernet | HDMI | I2C | RS-485 |
SDI | nas | DMA | HomeKit | 閾值電壓 | UART | 機器學習 | TensorFlow |
Arduino | BeagleBone | 樹莓派 | STM32 | MSP430 | EFM32 | ARM mbed | EDA |
示波器 | LPC | imx8 | PSoC | Altium Designer | Allegro | Mentor | Pads |
OrCAD | Cadence | AutoCAD | 華秋DFM | Keil | MATLAB | MPLAB | Quartus |
C++ | Java | Python | JavaScript | node.js | RISC-V | verilog | Tensorflow |
Android | iOS | linux | RTOS | FreeRTOS | LiteOS | RT-THread | uCOS |
DuerOS | Brillo | Windows11 | HarmonyOS |