2013/09/28

[電子工作]aitendoのDDSモジュールを動かす その2

,
0)前置き

 前にこんな記事を書いて以来、aitendoのDDSモジュールも放置していたのですが、そろそろケースに入れたいのでまた触り始めました。
 取り敢えず、SPIでいい加減動かさないと…ということでSPIから制御する話です。

 使ったハードはArduino Duemilanoveなので(今となっては化石…)、Master側のSPI設定に困ることはないです。


1)ハード的な話

 AD9850は、どうも2ピンがLow、3・4ピンがHighならばデフォルトでシリアル通信モードみたいです。aitendoにある回路図を見ると、2ピンに繋がっているJP1をジャンパしておけばGNDに落ちるみたいなので、パラレル→シリアルへの変換コマンドを送る必要はないみたいです。

 出力ですが、IOUTが200ΩでGNDに落ちているので、そのまま出力インピーダンスも200Ωなのでしょうか…?評価キットの回路図では、IOUTBは25ΩでGNDに、IOUTは50ΩでGNDに落ちてますが…

2)ソフト的な話

 AD9850のデータシートに書かれている、SPI通信のタイミングをみます。
AD9850 Data Sheet 英語 Rev H(http://www.analog.com/static/imported-files/data_sheets/AD9850.pdf)より転載
で、AD9850のシリアル信号線の名前は、SPIによくあるSS、MOSIなどとは違ってますが、結局役割は同じみたいです。

FQUP(FreQuency UPdate) → SS(10)
WCLK → SCLK(13)
D7 → MOSI(11)


 SPI通信をするときには、幾つか設定しないといけない事がありますが、AD9850のデータシートを見る限りでは、以下の様になってるみたいです。

・動作モード
 CLKの立ち上がりでデータをサンプリングするみたいです。又、通信していない時のCLKはLowなので、SPI_MODE0になります。

・データの送り方(BitOrder)
 BitOrderは、データの送る順番がw0(LSB)から順にw1、w2、…、w31(MSB)なので、LSBFIRSTです。

・SS(FQUP)の制御
 SPI通信では、先ず最初にSSを下げてから通信をしますが、どうも通信終わりのSS↑↓は自分でやらないといけないみたいです。

・AD9850のRESET信号
 RESETを最初に落とすことになりますが、このRESETは正論理(!)なので、Resetしたい時に0にします。最初負論理だとてっきり思っていて、動かずに困りました…

・送るデータですが、EF_AD9850に依れば、
//Calculate the frequency of the HEX value
x=4294967295/125;//Suitable for 125M Crystal
frequence=frequence/1000000;
frequence=frequence*x;
y=frequence;
らしいです。例えば40kHzであれば、0b00000000, 0b00010100, 0b11111000, 0b10110101になります。

最後のw32~39のControl Registerには、
bit[1:0] Control Serialならば00
bit2 Power Shutdown 0
bit[7:3] Phase
を書き込みます。


 ということで、ArduinoのSPIを使うように改造しました。一応クラスにしてますが、8bitレジスタ5個分を送るだけの簡単なプログラムです。
class AD9850{
 //7 reset
 //10 fqup
 //11 d7
 //13 wclk 

private:

public:
 AD9850(){};
 ~AD9850(){};

 //Initialize SPI & DDS(AD9850)
 void Init(){
  //set
  pinMode(7, OUTPUT);

  //Send Reset signal
  digitalWrite(7, 0);
  digitalWrite(7, 1);
  digitalWrite(7, 0);

  //Init SPI
  SPI.begin();
  SPI.setDataMode(SPI_MODE0);  //Idle : clk low, rising edge. 
  SPI.setBitOrder(LSBFIRST);
 };

 //freq : Frequency[Hz]
 //w0 : Control Register Value
 void SetFrequency(const unsigned char w0, const double freq){
  const double xtal_freq = 125;  //125MHz Xtal
  const double x = (4294967295 / xtal_freq)  / 1000000;
  long int y = (long int)(freq * x);
  
  SPI.transfer(y & 0xFF);
  SPI.transfer((y >> 8) & 0xFF);
  SPI.transfer((y >> 16) & 0xFF);
  SPI.transfer((y >> 24) & 0xFF);
  SPI.transfer(w0);  //Control Register
  //FQUP
  digitalWrite(10, 1);
  digitalWrite(10, 0);
 };
};
このプログラムを実機上で動かして、ロジック・アナライザで通信データを見てみたところ、下の写真のようになりました。
ロジアナで見たSPI通信

 SPI.transfer()を1byteごとに呼んで送信しているため、1byteごとに何も通信していない部分(A2のMOSIが1になっているところ)がありますが、CLKもLowのままでサンプリングされてないので問題無いと思っています。

 DigitalWrite()でSS(FQUP)を制御しているので、SPIの通信が終わってからSSが上がるまでに結構時間がかかっているみたいですが、まあ動いてるので大丈夫でしょう…

 使い方は、前のライブラリ(EF_AD9850)とほぼ一緒。

0 コメント to “[電子工作]aitendoのDDSモジュールを動かす その2”

コメントを投稿