中華DDS AD9850のコントロール

なぜ、いまさらAD9850のクラスライブラリ ?

AnalogDevicesのAD9850を使った中華DDS基板が比較的安い価格で入手できるようになって久しい。
しかし、mbed LPC1768では SPIでトリッキーな操作することで40bitの出力ができるが、 mbed HRM1017等ではSPIの動作が違うためソフトウェアでシリアルデータを出力する必要があったのでそのメモ。 /media/uploads/ohneta/img_4426_tochIV1.jpg

コードは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.