天天看點

FPGA設計——全局曝光CMOS圖像采集與USB2.0顯示

1. 概述 

本設計采用FPGA技術,将CMOS攝像頭(LVDS接口)的視訊資料經過采集、存儲、幀率轉換及格式轉換,最終通過USB2.0接口顯示在電腦螢幕上。

2. 硬體系統框圖

CMOS采用一款全局曝光晶片,FPGA采用ALTERA公司的CYCLONE IV,FLASH采用EPCS64,DDR2采用Hynix公司的1Gb記憶體條,USB2.0采用Cypress公司的68013晶片。

<a href="https://s3.51cto.com/wyfs02/M01/8D/9E/wKioL1ikEwyDnMk6AABlH8_nokk267.jpg" target="_blank"></a>

3. FPGA邏輯框圖

FPGA各部分邏輯子產品如下圖所示:

<a href="https://s2.51cto.com/wyfs02/M02/8D/9E/wKioL1ikFOPADhJPAACbnt1QUtI241.jpg" target="_blank"></a>

LVDS Decode,解碼CMOS攝像頭視訊資料;

I2C Master,配置CMOS晶片;

DDR2 Control,配置與控制DDR2晶片組,實作讀寫仲裁;

FIFO Write,将采集到的視訊資料跨時鐘域地寫進DDR2中;

FIFO Read,将DDR2中的資料跨時鐘域地讀出給後續圖像處理子產品;

Frame Buffer,負責FIFO Write和FIFO Read的排程,實作幀率轉換;

USB Control,接受USB PHY的請求,通過FIFO Read向DDR2索取資料,并自定義打包發送給USB PHY晶片。

4. 全局曝光

全局曝光是針對逐行曝光的改進,在逐行曝光下,sensor是按照行為機關進行逐行曝光,這樣當被攝物體和sensor存在高速的相對運動時,圖像會發生形狀和顔色的變形,如下圖所示:

而全局曝光則是以幀為機關進行曝光,可以拍攝到高速運動的物體且沒有變形。

5. LVDS解碼

攝像頭晶片提供差分串行接口(LVDS),支援1/2/4個Data lane來傳輸圖像8/10/12 bit資料。這裡以4個data lane,同步信号内嵌的模式為例,介紹其傳輸時序。

<a href="https://s1.51cto.com/wyfs02/M00/8D/A1/wKiom1ikGi_gUK2iAADywDjoxlo870.jpg" target="_blank"></a>

6. CMOS配置

CMOS sensor支援最高130萬像素,240幀的視訊輸出。

<code>SpiWriteRegister(0x01,0x03,0x01);</code><code>// soft reset</code>

<code>SpiWriteRegister(0x01,0x00,0x00);SpiWriteRegister(0x30,0x34,0x01);SpiWriteRegister(0x30,0x35,0xc2);</code>

<code>SpiWriteRegister(0x33,0x0b,0x4c);SpiWriteRegister(0x36,0x64,0x09);SpiWriteRegister(0x36,0x38,0x82);</code>

<code>SpiWriteRegister(0x3d,0x08,0x00);SpiWriteRegister(0x36,0x40,0x03);SpiWriteRegister(0x36,0x28,0x07);</code>

<code>SpiWriteRegister(0x32,0x05,0x93); </code><code>//rnc</code>

<code>SpiWriteRegister(0x36,0x20,0x42);SpiWriteRegister(0x36,0x23,0x06);SpiWriteRegister(0x36,0x27,0x02);</code>

<code>SpiWriteRegister(0x36,0x21,0x28);SpiWriteRegister(0x36,0x3b,0x00);SpiWriteRegister(0x36,0x33,0x24);</code>

<code>SpiWriteRegister(0x36,0x34,0xff);  </code><code>//fpn optimize</code>

<code>SpiWriteRegister(0x34,0x16,0x10);SpiWriteRegister(0x3e,0x03,0x0b);SpiWriteRegister(0x3e,0x08,0x03);</code>

<code>SpiWriteRegister(0x3e,0x09,0x20);SpiWriteRegister(0x3e,0x01,0x23);</code>

<code>SpiWriteRegister(0x3e,0x14,0xb0);SpiWriteRegister(0x33,0x0b,0x40);SpiWriteRegister(0x3e,0x08,0x3f);</code>

<code>SpiWriteRegister(0x36,0x3b,0x80);SpiWriteRegister(0x36,0x23,0x07);SpiWriteRegister(0x50,0x00,0x01);</code>

<code>SpiWriteRegister(0x3e,0x01,0x00);SpiWriteRegister(0x3e,0x02,0x30);SpiWriteRegister(0x32,0x0c,0x05);</code>

<code>SpiWriteRegister(0x32,0x0d,0x46);SpiWriteRegister(0x32,0x0e,0x02);</code>

<code>SpiWriteRegister(0x32,0x0f,0x58);SpiWriteRegister(0x36,0x38,0x85);SpiWriteRegister(0x33,0x06,0x50);</code>

<code>SpiWriteRegister(0x33,0x0b,0x68);SpiWriteRegister(0x33,0x08,0x10);SpiWriteRegister(0x3e,0x01,0x00);</code>

<code>SpiWriteRegister(0x36,0x3b,0x00);SpiWriteRegister(0x36,0x63,0xf8);SpiWriteRegister(0x36,0x64,0x0a);</code>

<code>SpiWriteRegister(0x36,0x33,0x27);SpiWriteRegister(0x30,0x3a,0x3a);</code>

<code>SpiWriteRegister(0x30,0x3a,0x3a);SpiWriteRegister(0x30,0x3a,0x3a);SpiWriteRegister(0x30,0x3a,0x3a);</code>

<code>SpiWriteRegister(0x36,0x3b,0x00);SpiWriteRegister(0x34,0x16,0x38);SpiWriteRegister(0x3e,0x08,0x23);</code>

<code>SpiWriteRegister(0x3c,0x00,0x41); </code><code>//FIFO RESET for mipi</code>

<code>SpiWriteRegister(0x30,0x19,0x00);</code>

<code>SpiWriteRegister(0x30,0x31,0x0a); </code><code>// 10bit</code>

<code>SpiWriteRegister(0x30,0x00,0x00);SpiWriteRegister(0x30,0x01,0x00);SpiWriteRegister(0x30,0x39,0x20);</code>

<code>SpiWriteRegister(0x30,0x3a,0x31);SpiWriteRegister(0x30,0x3b,0x02);SpiWriteRegister(0x30,0x3c,0x08);</code>

<code>SpiWriteRegister(0x4b,0x00,0xa2); </code><code>//must </code>

<code>SpiWriteRegister(0x30,0x22,0x19); </code><code>//must</code>

<code>SpiWriteRegister(0x30,0x3f,0x01); </code><code>//must</code>

<code>SpiWriteRegister(0x30,0x30,0x04); </code><code>//must</code>

<code>SpiWriteRegister(0x30,0x2b,0xa0); </code><code>//must</code>

<code>SpiWriteRegister(0x36,0x20,0x43);SpiWriteRegister(0x36,0x21,0x18);SpiWriteRegister(0x45,0x01,0xc0);</code>

<code>SpiWriteRegister(0x45,0x02,0x16); </code><code>//br recieve inv off</code>

<code>SpiWriteRegister(0x36,0x23,0x07);SpiWriteRegister(0x50,0x00,0x01);SpiWriteRegister(0x36,0x20,0x43);</code>

<code>SpiWriteRegister(0x33,0x00,0x30);SpiWriteRegister(0x3e,0x01,0x14);SpiWriteRegister(0x36,0x3b,0x80);</code>

<code>SpiWriteRegister(0x36,0x64,0x0a);SpiWriteRegister(0x3e,0x08,0x23);</code>

<code>SpiWriteRegister(0x34,0x16,0x00);SpiWriteRegister(0x36,0x33,0x20);</code>

<code>SpiWriteRegister(0x36,0x33,0x23);SpiWriteRegister(0x32,0x11,0x0c);SpiWriteRegister(0x3e,0x0f,0x05);</code>

<code>SpiWriteRegister(0x36,0x3b,0x08); </code><code>//fpn</code>

<code>SpiWriteRegister(0x36,0x33,0x22); </code><code>//nvdd</code>

<code>SpiWriteRegister(0x33,0x02,0x0c);</code><code>//rst go low</code>

<code>SpiWriteRegister(0x33,0x83,0x0a);</code><code>// pbias en rise edge</code>

<code>SpiWriteRegister(0x36,0x23,0x04);</code>

<code>SpiWriteRegister(0x33,0x82,0x0f); </code><code>//sa fall edge</code>

<code>SpiWriteRegister(0x3e,0x0f,0x84);  </code><code>//gain</code>

<code>SpiWriteRegister(0x3e,0x0e,0x03);  </code><code>//gain</code>

<code>SpiWriteRegister(0x3e,0x08,0x27);SpiWriteRegister(0x3e,0x08,0x23);SpiWriteRegister(0x36,0x64,0x05);</code>

<code>SpiWriteRegister(0x33,0x0b,0x68);</code>

<code>SpiWriteRegister(0x36,0x38,0x84);SpiWriteRegister(0x5b,0x00,0x02);SpiWriteRegister(0x5b,0x01,0x03);</code>

<code>SpiWriteRegister(0x5b,0x02,0x01);SpiWriteRegister(0x5b,0x03,0x01);SpiWriteRegister(0x36,0x3b,0x02);</code>

<code>SpiWriteRegister(0x36,0x32,0x54);SpiWriteRegister(0x36,0x33,0x32);SpiWriteRegister(0x34,0x16,0x0e);</code>

<code>SpiWriteRegister(0x36,0x64,0x0e);SpiWriteRegister(0x36,0x63,0x88);SpiWriteRegister(0x33,0x0b,0x50);</code>

<code>SpiWriteRegister(0x36,0x22,0x06); </code><code>//blksun</code>

<code>SpiWriteRegister(0x36,0x30,0xb3);SpiWriteRegister(0x34,0x16,0x11);SpiWriteRegister(0x01,0x00,0x01);</code>

7. USB2.0 PHY

Cypress公司的EZ-USB FX2是世界上第一款內建USB2.0的微處理器,它內建了USB2.0收發器、SIE(串行接口引擎)、增強的8051微控制器和可程式設計的外圍接口。

<a href="https://s1.51cto.com/wyfs02/M02/8D/9F/wKioL1ikHcSgqv35AADhn28koiQ320.jpg" target="_blank"></a>

8. USB Slave FIFO傳輸

當有一個與晶片相連主要隻需要利用FX2做為一個USB2.0接口而實作與主機的高速通訊,而它本身又能夠提供滿足Slave FIFO要求的傳輸時序時,可采用Slave FIFO傳輸方式。

<a href="https://s3.51cto.com/wyfs02/M01/8D/9F/wKioL1ikH_aiiYkAAABY_UkM_Iw281.jpg" target="_blank"></a>

這種方式下,内嵌的8051固件隻負責配置Slave FIFO相關的寄存器以及控制FX2何時工作在Slave FIFO模式下。

在Slave FIFO模式下,主要邏輯與FX2的連接配接如下圖所示:

<a href="https://s2.51cto.com/wyfs02/M01/8D/9F/wKioL1ikICCh17_vAABONIi0IRM068.jpg" target="_blank"></a>

IFCLK: FX2 輸出的時鐘,可做為通訊的同步時鐘

FLAGA/FLAGB/FLAGC/FLAGD: FX2 輸出的FIFO狀态資訊,如滿,空等

SLCS:FIFO的片選信号,外部邏輯控制,當 SLCS 輸出高時,不可進行資料傳輸

SLOE:FIFO輸出使能,外部邏輯控制,當 SLOE 無效時,資料線不輸出有效資料

SLRD:FIFO 讀信号,外部邏輯控制,同步讀時,FIFO指針在SLRD 有效時的每個IFCLK的上升沿遞增,異步讀時, FIFO 讀指針在 SLRD 的每個有效—無效的跳變沿時遞增

SLWR:FIFO 寫信号,外部邏輯控制,同步寫時,在 SLWR 有效時的每個 IFCLK 的上升沿時資料被寫入, FIFO指針遞增,異步寫時,在SLWR的每個有效—無效的跳變沿時資料被寫入,FIFO寫指針遞增

PKTEND:包結束信号,外部邏輯控制,在正常情況下,外部邏輯向 FX2 的 FIFO 中寫數,當寫入FIFO端點的位元組數等于FX2固件設定的包大小時,資料将自動被打成一包進行傳輸,但有時外部邏輯可能需要傳輸一個位元組數小于 FX2 固件設定的包大小的包,這時它隻需在寫入一定數目的位元組後,聲明此信号,此時 FX2 硬體不管外部邏輯寫入了多少位元組,都自動将之打成一包進行傳輸

FD[15:0]:資料線;

FIFOADR[1:0]:選擇四個 FIFO 端點的位址線,外部邏輯控制

這裡設定FIFO為異步寫模式,連接配接的接口如下圖所示:

<a href="https://s3.51cto.com/wyfs02/M00/8E/89/wKioL1jD-1DBgPxtAAByCrLtm7E469.png" target="_blank"></a>

标準的異步寫模式的狀态機如下圖所示:

<a href="https://s4.51cto.com/wyfs02/M02/8E/89/wKioL1jD-5ej5xXZAACEle3C2vs598.png" target="_blank"></a>

IDLE:當寫事件發生時,進入狀态1;

狀态1:使FIFOADR[1:0]指向IN FIFO,進入狀态2;

狀态2:如果FIFO滿,進入等待,否則進入狀态3;

狀态3:擷取資料,使能SLWR,再無效,進入狀态4;

狀态4:如需繼續傳遞資料,進入狀态2,否則進入IDLE。

9. USB驅動開發

開發EZ-USB驅動程式需要用到微軟的WDW DDK和VC++,DDK可從http://www.microsoft.com/hwdev獲得。這裡我們直接使用Cypress提供的一套驅動程式,足以滿足一般項目需求。以WIN7 64位驅動為例,需以下三個檔案:

cyusb.sys、cyusbfx1_fx2lp.cat、cyusbfx1_fx2lp.inf。

其中需要我們修改的是cyusbfx1_fx2lp.inf檔案,在其中添加我們的PID/VID和描述符(Shugen_VIP Device)。

<code>;</code><code>for</code> <code>x64 platforms</code>

<code>[Device.NTamd64]</code>

<code>%VID_2017&amp;PID_0328.DeviceDesc%=CyUsb, USB\VID_2017&amp;PID_0328</code>

<code>[Strings]</code>

<code>CYUSB_Provider    = </code><code>"Cypress"</code>

<code>CYUSB_Company     = </code><code>"Cypress Semiconductor Corporation"</code>

<code>CYUSB_Description = </code><code>"Cypress Generic USB Driver"</code>

<code>CYUSB_DisplayName = </code><code>"Cypress USB Generic"</code>

<code>CYUSB_Install     = </code><code>"Cypress CYUSB Driver Installation Disk"</code>

<code>VID_2017&amp;PID_0328.DeviceDesc=</code><code>"Shugen_VIP Device"</code>

<code>CYUSB.GUID=</code><code>"{AE18AA60-7F6A-11d4-97DD-00010229B959}"</code>

<code>CYUSB_Unused      = </code><code>"."</code>

在裝置管理器中安裝好的驅動如下:

<a href="https://s2.51cto.com/wyfs02/M02/8F/AC/wKiom1jogGDzL9zUAAB2WoJN8r0165.png" target="_blank"></a>

10. 固件程式開發

USB2.0的固件程式開發在KEIL下完成,在工程中添加EZUSB的USBJmp.OBJ和EZUSB.LIB兩個目标和庫檔案,工程下有三個重要源檔案:

fw.c, FirmWare的縮寫,USB協定方面的通信都是在這裡完成的,包括上電枚舉、重枚舉、喚醒及調用使用者程式等。

periph.c,使用者代碼在這裡完成,Cypress已經為我們搭好了架構。檔案中包括void TD_Init(void)、void TD_Poll(void)、BOOL DR_VendorCmnd(void)、void ISR_Ep0in(void) interrupt 0~void ISR_Ep8inout(void) interrupt 0 函數。

dscr.51,USB描述符檔案,包括了裝置描述符、接口描述符、端點描述符、字元串等。

這裡為了實作USB PHY晶片和FPGA的同步,需要用視訊的場同步信号vsync來做同步,使用68013的INT0引腳實作中斷觸發,具體中斷函數如下:

<code>void</code> <code>ISR_EXTR0(</code><code>void</code><code>) interrupt  0 </code><code>//using 0</code>

<code>{</code>

<code>    </code><code>if</code><code>(frame_sign == 1){</code>

<code>       </code><code>PA1 = 1; </code><code>//Enable image input   </code>

<code>    </code><code>}</code>

<code>    </code><code>else</code>   

<code>    </code><code>{</code>

<code>        </code><code>PA1 = 0; </code><code>//Disable image input</code>

<code>        </code><code>//Reset FIFO of EDP2</code>

<code>        </code><code>SYNCDELAY;</code>

<code>        </code><code>FIFORESET = 0x80;</code><code>// activate NAK-ALL to avoid race conditions</code>

<code>        </code><code>FIFORESET = 0x02;</code><code>// reset, FIFO 2</code>

<code>        </code><code>FIFORESET = 0x00;</code><code>// deactivate NAK-AL</code>

<code>}</code>

設計好代碼後,編譯生成HEX檔案(用于線上調試,下載下傳到ram中)和IIC檔案(用于固化EEPROM)。

11. 固化代碼

将KEIL編譯生成的IIC檔案固化到EEPROM中需要使用CYPRESS提供的CyConsole工具,具體使用方法如下圖所示:

<a href="https://s5.51cto.com/wyfs02/M02/8F/AB/wKioL1johgSgzExMAAE4Q84ksQk422.png" target="_blank"></a>

如果固化成功,重新開機後可以在CyConsole中看到USB2.0裝置的具體資訊:

<a href="https://s3.51cto.com/wyfs02/M00/8F/AB/wKioL1johkaQ6gn3AAB8XNk7qDU057.png" target="_blank"></a>

12. 上位機DEMO軟體

在Windows下可以使用VC++開發應用軟體,在設計68013上位機程式的過程中,需要用到CPYRESS官方提供的API函數和驅動程式。開發包位址如下:

http://www.cypress.com/documentation/software-and-drivers/suiteusb-34-usb-development-tools-visual-studio

支援的作業系統:

Windows 2000(w2K) Windows XP (wxp) Windows Vista (wlh) Windows 7

支援的CPU類型:

x86(32bit-i386) x64(64bit-amd64)

開發過程需要使用cyapi.h和cyapi.lib兩檔案。CyAPI 控制函數類主要包括 8 個控制類:

傳輸端點控制類 CCyBulkEndPoint、控制傳輸端點類CCyControlEndPoint 、 中 斷 傳 輸 端 點 控 制 類 CCyInterruptEndPoint 、 同 步 傳 輸 端 點 控 制 類CCyIsocEndPoint、裝置控制類 CCyUSBDevice、配置資訊類 CCyUSBConfig、端點控制類 CCyUSBEndPoint和接口控制類 CCyUSBInterface。具體的使用方法可以參考Cypress CyAPI Programmer's Reference

13. 最終結果

下圖為用手機拍攝的風扇的圖檔,已經完全看不到扇葉的形狀。

<a href="https://s5.51cto.com/wyfs02/M00/8D/9F/wKioL1ikI9nzK4l-AACKUSqDe7Q272.jpg" target="_blank"></a>

下圖為設計的闆卡拍攝的圖檔,從圖中可以看出扇葉的形狀,盡管風扇在高速旋轉。

<a href="https://s2.51cto.com/wyfs02/M00/8D/A2/wKiom1ikJHiQltdDAAD6EHGPFcI292.jpg" target="_blank"></a>

本文轉自 shugenyin 51CTO部落格,原文連結:http://blog.51cto.com/shugenyin/1898160

繼續閱讀