中華DDS AD9850のコントロール
なぜ、いまさらAD9850のクラスライブラリ ?
AnalogDevicesのAD9850を使った中華DDS基板が比較的安い価格で入手できるようになって久しい。
しかし、mbed LPC1768では SPIでトリッキーな操作することで40bitの出力ができるが、
mbed HRM1017等ではSPIの動作が違うためソフトウェアでシリアルデータを出力する必要があったのでそのメモ。

コードはpublishしていませんので、再利用する場合は下記の内容を自身でファイルにしてください。
ソースコードを公開しました。
なお、ソースコード内のwait/wait_ms関数を使って時間を待っている箇所がいくつかあるが、比較的余裕をもって値を設定しているので時間的には冗長であり、ライブラリのスループットが悪くなっているので利用する場合は最適化してください。
/users/ohneta/code/AD9850/
参考資料
AD9850データシート
http://www.analog.com/static/imported-files/data_sheets/AD9850.pdf
mbed LPC1768 SPIでの実装例
http://developer.mbed.org/users/liamg/code/AD9850-function-generator-SPI-driver/
AD9850.h
AD9850 class header
#include "mbed.h"
class AD9850 {
public:
AD9850(PinName data, PinName w_clk, PinName fu_ud, PinName reset);
~AD9850();
void init();
void reset();
void setFrequency(int freq, int pdwon = 0, int phase = 0);
private:
DigitalOut _outBit;
DigitalOut _w_clk;
DigitalOut _fu_ud;
DigitalOut _reset;
};
AD9850.cpp
AD9850 class
#include "AD9850.h"
#define AD9850_FREQ_CONST 34.359738368
/*
* AD9850/clock=125MHz
* 2の32乗=4294967296、DDSクロック==125MHzを前提とすると...
* 1Hz設定時の値 = 4294967296/125000000 = 34.359738368 となる
*/
//----------------------------------------------------------------
/**
* コンストラクタ
*
* @param PinName data データ転送ピン
* @param PinName w_clk クロックピン
* @param PinName fu_ud モジュール選択
* @param PinName reset リセット
*/
AD9850::AD9850(PinName data, PinName w_clk, PinName fu_ud, PinName reset)
: _outBit(data), _w_clk(w_clk), _fu_ud(fu_ud), _reset(reset)
{
init();
}
//----------------------------------------------------------------
/**
* デストラクタ
*/
AD9850::~AD9850()
{
}
//----------------------------------------------------------------
/**
* 初期化
*/
void AD9850::init()
{
reset();
}
//----------------------------------------------------------------
/**
* リセット
*/
void AD9850::reset()
{
_reset = 0; wait_ms(5);
_reset = 1; wait_ms(5);
_reset = 0; wait_ms(5);
}
//----------------------------------------------------------------
/**
* 周波数設定
*
* @param int freq 設定する周波数(Hz)
* AD9850ボードに依存するがクロック125MHzで概ね 1〜40000000(1Hz〜40MHz)程度まで安定して動作する模様
* @param int pdwon パワーダウンビット (W34)
* @param int phase コントロール/フェーズ等データ (W32〜W39)
*
* AD9850へ送信する40bit
* W0〜W31:
* freqにAD9850_FREQ_CONSTを乗算した32bit値
* W32, W33:
* コントロールビット。常に0
* W34:
* 1でパワーダウン(通常は0)
* W35〜W39:
* 位相オフセット調整値 (11.25度単位)
*/
void AD9850::setFrequency(int freq, int pdwon, int phase)
{
int freqParam = (int)((double)freq * AD9850_FREQ_CONST); // 周波数に対応した32bitデータ(W0〜W31)
_w_clk = 0;
_fu_ud = 0; wait_ms(5);
_fu_ud = 1; wait_ms(5);
_fu_ud = 0;
for (int i = 0; i < 32; i++) {
int bit = ((freqParam >> i) & 0x01); // LSBから送信
_w_clk = 0;
_outBit = bit;
wait_ms(0.1);
_w_clk = 1; wait_ms(2);
_w_clk = 0; wait_ms(2);
}
for (int i = 0; i < 8; i++) {
int bit = ((phase >> (7 - i)) & 0x01);
_w_clk = 0;
_outBit = bit;
wait_ms(0.1);
_w_clk = 1; wait_ms(2);
_w_clk = 0; wait_ms(2);
}
_fu_ud = 0; wait_ms(5);
_fu_ud = 1; wait_ms(5);
_fu_ud = 0;
}
sample main.cpp
main.cpp
#include "AD9850.h"
// mbed HRM1017の場合
AD9850 dds(P0_20, P0_25, P0_24, P0_23);
int main()
{
int frq = 10 * 1000 * 1000; // 10MHz
dds.setFrequency(frq, 0, 0);
while(1) {
//
}
}
Please log in to post comments.
