STM32F4Discovery-DCMIを介してカメラを接続します
![](https://habrastorage.org/storage2/019/9f9/9ce/0199f99ce27d7c60203b70d278c6e627.png)
MKでさまざまなモバイルハードウェア(特にLCDやカメラ)を研究し、共同発売することの大ファンなので、そのような発見をすり抜けることができなかったため、STM32周辺機器の研究でこのギャップを埋めることにしました。 実際、この資料は、アイデアの実装の説明に専念しています。
ちょっとした理論。
まず第一に、それが何であるかを想像する必要があります-むしろ、CMOSカメラとは何か、それは何と一緒に食べられるのか。
このタイプのカメラは、センサーからの情報をデジタル形式(RGB、YCbCr、および圧縮形式-JPEG)で表示します。 さまざまなカメラは機能の点で独自のニュアンスを持っています。私は、 Siemens C72電話( PixelPlus PO2030Nセンサー)から太古の時代から引き出された小さな解像度(VGA、640x480)のカメラの非常に特殊なケースを検討します。 このカメラは、操作が簡単で、多かれ少なかれ一般的なタイプに属しているため、研究に最適です。 むかしむかし、I 2 Cバスに2.8 Vのスタビライザーとプルアップ抵抗を付けて、接続のために小さなボードをエッチングしました。 ここにあります(ケーブルとカメラコネクタはカバーの下に隠れています)。
![画像](https://habrastorage.org/storage2/cdd/85c/ecb/cdd85cecb310ea068d1545c67e3dde87.png)
データ形式の分野でのニュアンスに加えて、カメラは同期リードの数の分野でも異なる場合があります。 ほとんどの(私の意見では)センサーには、特別なラインおよびフレーム同期の結論があります。 ただし、ピクセルストロボ出力しかないカメラがあり、特殊な送信コード(たとえば、 0x00または0xFF )を使用して、新しいライン/フレームの開始を知らせます。 利用可能なカメラには外部同期出力があります。
ブロックの形でカメラのおおよその概略画像を推定できます。
![](https://habrastorage.org/storage2/0bf/b66/688/0bfb66688daea6e65b596d469f4a0c12.png)
ほとんどの場合、CMOSカメラはI2Cインターフェイスを介して制御されます (ただし、 UARTによっても制御されるデバイスを見てきました)。 I2Cは、解像度、色域、出力データ形式などのさまざまなパラメーターを構成します。
EXTCLKの結論はカメラのクロッキングであり、外部から提供する必要があります。 DCLK-データがカメラデータバスに記録される前縁または後縁のストローブ信号(たとえば、マトリックスの1ピクセルのデータバイト、またはカメラがRGB565モードで動作している場合は「ハーフピクセル」のデータバイト)。 HSYNCは、新しいラインの始まりを示す水平同期信号です。VSYNCは、アクティブレベルが新しいフレームの始まりを示す同期信号です。 結論D0..D7-データバス。 原則として、このようなカメラでは8ビットです。
同期信号について詳しく説明します。
![](https://habrastorage.org/storage2/159/aef/938/159aef9387f0ea7ddaf7436ec81fcf0d.png)
グラフは、カメラがアクティブなHSYNCフェーズでのみDCLK信号アクティビティ用に設定されていることを示しています(つまり、このフェーズは私たちにとって重要であり、「ラインフィード」期間中のクロック信号には興味がありません)。 カメラが320x240の解像度に設定されている場合、 DCLKの 320パルスが各HSYNCパルスの周期に適合し、240 HSYNCがVSYNC周期に適合します 。
ズームインすると、データバスで何が起こっているかがわかります。
![](https://habrastorage.org/storage2/f23/cdd/04c/f23cdd04cface68b9b0d3b71c39d694a.png)
リーディングエッジ(この場合)では、1バイトがデータバスから削除されます。これは、表示のためにディスプレイに直接送信されるか、後続の処理のためにバッファに「入れられます」。
理論的には、 STM32マイクロコントローラーのDCMIインターフェースに関するすべてが多かれ少なかれ明確です。
DCMIインターフェイスは、最大14ビット幅のデータバスで動作し、ハードウェアとソフトウェアの両方の同期、およびデータ形式(YCbCr、RGB、JPEG)をサポートします。
さらに、 DCMIにはFIFOバッファーが含まれており、割り込み(データレジスタの入力を含む)を構成し、 DMAを介して作業を構成できます。
![](https://habrastorage.org/storage2/990/dbb/326/990dbb3269c59873fd044da950a6e8c9.png)
DCMI割り込みは、次の条件が発生したときにトリガーできます 。ライン終了、フレーム終了、受信バッファーオーバーフロー、同期エラー検出(内部同期あり)。
戸惑うことに、カメラクロック用の特別な出力がないことで私は紹介されました。 SGS Microelectronicsの開発者がそれを拒否した理由はわかりませんが、たとえば、カスタムクロックソースがあると非常に便利です。
個人的には、PWMモードに含まれる汎用タイマーカウンターを使用して、4 MHzの蛇行を生成しました。 もちろん、このようなクロック速度では大きなFPSを取得することはできませんが、すぐに予約します-使用するディスプレイはFSMCに接続されていないため、回路全体で最も長い機能はLCD出力機能です。したがって、より高い周波数では、画面への画像出力が失敗します。 したがって、アンロードする前にタイマーをオフにし、その後タイマーを再びオンにします。
DCMIハードウェアモジュールには、データレジスタに加えて、10個の制御/ステータスレジスタが含まれています。 制御レジスタ( DCMI_CR )、ステータスレジスタ( DCMI_SR )、割り込みステータスレジスタ( DCMI_RIS )、割り込みイネーブルレジスタ( DCMI_IER )、割り込みマスクレジスタ( DCMI_MIS )、割り込みフラグリセットレジスタ( DCMI_ICR )、内部同期コードレジスタ( DCMI_ESCR ) 、内部同期コードのマスクをリセットするためのレジスタ( DCMI_ESUR )、フレームの一部をキャプチャするときの開始値のレジスタ( DCMI_CWSTRT )、およびCropWindowモードのフレームのフラグメントの値のレジスタ( DCMI_CWSIZE )。 そして、もちろん、データレジスタはDCMI_DRです。
この場合、フレームの一部のキャプチャと内部同期に関連するレジスタは、私たちには関係ありません。 また、今のところ中断を残すことにしたので、 DCMI_CR制御レジスタとDCMI_SRステータスレジスタのみをより詳細に検討する価値があります。
制御レジスタにより、カメラとの相互作用のフォーマットを完全にカスタマイズできます:データバスサイズ、 HSYNCおよびVSYNCラインのアクティブレベルなど。
![](https://habrastorage.org/storage2/de2/12b/e57/de212be5787e089d110810d75797c0a1.png)
順番に。 ENABLEビットは、もちろん、インターフェイスを含めることです。 フィールドEDM ( 拡張データモード )-データバスサイズ。 カメラのバスは8ビットなので、このフィールドは「00」に設定する必要があります。 フィールドFCRC ( フレームキャプチャレート制御 )を使用すると、FPCをわずかに調整できます。00-すべての着信フレームがキャプチャされ、 01-1秒おきに フレーム、 10-4秒ごとにキャプチャされます。 VSPOLおよびHSPOLビットは、垂直および水平同期ラインのアクティブレベルです。 アクティブなレベルは無視され、アクティビティ期間中のデータはキャプチャされません。これを考慮する必要があります。 PCKPOL-ピクセルストローブのアクティブレベルのビット-バスからデータを読み取る信号のエッジ:フロントまたはバック。 ESS-同期方法の選択のビット:外部または内部。 JPEG-受信データの形式を選択します-圧縮されているかどうか。 CROP-フレームフラグメントのキャプチャを選択するビット( トリミングウィンドウ )。 このビットが1に設定されている場合、インターフェイスは、 DCMI_CWSTRTおよびDCMI_CWSIZEレジスタの値によって決定されるウィンドウのデータをキャプチャします。
だから、カスタマイズ可能。
私はSTの標準周辺機器ライブラリを使用することに慣れているため(「ペン」でレジスタをさらに掘り下げるまで、新しい周辺機器を使用する最初の反復では使用しませんが)、ライブラリを使用して設定を行います。
void DCMIInitialRoutine(void) { DCMI_InitTypeDef DCMI_CamType; DCMI_DeInit(); DCMI_CamType.DCMI_CaptureMode = DCMI_CaptureMode_Continuous; DCMI_CamType.DCMI_CaptureRate = DCMI_CaptureRate_All_Frame; DCMI_CamType.DCMI_ExtendedDataMode = DCMI_ExtendedDataMode_8b; DCMI_CamType.DCMI_SynchroMode = DCMI_SynchroMode_Hardware; DCMI_Init(&DCMI_CamType); DCMI_CaptureCmd(ENABLE); DCMI_Cmd(ENABLE); return; }
実際、私のニーズのために、 DCMI_CRレジスタの1ビットに触れないようにすることができました-デフォルトでは、 CAPTUREおよびENABLEビットを除き、リセットされます。
インターフェイスが構成され、準備ができました。 カメラにクロック信号を適用すると、インターフェイスは処理が必要なデータの受信を開始します。
まず、タスクを可能な限り単純に設定します。ディスプレイに画像を表示して、データ処理が最小限になるようにします。
受信バッファからのデータのタイムリーな読み取りでは、ステータスレジスタDCMI_SRが役立ちます。
![](https://habrastorage.org/storage2/9de/7dc/6df/9de7dc6dfc4209a6f183c0b77e59adce.png)
読み取りに使用できるビット数は非常に少ないため、3ビットのみです。 HSYNCおよびVSYNCビットは、対応するラインのステータスを通知します。アクティブフェーズまたはラインフィード。 最も興味深いのはFNEビットです。 バッファをデータで埋めるように指示します。 または記入しません。
一定のサイクルでDCMI_SRのFNEビットの状態を確認すると、32ビットの受信バッファーにデータが到着したことがわかります。 私の場合、データは次のように配置されます。
![](https://habrastorage.org/storage2/68f/337/86c/68f33786c0a6515116456140d1835b0b.png)
FNEビットが設定されると、受信バッファーのDCMI_SRステータスレジスタには4つのバイト、2つの隣接ピクセルのデータが含まれます: Byte0とByte1-ピクセルnの 16ビット、 Byte2とByte3-ピクセルn + 1の 16ビット。 それらを組み合わせて表示用に送信するだけです。 メインループは次のようになります。
while (1) { while ((DCMI_GetFlagStatus(DCMI_FLAG_FNE)) == RESET); //Waiting for the buffer TIM_Cmd(TIM3, DISABLE); //Disable CAM clock cam_grab = (DCMI->DR); //Reading buffer SendDataByte_LCD (cam_grab); cam_grab = (DCMI->DR)>>16; //Reading 2nd part of the buffer SendDataByte_LCD (cam_grab); TIM_Cmd(TIM3, ENABLE); //Enable CAM clock again }
つまり、 DCMI_SRステータスレジスタでFNEビットが設定されるのを待ち 、その後16ビットのデータを2 パスでディスプレイにアップロードします。
この時点で、論理的な結論に達したいと思いますが、そうでした。
ディスプレイでMKを点滅させて再起動した後、私は見ました...いいえ、私は自分の身近な物理学を見ましたが、黒と青の色合いで見ました。 赤と緑の色は完全に欠けていました。
デバッガーで簡単に逆アセンブルした後、次のことが発見されました。インターフェイスデータレジスタには、1ピクセルのデータが16ビットのみ含まれ、下位8ビットはByte0 (上図を参照)、最古はByte2にあります。 スペースByte1およびByte3は空でした。 今まで、私は現実の記録間の矛盾がどこから来たのか理解しておらず、STMに目を向けることがあります。
その結果、 DCMIインターフェースを使用してカメラから画像を取得することができましたが、多少の困難はありました。 図では、カメラのSTM32F3Discoveryデモボードの画像が表示されたディスプレイの写真を示しています。
![](https://habrastorage.org/storage2/6f6/634/1bc/6f66341bc90a03b33f15de3cfd61130c.png)
ロジックアナライザーを接続した場合のEXTCLK 、 PIXCK 、 HSYNC 、およびVSYNCの出力に表示されるものを次に示します。
![](https://habrastorage.org/storage2/530/610/cd2/530610cd28d99ee6cef684269e1d85bf.png)
すべてが期待どおりに見えます。240個のHSYNCパルスが1つのVSYNCの持続時間に収まり、320 PIXCK -1つのHSYNCに 収まります。 HSYNCのアクティブフェーズでは、カメラは設定されたとおりにPIXCK信号を出力しません。
一般的に言って、インターフェースは私をいくらか失望させました。 カメラをクロックするための「通常の」足の欠如、興味深い組み込みチップの欠如(ハードウェアJPEGエンコーダーについてはどうでしょうか?)、さらに半分のFIFOでタンバリンと踊る...
PIXCK 、 HSYNC 、およびVSYNC割り込みでカメラを使用して作業を整理しましたが、ハードウェアDCMIを使用してカメラを操作していましたが、これほどバントはありませんでした。
それでも、近い将来、フレームをキャプチャしてJPEGで圧縮し、SDカードに画像を書き込もうとします。
PS。 念のため、「 Code :: Blocks 」のプロジェクトへのリンクを提供します-それは突然誰かに役立つでしょう。
www.dropbox.com/sh/nfjdwqsdzlr7djm/9v2mQM8uYV