bit-banging control for AD9850.
こちらのnoteに書いてます。
/users/ohneta/notebook/DDS-AS9850_softSPI/
AD9850.cpp@0:25d6d7c1a48a, 2015-06-18 (annotated)
- Committer:
- ohneta
- Date:
- Thu Jun 18 05:23:11 2015 +0000
- Revision:
- 0:25d6d7c1a48a
1st commit
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
ohneta | 0:25d6d7c1a48a | 1 | //---------------------------------------------------------------- |
ohneta | 0:25d6d7c1a48a | 2 | /** |
ohneta | 0:25d6d7c1a48a | 3 | * 中華DDS AD9850のコントロール |
ohneta | 0:25d6d7c1a48a | 4 | * |
ohneta | 0:25d6d7c1a48a | 5 | * mbed LPC1768では SPIを操作することで40bitの出力ができるが、 |
ohneta | 0:25d6d7c1a48a | 6 | * mbed HRM1017等ではSPIの動作が違うためソフトウェアでシリアルデータを出力する |
ohneta | 0:25d6d7c1a48a | 7 | * |
ohneta | 0:25d6d7c1a48a | 8 | * 参考資料 |
ohneta | 0:25d6d7c1a48a | 9 | * AD9850データシート |
ohneta | 0:25d6d7c1a48a | 10 | * http://www.analog.com/static/imported-files/data_sheets/AD9850.pdf |
ohneta | 0:25d6d7c1a48a | 11 | * mbed LPC1768 SPIでの実装例 |
ohneta | 0:25d6d7c1a48a | 12 | * http://developer.mbed.org/users/liamg/code/AD9850-function-generator-SPI-driver/ |
ohneta | 0:25d6d7c1a48a | 13 | */ |
ohneta | 0:25d6d7c1a48a | 14 | //---------------------------------------------------------------- |
ohneta | 0:25d6d7c1a48a | 15 | |
ohneta | 0:25d6d7c1a48a | 16 | #include "AD9850.h" |
ohneta | 0:25d6d7c1a48a | 17 | |
ohneta | 0:25d6d7c1a48a | 18 | #define AD9850_FREQ_CONST 34.359738368 |
ohneta | 0:25d6d7c1a48a | 19 | /* |
ohneta | 0:25d6d7c1a48a | 20 | * AD9850/clock=125MHz |
ohneta | 0:25d6d7c1a48a | 21 | * 2の32乗=4294967296、DDSクロック==125MHzを前提とすると... |
ohneta | 0:25d6d7c1a48a | 22 | * 1Hz設定時の値 = 4294967296/125000000 = 34.359738368 となる |
ohneta | 0:25d6d7c1a48a | 23 | */ |
ohneta | 0:25d6d7c1a48a | 24 | |
ohneta | 0:25d6d7c1a48a | 25 | //---------------------------------------------------------------- |
ohneta | 0:25d6d7c1a48a | 26 | /** |
ohneta | 0:25d6d7c1a48a | 27 | * コンストラクタ |
ohneta | 0:25d6d7c1a48a | 28 | * |
ohneta | 0:25d6d7c1a48a | 29 | * @param PinName data データ転送ピン |
ohneta | 0:25d6d7c1a48a | 30 | * @param PinName w_clk クロックピン |
ohneta | 0:25d6d7c1a48a | 31 | * @param PinName fu_ud モジュール選択 |
ohneta | 0:25d6d7c1a48a | 32 | * @param PinName reset リセット |
ohneta | 0:25d6d7c1a48a | 33 | */ |
ohneta | 0:25d6d7c1a48a | 34 | AD9850::AD9850(PinName data, PinName w_clk, PinName fu_ud, PinName reset) |
ohneta | 0:25d6d7c1a48a | 35 | : _outBit(data), _w_clk(w_clk), _fu_ud(fu_ud), _reset(reset) |
ohneta | 0:25d6d7c1a48a | 36 | { |
ohneta | 0:25d6d7c1a48a | 37 | init(); |
ohneta | 0:25d6d7c1a48a | 38 | } |
ohneta | 0:25d6d7c1a48a | 39 | |
ohneta | 0:25d6d7c1a48a | 40 | //---------------------------------------------------------------- |
ohneta | 0:25d6d7c1a48a | 41 | /** |
ohneta | 0:25d6d7c1a48a | 42 | * デストラクタ |
ohneta | 0:25d6d7c1a48a | 43 | */ |
ohneta | 0:25d6d7c1a48a | 44 | AD9850::~AD9850() |
ohneta | 0:25d6d7c1a48a | 45 | { |
ohneta | 0:25d6d7c1a48a | 46 | } |
ohneta | 0:25d6d7c1a48a | 47 | |
ohneta | 0:25d6d7c1a48a | 48 | //---------------------------------------------------------------- |
ohneta | 0:25d6d7c1a48a | 49 | /** |
ohneta | 0:25d6d7c1a48a | 50 | * 初期化 |
ohneta | 0:25d6d7c1a48a | 51 | */ |
ohneta | 0:25d6d7c1a48a | 52 | void AD9850::init() |
ohneta | 0:25d6d7c1a48a | 53 | { |
ohneta | 0:25d6d7c1a48a | 54 | reset(); |
ohneta | 0:25d6d7c1a48a | 55 | } |
ohneta | 0:25d6d7c1a48a | 56 | |
ohneta | 0:25d6d7c1a48a | 57 | //---------------------------------------------------------------- |
ohneta | 0:25d6d7c1a48a | 58 | /** |
ohneta | 0:25d6d7c1a48a | 59 | * リセット |
ohneta | 0:25d6d7c1a48a | 60 | */ |
ohneta | 0:25d6d7c1a48a | 61 | void AD9850::reset() |
ohneta | 0:25d6d7c1a48a | 62 | { |
ohneta | 0:25d6d7c1a48a | 63 | _reset = 0; wait_ms(5); |
ohneta | 0:25d6d7c1a48a | 64 | _reset = 1; wait_ms(5); |
ohneta | 0:25d6d7c1a48a | 65 | _reset = 0; wait_ms(5); |
ohneta | 0:25d6d7c1a48a | 66 | } |
ohneta | 0:25d6d7c1a48a | 67 | |
ohneta | 0:25d6d7c1a48a | 68 | //---------------------------------------------------------------- |
ohneta | 0:25d6d7c1a48a | 69 | /** |
ohneta | 0:25d6d7c1a48a | 70 | * 周波数設定 |
ohneta | 0:25d6d7c1a48a | 71 | * |
ohneta | 0:25d6d7c1a48a | 72 | * @param int freq 設定する周波数(Hz) |
ohneta | 0:25d6d7c1a48a | 73 | * AD9850ボードに依存するがクロック125MHzで概ね 1〜40000000(1Hz〜40MHz)程度まで安定して動作する模様 |
ohneta | 0:25d6d7c1a48a | 74 | * @param int pdwon パワーダウンビット (W34) |
ohneta | 0:25d6d7c1a48a | 75 | * @param int phase コントロール/フェーズ等データ (W32〜W39) |
ohneta | 0:25d6d7c1a48a | 76 | * |
ohneta | 0:25d6d7c1a48a | 77 | * AD9850へ送信する40bit |
ohneta | 0:25d6d7c1a48a | 78 | * W0〜W31: |
ohneta | 0:25d6d7c1a48a | 79 | * freqにAD9850_FREQ_CONSTを乗算した32bit値 |
ohneta | 0:25d6d7c1a48a | 80 | * W32, W33: |
ohneta | 0:25d6d7c1a48a | 81 | * コントロールビット。常に0 |
ohneta | 0:25d6d7c1a48a | 82 | * W34: |
ohneta | 0:25d6d7c1a48a | 83 | * 1でパワーダウン(通常は0) |
ohneta | 0:25d6d7c1a48a | 84 | * W35〜W39: |
ohneta | 0:25d6d7c1a48a | 85 | * 位相オフセット調整値 (11.25度単位) |
ohneta | 0:25d6d7c1a48a | 86 | */ |
ohneta | 0:25d6d7c1a48a | 87 | void AD9850::setFrequency(int freq, int pdwon, int phase) |
ohneta | 0:25d6d7c1a48a | 88 | { |
ohneta | 0:25d6d7c1a48a | 89 | int freqParam = (int)((double)freq * AD9850_FREQ_CONST); // 周波数に対応した32bitデータ(W0〜W31) |
ohneta | 0:25d6d7c1a48a | 90 | |
ohneta | 0:25d6d7c1a48a | 91 | _w_clk = 0; |
ohneta | 0:25d6d7c1a48a | 92 | _fu_ud = 0; wait_ms(5); |
ohneta | 0:25d6d7c1a48a | 93 | _fu_ud = 1; wait_ms(5); |
ohneta | 0:25d6d7c1a48a | 94 | _fu_ud = 0; |
ohneta | 0:25d6d7c1a48a | 95 | |
ohneta | 0:25d6d7c1a48a | 96 | for (int i = 0; i < 32; i++) { |
ohneta | 0:25d6d7c1a48a | 97 | int bit = ((freqParam >> i) & 0x01); // LSBから送信 |
ohneta | 0:25d6d7c1a48a | 98 | _w_clk = 0; |
ohneta | 0:25d6d7c1a48a | 99 | _outBit = bit; |
ohneta | 0:25d6d7c1a48a | 100 | wait_ms(0.1); |
ohneta | 0:25d6d7c1a48a | 101 | _w_clk = 1; wait_ms(2); |
ohneta | 0:25d6d7c1a48a | 102 | _w_clk = 0; wait_ms(2); |
ohneta | 0:25d6d7c1a48a | 103 | } |
ohneta | 0:25d6d7c1a48a | 104 | |
ohneta | 0:25d6d7c1a48a | 105 | for (int i = 0; i < 8; i++) { |
ohneta | 0:25d6d7c1a48a | 106 | int bit = ((phase >> (7 - i)) & 0x01); |
ohneta | 0:25d6d7c1a48a | 107 | _w_clk = 0; |
ohneta | 0:25d6d7c1a48a | 108 | _outBit = bit; |
ohneta | 0:25d6d7c1a48a | 109 | wait_ms(0.1); |
ohneta | 0:25d6d7c1a48a | 110 | _w_clk = 1; wait_ms(2); |
ohneta | 0:25d6d7c1a48a | 111 | _w_clk = 0; wait_ms(2); |
ohneta | 0:25d6d7c1a48a | 112 | } |
ohneta | 0:25d6d7c1a48a | 113 | |
ohneta | 0:25d6d7c1a48a | 114 | _fu_ud = 0; wait_ms(5); |
ohneta | 0:25d6d7c1a48a | 115 | _fu_ud = 1; wait_ms(5); |
ohneta | 0:25d6d7c1a48a | 116 | _fu_ud = 0; |
ohneta | 0:25d6d7c1a48a | 117 | } |
ohneta | 0:25d6d7c1a48a | 118 | |
ohneta | 0:25d6d7c1a48a | 119 | //---------------------------------------------------------------- |
ohneta | 0:25d6d7c1a48a | 120 | /* |
ohneta | 0:25d6d7c1a48a | 121 | |
ohneta | 0:25d6d7c1a48a | 122 | // mbed HRM1017の場合 |
ohneta | 0:25d6d7c1a48a | 123 | AD9850 dds(P0_20, P0_25, P0_24, P0_23); |
ohneta | 0:25d6d7c1a48a | 124 | |
ohneta | 0:25d6d7c1a48a | 125 | int main() |
ohneta | 0:25d6d7c1a48a | 126 | { |
ohneta | 0:25d6d7c1a48a | 127 | int frq = 10 * 1000 * 1000; // 10MHz |
ohneta | 0:25d6d7c1a48a | 128 | int phase = 0; |
ohneta | 0:25d6d7c1a48a | 129 | |
ohneta | 0:25d6d7c1a48a | 130 | dds.setFrequency(frq, phase); |
ohneta | 0:25d6d7c1a48a | 131 | while(1) { |
ohneta | 0:25d6d7c1a48a | 132 | // |
ohneta | 0:25d6d7c1a48a | 133 | } |
ohneta | 0:25d6d7c1a48a | 134 | } |
ohneta | 0:25d6d7c1a48a | 135 | */ |