看到一位牛人用51單片機自制數碼相機,覺得好厲害的樣子搬過來大家一起看看,源碼在最后啊
所謂“數碼相機”,其實就是圖像采集+數據存儲+顯示,當然還要有一個CPU作核心。
DIY一個簡易的“數碼相機”的想法由來已久,我們不需要它有多么強的功能,只要實現基本的圖像采集與存儲功能即可。我一直在關注和研究OV的圖像傳感器(俗稱攝像頭芯片)OV7670,雖然已經比較了解它的驅動方法,但也是困難重重,“DIY數碼相機”實驗也就一直擱置。
這個東西為什么那么難搞?其原因主要一是速度問題,二是數據量比較大。
速度方面,說白了,就是攝像頭芯片輸出像素數據的速度太快了!我們來舉例說明:假設芯片每秒產生10個圖像,即它的幀頻為10幀/秒。如果圖像的分辨率為320*240(QVGA),那么它每秒就將產生768000個像素數據,每一個像素數據在攝像頭芯片數據輸出端口上維持的時間約為1000ns。我們如果用單片機去采集這個數據,就必須在這1000ns的時間內完成數據的讀入、存儲與處理。有人可能說:“1000ns的時間應該是比較富裕的,足夠單片機去完成這些操作了。”確實!但是這需要代碼的運行效率很高,也許要使用匯編來完成。
另外,每一個像素數據并不單純是一個字節,而可能是16位或24位的。這就會涉及到多次數據讀入等操作。我們拿AVR這種單指令周期的CPU來舉個例子:我們將AVR超頻到20MHz(它的可靠工作主頻最高為16MHz),那么它每執行一條指令的時間為50ns,它要在1000ns的時間里完成像素數據的讀取等操作,最多只能用20條指令。是不是感覺有點玄乎?!再加之,像素數據在攝像頭芯片的數據輸出端口上產生也需要一個信號建立的過程,為了保證數據數據的穩定性,實際上留給我們去讀取像素數據的時間也只有700ns左右。這顯然是非常緊張的!
其實,就算真的來得及去讀取和處理像素數據,數據量也是一個大問題。像素數據我們是首先暫存在RAM中的,前面說過,一個像素數據可能是16位或24位的,就拿16位來說,一幅QVGA的圖像數據量為150KB,有多少單片機,乃至于ARM或更高端的芯片會有這么多的RAM資源?
上面說的是“數碼相機”實驗中,攝像頭芯片方面的一此困難。另一方面的問題是:SD卡的文件操作和數據寫入速率問題。假設我們現在已經得到了一幅完整而正確的圖像數據,它就存放在RAM中。現在,我們要把這些數據以文件的形式存入到SD卡中,并作成BMP位圖圖片。這一過程,仍然是一個極大的挑戰,挑戰并不在于SD卡的驅動或是BMP文件格式,這些都簡單!而在于文件系統,尤其是文件數據寫入這方面!詳細解釋一下:我們知道,SD卡或U盤這類存儲設備,要存儲文件必須事先進行格式化。格式化的過程其實就是使存儲設備遵從某種文件系統協議或者格式,比如我們經常使用的FAT32。要用單片機或ARM等去操作SD卡上的文件,必須也要遵循FAT32的協議格式。
長期以來所研究和編寫的znFAT就是在作這樣的事情,通過znFAT可以在SD卡等存儲設備上進行各種文件操作,如文件創建、數據讀寫等等。我們要將像素數據以BMP文件的形式寫入SD卡,就可以使用znFAT的文件創建和數據寫入功能來實現(znFAT是一個完備而龐雜的東西,詳細可以參考使用手冊)。對于像素數據的寫入,我們是要講求一些速度的。說白了,向SD卡上的文件中寫入這150KB的像素數據,如果用了半個小時,那這樣的“數碼相機”實驗還有什么樂趣和實用性可言,簡直變成了一種煎熬!我們要求每寫入一個圖片,這個寫入數據的過程所花費的時間最好控制在幾秒以內,最多不過10秒。znFAT的性能和執行效率能有這么高嗎?這正是上面我們所說的的挑戰所在!
現在“數碼相機”實驗已經作成功了,發布在這里給大家作個參考。上面的諸多問題的解決方法:
1、速度太快的問題采用在攝像頭芯片的數據輸出端口上加一片FIFO芯片AL422來解決,同時因為AL422有300多KB的容量,所以數據量大的問題也隨之解決。150KB的像素數據進入到FIFO中后,單片機可以“小數據量,多次取出”的方式將數據取走,進而再存到SD卡的BMP文件中。當然,數據寫入文件的方式是“頻繁的小數據量寫入”,這種寫入方式其實是最考驗一個文件系統方案的效率的。我試過在不開啟znFAT的加速算法的時候,以這種方式寫完一個BMP文件,大約需要40s左右。然而在開啟加速算法之后,只需要10s(開啟與不開啟,在RAM資源的占用上僅僅多了幾十個字節,這也正是znFAT所使用的加速算法的獨到之處)。
2、采用了比較優秀的加速算法(基于預建簇鏈與壓縮簇鏈緩沖思想),可以在占用極少的內存資源的前提下,極大的提高文件數據的寫入速率。因此,BMP文件數據的寫入速率問題也解決了。
51單片機DIY數碼相機源碼下載:
DIY簡易數碼相機的源代碼.zip