2014/04/16

ADNS系センサのRead / Write Operation

Avago製のADNS系センサーのレジスタへのRead Writeにちょっとつまずいたのでメモ的な感じで。
1から全部説明する時間が取れそうもないなので分かってる人向けです。要するにCypressの石を使って開発している方向けですが、そもそもそういう方は説明の必要もないのではとか思ったり。


環境 : PSoC Creator 3.0 SP7
センサ : ADNS-5090
MCU : PSoC 4 Pioneer Kit

PSoC 3 | 4 | 5 | 5LPだったら動くと思います。
PSoC CreatorのSPI ComponentはSPIMという名前にリネームして下さい。

Componentの設定は下図参照。ビットレート(1Mbps)とMode(Mode3 | CPHA=1、CPOL=1)に注意して下さい。
Avagoはデータシートにタイミングチャートだけポンと載せてModeを書かないのでちょっと混乱しました。

Write_Operation :
ターゲットのレジスタのアドレスと書き込む値を渡します。
e.g. Write_Operation(0x3A , 0x5A); //AVAGOセンサーは全部この値でRESETできます。

Read_Operation :
ターゲットのレジスタを渡すとuint8でレジスタの値を返します。
e.g. uint8 product_id = Read_Operation(0x00); //ProductID取得

SourceCode
------------------------------------------------------------------
// SPI Write Operation : detail -> Datasheet
void Write_Operation(uint8 address , uint8 value )
{

 CyDelayUs(14u);

 address = address | 0b10000000;

 SPIM_ClearRxBuffer();
 SPIM_ClearTxBuffer();
 SPIM_ClearFIFO();

 SPIM_WriteTxData(address);
 while(!(SPIM_ReadTxStatus() & SPIM_STS_TX_FIFO_EMPTY)){};

 SPIM_WriteTxData(value);
 while(!(SPIM_ReadTxStatus() & SPIM_STS_TX_FIFO_EMPTY)){};
}

// SPI Read Operation : detail -> Datasheet
uint8 Read_Operation(uint8 address)
{
 CyDelayUs(16u);

 address = address | 0b00000000;

 SPIM_ClearRxBuffer();
 SPIM_ClearTxBuffer();
 SPIM_ClearFIFO();

 SPIM_WriteTxData(address);
 while(!(SPIM_ReadTxStatus() & SPIM_STS_TX_FIFO_EMPTY)){};
 SPIM_WriteTxData(0x00);
 while(!(SPIM_ReadTxStatus() & SPIM_STS_TX_FIFO_EMPTY)){};

 while(!(SPIM_ReadRxStatus() & SPIM_STS_RX_FIFO_NOT_EMPTY )){};
 SPIM_ReadRxData();
 while(!(SPIM_ReadRxStatus() & SPIM_STS_RX_FIFO_NOT_EMPTY )){};
 return SPIM_ReadRxData();
}

------------------------------------------------------------------

Writeはあっさり実装できたのですが、ADNS-5090のRead Operationのタイミングチャートが間違っていて(文章は合っています)レジスタを読むのに結構手間取りました。他のデータシートも確認したのですが、タイミングチャートも大体あってると思います(若干怪しいのがあったような・・・)。

ポイントは、W/Rでアドレスのマスクが違うということ。これで送受信方向をセンサが判定しています。要するに、
Writeはaddress = address | 0b10000000;
Readはaddress = address | 0b00000000;
になるということですね。
加えて、Readの時はマスクしたアドレスを送った後に0x00をWriteTxしないとセンサから戻ってくるデータがReadFIFOに値が入らないということと、一回目のReadFIFOにはアドレスのTxした時のゴミデータ(0x00)が入っているので一度FIFOを読んで捨てる必要があります。

CyDelayUs(XXX)は連続でレジスタを操作しないためのディレイなのですが、センサによって値が異なるのでお手元のデータシートを参照下さい。


はじめはオシロスコープを使って実際のデータを見ながら試行錯誤していたのですが、なんだかんだデータシートを読めばオシロスコープ無しでも実装できました。


時間ができたらちゃんと記事にしたい(小声)

0 件のコメント:

コメントを投稿