找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 4220|回复: 1
收起左侧

用Arduino操纵AD9834模块的源码分享

[复制链接]
ID:423060 发表于 2018-11-8 15:57 | 显示全部楼层 |阅读模式
AD9834是使用spi通信连接来操作的信号发生模块
直接上传
example中的第二个ino,直接运行,亲测有效
程序写的非常顾名思义,函数名称就是字面含义

单片机源程序如下:
  1. /*
  2. * AD9833.cpp
  3. *
  4. * Copyright 2016 Bill Williams <wlwilliams1952@gmail.com, github/BillWilliams1952>
  5. *
  6. * Thanks to john@vwlowen co uk for his work on the AD9833. His web page
  7. *
  8. * This program is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; either version 2 of the License, or
  11. * (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, write to the Free Software
  20. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
  21. * MA 02110-1301, USA.
  22. *
  23. */

  24. #include "AD9833.h"

  25. /*
  26. * Create an AD9833 object
  27. */
  28. AD9833 :: AD9833 ( uint8_t FNCpin, uint32_t referenceFrequency ) {
  29.         // Pin used to enable SPI communication (active LOW)
  30. #ifdef FNC_PIN
  31.         pinMode(FNC_PIN,OUTPUT);
  32. #else
  33.         this->FNCpin = FNCpin;
  34.         pinMode(FNCpin,OUTPUT);
  35. #endif
  36.         WRITE_FNCPIN(HIGH);

  37.         /* TODO: The minimum resolution and max frequency are determined by
  38.          * by referenceFrequency. We should calculate these values and use
  39.          * them during setFrequency. The problem is if the user programs a
  40.          * square wave at refFrequency/2, then changes the waveform to sine.
  41.          * The sine wave will not have enough points?
  42.          */
  43.         refFrequency = referenceFrequency;
  44.        
  45.         // Setup some defaults
  46.         DacDisabled = false;
  47.         IntClkDisabled = false;
  48.         outputEnabled = false;
  49.         waveForm0 = waveForm1 = SINE_WAVE;
  50.         frequency0 = frequency1 = 1000;                // 1 KHz sine wave to start
  51.         phase0 = phase1 = 0.0;                                // 0 phase
  52.         activeFreq = REG0; activePhase = REG0;
  53. }

  54. /*
  55. * This MUST be the first command after declaring the AD9833 object
  56. * Start SPI and place the AD9833 in the RESET state
  57. */
  58. void AD9833 :: Begin ( void ) {
  59.         SPI.begin();
  60.         delay(100);
  61.         Reset();        // Hold in RESET until first WriteRegister command
  62. }

  63. /*
  64. * Setup and apply a signal. phaseInDeg defaults to 0.0 if not supplied.
  65. * phaseReg defaults to value of freqReg if not supplied.
  66. * Note that any previous calls to EnableOut,
  67. * SleepMode, DisableDAC, or DisableInternalClock remain in effect.
  68. */
  69. void AD9833 :: ApplySignal ( WaveformType waveType,
  70.                 Registers freqReg, float frequencyInHz,
  71.                 Registers phaseReg, float phaseInDeg ) {
  72.         SetFrequency ( freqReg, frequencyInHz );
  73.         SetPhase ( phaseReg, phaseInDeg );
  74.         SetWaveform ( freqReg, waveType );
  75.         SetOutputSource ( freqReg, phaseReg );
  76. }

  77. /***********************************************************************
  78.                                                 Control Register
  79. ------------------------------------------------------------------------
  80. D15,D14(MSB)        10 = FREQ1 write, 01 = FREQ0 write,
  81.                                 11 = PHASE write, 00 = control write
  82. D13        If D15,D14 = 00, 0 = individual LSB and MSB FREQ write,
  83.                                          1 = both LSB and MSB FREQ writes consecutively
  84.         If D15,D14 = 11, 0 = PHASE0 write, 1 = PHASE1 write
  85. D12        0 = writing LSB independently
  86.         1 = writing MSB independently
  87. D11        0 = output FREQ0,
  88.         1 = output FREQ1
  89. D10        0 = output PHASE0
  90.         1 = output PHASE1
  91. D9        Reserved. Must be 0.
  92. D8        0 = RESET disabled
  93.         1 = RESET enabled
  94. D7        0 = internal clock is enabled
  95.         1 = internal clock is disabled
  96. D6        0 = onboard DAC is active for sine and triangle wave output,
  97.         1 = put DAC to sleep for square wave output
  98. D5        0 = output depends on D1
  99.         1 = output is a square wave
  100. D4        Reserved. Must be 0.
  101. D3        0 = square wave of half frequency output
  102.         1 = square wave output
  103. D2        Reserved. Must be 0.
  104. D1        If D5 = 1, D1 = 0.
  105.         Otherwise 0 = sine output, 1 = triangle output
  106. D0        Reserved. Must be 0.
  107. ***********************************************************************/

  108. /*
  109. * Hold the AD9833 in RESET state.
  110. * Resets internal registers to 0, which corresponds to an output of
  111. * midscale - digital output at 0.
  112. *
  113. * The difference between Reset() and EnableOutput(false) is that
  114. * EnableOutput(false) keeps the AD9833 in the RESET state until you
  115. * specifically remove the RESET state using EnableOutput(true).
  116. * With a call to Reset(), ANY subsequent call to ANY function (other
  117. * than Reset itself and Set/IncrementPhase) will also remove the RESET
  118. * state.
  119. */
  120. void AD9833 :: Reset ( void ) {
  121.         WriteRegister(RESET_CMD);
  122.         delay(15);
  123. }

  124. /*
  125. *  Set the specified frequency register with the frequency (in Hz)
  126. */
  127. void AD9833 :: SetFrequency ( Registers freqReg, float frequency ) {
  128.         // TODO: calculate max frequency based on refFrequency.
  129.         // Use the calculations for sanity checks on numbers.
  130.         // Sanity check on frequency: Square - refFrequency / 2
  131.         //                                                          Sine/Triangle - refFrequency / 4
  132.         if ( frequency > 12.5e6 )        // TODO: Fix this based on refFreq
  133.                 frequency = 12.5e6;
  134.         if ( frequency < 0.0 ) frequency = 0.0;
  135.        
  136.         // Save frequency for use by IncrementFrequency function
  137.         if ( freqReg == REG0 ) frequency0 = frequency;
  138.         else frequency1 = frequency;
  139.        
  140.         int32_t freqWord = (frequency * pow2_28) / (float)refFrequency;
  141.         int16_t upper14 = (int16_t)((freqWord & 0xFFFC000) >> 14),
  142.                         lower14 = (int16_t)(freqWord & 0x3FFF);

  143.         // Which frequency register are we updating?
  144.         uint16_t reg = freqReg == REG0 ? FREQ0_WRITE_REG : FREQ1_WRITE_REG;
  145.         lower14 |= reg;
  146.         upper14 |= reg;   

  147.         // I do not reset the registers during write. It seems to remove
  148.         // 'glitching' on the outputs.
  149.         WriteControlRegister();
  150.         // Control register has already been setup to accept two frequency
  151.         // writes, one for each 14 bit part of the 28 bit frequency word
  152.         WriteRegister(lower14);                        // Write lower 14 bits to AD9833
  153.         WriteRegister(upper14);                        // Write upper 14 bits to AD9833
  154. }

  155. /*
  156. * Increment the specified frequency register with the frequency (in Hz)
  157. */
  158. void AD9833 :: IncrementFrequency ( Registers freqReg, float freqIncHz ) {
  159.         // Add/subtract a value from the current frequency programmed in
  160.         // freqReg by the amount given
  161.         float frequency = (freqReg == REG0) ? frequency0 : frequency1;
  162.         SetFrequency(freqReg,frequency+freqIncHz);
  163. }

  164. /*
  165. * Set the specified phase register with the phase (in degrees)
  166. * The output signal will be phase shifted by 2π/4096 x PHASEREG
  167. */
  168. void AD9833 :: SetPhase ( Registers phaseReg, float phaseInDeg ) {
  169.         // Sanity checks on input
  170.         phaseInDeg = fmod(phaseInDeg,360);
  171.         if ( phaseInDeg < 0 ) phaseInDeg += 360;
  172.        
  173.         // Phase is in float degrees ( 0.0 - 360.0 )
  174.         // Convert to a number 0 to 4096 where 4096 = 0 by masking
  175.         uint16_t phaseVal = (uint16_t)(BITS_PER_DEG * phaseInDeg) & 0x0FFF;
  176.         phaseVal |= PHASE_WRITE_CMD;
  177.        
  178.         // Save phase for use by IncrementPhase function
  179.         if ( phaseReg == REG0 )        {
  180.                 phase0 = phaseInDeg;
  181.         }
  182.         else {
  183.                 phase1 = phaseInDeg;
  184.                 phaseVal |= PHASE1_WRITE_REG;
  185.         }
  186.         WriteRegister(phaseVal);
  187. }

  188. /*
  189. * Increment the specified phase register by the phase (in degrees)
  190. */
  191. void AD9833 :: IncrementPhase ( Registers phaseReg, float phaseIncDeg ) {
  192.         // Add/subtract a value from the current phase programmed in
  193.         // phaseReg by the amount given
  194.         float phase = (phaseReg == REG0) ? phase0 : phase1;
  195.         SetPhase(phaseReg,phase + phaseIncDeg);
  196. }

  197. /*
  198. * Set the type of waveform that is output for a frequency register
  199. * SINE_WAVE, TRIANGLE_WAVE, SQUARE_WAVE, HALF_SQUARE_WAVE
  200. */
  201. void AD9833 :: SetWaveform (  Registers waveFormReg, WaveformType waveType ) {
  202.         // TODO: Add more error checking?
  203.         if ( waveFormReg == REG0 )
  204.                 waveForm0 = waveType;
  205.         else
  206.                 waveForm1 = waveType;
  207.         WriteControlRegister();
  208. }

  209. /*
  210. * EnableOutput(false) keeps the AD9833 is RESET state until a call to
  211. * EnableOutput(true). See the Reset function description.
  212. */
  213. void AD9833 :: EnableOutput ( bool enable ) {
  214.         outputEnabled = enable;
  215.         WriteControlRegister();
  216. }

  217. /*
  218. * Set which frequency and phase register is being used to output the
  219. * waveform. If phaseReg is not supplied, it defaults to the same
  220. * register as freqReg.
  221. */
  222. void AD9833 :: SetOutputSource ( Registers freqReg, Registers phaseReg ) {
  223.         // TODO: Add more error checking?
  224.         activeFreq = freqReg;
  225.         if ( phaseReg == SAME_AS_REG0 )        activePhase = activeFreq;
  226.         else activePhase = phaseReg;
  227.         WriteControlRegister();
  228. }

  229. //---------- LOWER LEVEL FUNCTIONS NOT NORMALLY NEEDED -------------

  230. /*
  231. * Disable/enable both the internal clock and the DAC. Note that square
  232. * wave outputs are avaiable if using an external Reference.
  233. * TODO: ?? IS THIS TRUE ??
  234. */
  235. void AD9833 :: SleepMode ( bool enable ) {
  236.         DacDisabled = enable;
  237.         IntClkDisabled = enable;
  238.         WriteControlRegister();
  239. }

  240. /*
  241. * Enables / disables the DAC. It will override any previous DAC
  242. * setting by Waveform type, or via the SleepMode function
  243. */
  244. void AD9833 :: DisableDAC ( bool enable ) {
  245.         DacDisabled = enable;
  246.         WriteControlRegister();       
  247. }

  248. /*
  249. * Enables / disables the internal clock. It will override any
  250. * previous clock setting by the SleepMode function
  251. */
  252. void AD9833 :: DisableInternalClock ( bool enable ) {
  253.         IntClkDisabled = enable;
  254.         WriteControlRegister();       
  255. }

  256. // ------------ STATUS / INFORMATION FUNCTIONS -------------------
  257. /*
  258. * Return actual frequency programmed
  259. */
  260. float AD9833 :: GetActualProgrammedFrequency ( Registers reg ) {
  261.         float frequency = reg == REG0 ? frequency0 : frequency1;
  262.         int32_t freqWord = (uint32_t)((frequency * pow2_28) / (float)refFrequency) & 0x0FFFFFFFUL;
  263.         return (float)freqWord * (float)refFrequency / (float)pow2_28;
  264. }

  265. /*
  266. * Return actual phase programmed
  267. */
  268. float AD9833 :: GetActualProgrammedPhase ( Registers reg ) {
  269.         float phase = reg == REG0 ? phase0 : phase1;
  270.         uint16_t phaseVal = (uint16_t)(BITS_PER_DEG * phase) & 0x0FFF;
  271.         return (float)phaseVal / BITS_PER_DEG;
  272. }

  273. /*
  274. * Return frequency resolution
  275. */
  276. float AD9833 :: GetResolution ( void ) {
  277.         return (float)refFrequency / (float)pow2_28;
  278. }

  279. // --------------------- PRIVATE FUNCTIONS --------------------------

  280. /*
  281. * Write control register. Setup register based on defined states
  282. */
  283. void AD9833 :: WriteControlRegister ( void ) {
  284.         uint16_t waveForm;
  285.         // TODO: can speed things up by keeping a writeReg0 and writeReg1
  286.         // that presets all bits during the various setup function calls
  287.         // rather than setting flags. Then we could just call WriteRegister
  288.         // directly.
  289.         if ( activeFreq == REG0 ) {
  290.                 waveForm = waveForm0;
  291.                 waveForm &= ~FREQ1_OUTPUT_REG;
  292.         }
  293.         else {
  294.                 waveForm = waveForm1;
  295.                 waveForm |= FREQ1_OUTPUT_REG;
  296.         }
  297.         if ( activePhase == REG0 )
  298.                 waveForm &= ~PHASE1_OUTPUT_REG;
  299.         else
  300.                 waveForm |= PHASE1_OUTPUT_REG;
  301.         if ( outputEnabled )
  302.                 waveForm &= ~RESET_CMD;
  303.         else
  304.                 waveForm |= RESET_CMD;
  305.         if ( DacDisabled )
  306.                 waveForm |= DISABLE_DAC;
  307.         else
  308.                 waveForm &= ~DISABLE_DAC;
  309.         if ( IntClkDisabled )
  310.                 waveForm |= DISABLE_INT_CLK;
  311.         else
  312.                 waveForm &= ~DISABLE_INT_CLK;

  313.         WriteRegister ( waveForm );
  314. }

  315. void AD9833 :: WriteRegister ( int16_t dat ) {
  316.         /*
  317.          * We set the mode here, because other hardware may be doing SPI also
  318.          */
  319.         SPI.setDataMode(SPI_MODE2);

  320.         /* Improve overall switching speed
  321.          * Note, the times are for this function call, not the write.
  322.          * digitalWrite(FNCpin)                        ~ 17.6 usec
  323.          * digitalWriteFast2(FNC_PIN)        ~  8.8 usec
  324.          */
  325.         WRITE_FNCPIN(LOW);                // FNCpin low to write to AD9833

  326.         //delayMicroseconds(2);        // Some delay may be needed

  327.         // TODO: Are we running at the highest clock rate?
  328.         SPI.transfer(highByte(dat));        // Transmit 16 bits 8 bits at a time
  329.         SPI.transfer(lowByte(dat));

  330.         WRITE_FNCPIN(HIGH);                // Write done
  331. }
复制代码

所有资料51hei提供下载:
AD9833-Library-Arduino-master.rar (15.59 KB, 下载次数: 47)

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

ID:821002 发表于 2021-7-28 16:35 | 显示全部楼层
ad9833?  ad9834?
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表