中華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.