成为订阅者(免费)

加入29,000名其他订阅者以获得用户销售折扣和 其他免费资源。
:
:
大学教师'担心 - 您的邮件地址完全是 安全的。我保证使用它 只要 to send you MicroZine.

AD9833 DDS信号发生器

AD9833是一种直接数字合成器,可以生成正弦, 方形或三角形波并使用SPI协议控制。

几年前,你现在必须为DDS支付很多钱 你可以获得10美元!令人惊叹 - 这件事情可以在 0.1Hz分辨率,高达12.5MHz。

笔记: 如果您想复杂,您可以使其执行FSK,GMSK和QPSK等编码方案。在这里,我们''LL只是保持简单!

由于设备位于MSOP包中,最简单的使用方法是通过 让自己成为一个突破板。你可以买两种类型,一个配有opamp 缓冲芯片和数字衰减器,用于调整输出电平。

AD9833突破板

AD9833突破模块

右手侧输出直接来自DDS(标记为VOUT) 虽然左侧的输出通过锅和 放大器(标记为PGA)。

AD9833

AD9833规范

  Parameter
AD9833
  Voltage Supply (Vs)
 2V3 ~ 5V5
  Abs. Max V DD.
-0v3〜6v0.
  Output (Vpp)
600mV
  Outputs
广场,正弦,三角形。
  Max output frequency
12.5MHz.
  Resolution
0.1Hz
  Interface
spi.
  SPI rate (MHz)
25
  主动电流(典型,最大)
4.5mA / 5.5mA
  Standby mode
500uA
  Resolution
10bit
  INL(积分非线性) ±1.0LSB.
  DNL(差分非线性) ±0.5LSB.
  工作温度
-40°C〜105°C

AD9833数据表

这是直接数字合成芯片 数据表 (点击在新窗口中打开)。

AD9833突破板

需要opamp的原因是输出 AD9833约为600mV。 opamp通过5放大信号以提供3V 输出。使用数字锅允许您将此输出减少到 level you need.

框图

AD9833框图
上图中的一个有趣的点是有两个 频率寄存器FREQ0和FREQ1,您可以在它们之间进行选择 使用mux。这意味着频移键盘很容易即更改 两个存储频率之间的频率而不重新加载频率 注册,所以它很快。相同的阶段也是如此。

突发板组件

突破板似乎没有可用的原理图 很容易遵循电路板痕迹。董事会的组件是:

零件
描述
AD9833 
 DDS chip
MCP41010  数字电位计
H2A
 AD8051 (see below)

难以识别的组件是标记的H2A 在SOT23-5包上。这是配置为一个输出缓冲区 反相运算放大器,可能是AD8051 - 速度非常高(300MHz 3DB带宽)轨到轨道Opamp。

提示: 您可以在此处找到SMD芯片标记: http://www.smdmark.com

 

以下是模块示意图:

AD9833框图[Source:(//www.handsontec.com/dataspecs/module/Module%20Collection.pdf).]

突发模块连接器

模块PIN.
描述
CS
spi. 芯片选择到MCP41010
日子
spi. MOSI到AD9833和MCP41010
CLK.
spi. 时钟到AD9833和MCP41010
FSY.
spi. 芯片选择AD9833
GND.
0V
vcc.
3V〜5V.

arduino. 图书馆

您可以找到图书馆安装详细信息 这里 .

ad9833的图书馆

安装名为的库 md_ad9833.

使用库管理器,搜索 AD9833.

图书馆为MCP41010

安装名为的库 ardumax mcp41xxx.

使用库管理器,搜索 MCP41.

电路连接

对于AD9833,从Arduino Uno进行以下连接到突破板:

日子 11 /// SPI数据引脚数
CLK. 13 /// SPI时钟PIN码
FST 10 ///芯片选择(在AD9833使用中的FSYNC)

此外,对于MCP41010进行以下连接:

CS           9 ///芯片选择 for MCP41010

AD9833草图

以下草图允许您通过将命令输入串行来测试AD9833 monitor.

AD9833测试

有关帮助类型'?'进入Arduino串行监视器中的发送框。

键入以下命令将1kHz波形输出到VOUT

:F11000;
:OST; //三角波
:OSS; //正弦波
:OSQ; // 方波

现在输出10MHz波形
:F110000000; // 10MHz.

#include <SPI.h>
#include <MD_AD9833.h>

// Pins for SPI comm with the AD9833 IC
#define DATA  11	   ///< SPI Data pin number
#define CLK   13	   ///< SPI Clock pin number
#define FSYNC 10	   ///< SPI Load pin number (FSYNC in AD9833 usage)
#define CS_DIGIPOT 9 // MCP41010 chip select - digital potentiometer.

 md_ad9833. 	AD( FSY. NC); // Hardware SPI
//MD_AD9833	AD(DATA, CLK, FSYNC); // Arbitrary SPI pins

// Character constants for commands
const char CMD_HELP = '?';
const char BLANK = ' ';
const char PACKET_START = ':';
const char PACKET_END = ';';
const char CMD_FREQ = 'F';
const char CMD_PHASE = 'P';
const char CMD_OUTPUT = 'O';
const char OPT_FREQ = 'F';
const char OPT_PHASE = 'P';
const char OPT_SIGNAL = 'S';
const char OPT_1 = '1';
const char OPT_2 = '2';
const char OPT_MODULATE = 'M';
const uint8_t PACKET_SIZE = 20;

void setup()
{
  pinMode(  CS  _DIGIPOT,OUTPUT);

  Serial.begin(57600);
  AD.begin();
  usage();

  // take the CS pin low to select the chip:
  digitalWrite(  CS  _DIGIPOT,LOW);
  //  send in the address and value via SPI:
   spi. .transfer(B00010001);
  // write out the value
   spi. .transfer(127);
  // take the CS pin high to de-select the chip:
  digitalWrite(  CS  _DIGIPOT,HIGH);
}

void usage(void)
{
  Serial.print(F("\n\n[MD_AD9833_Tester]"));
  Serial.print(F("\n?\thelp - this message"));
  Serial.print(F("\n\n:<cmd><opt> <param>;"));
  Serial.print(F("\n:f1n;\tset frequency 1 to n Hz"));
  Serial.print(F("\n:f2n;\tset frequency 2 to n Hz"));
  Serial.print(F("\n:fmn;\tset frequency modulation to n Hz"));
  Serial.print(F("\n:p1n;\tset phase 1 to n in tenths of a degree (1201 is 120.1 deg)"));
  Serial.print(F("\n:p2n;\tset phase 2 to n in tenths of a degree (1201 is 120.1 deg)"));
  Serial.print(F("\n:ofn;\toutput frequency n or modulation [n=1/2/m]"));
  Serial.print(F("\n:opn;\toutput phase n or modulation [n=1/2/m]"));
  Serial.print(F("\n:osn;\toutput signal type n [n=(o)ff/(s)ine/(t)riangle/s(q)uare]"));
}

uint8_t htoi(char c)
{
  c = toupper(c);

  if (c >= '0' && c <= '9')
      return(c - '0');
  else if (c >= 'A' && c <= 'F')
      return(c - 'A' + 10);
  else
      return(0);
}

char nextChar(void)
// Read the next character from the serial input stream
// Blocking wait
{
  while (!Serial.available())
    ; /* do nothing */
  return(toupper(Serial.read()));
}

char *readPacket(void)
// read a packet and return the
{
  static enum { S_IDLE, S_READ_CMD, S_READ_MOD, S_READ_PKT } state = S_IDLE;
  static char cBuf[PACKET_SIZE + 1];
  static char *cp;
  char c;

  switch (state)
  {
  case S_IDLE:   // waiting for packet start
    c = nextChar();
    if (c == CMD_HELP)
    {
      usage();
      break;
    }
    if (c == PACKET_START)
    {
      cp = cBuf;
      state = S_READ_CMD;
    }
    break;

  case S_READ_CMD:   // waiting for command char
    c = nextChar();
    if (c == CMD_FREQ || c == CMD_PHASE || c == CMD_OUTPUT)
    {
      *cp++ = c;
      state = S_READ_MOD;
    }
    else
      state = S_IDLE;
    break;

  case S_READ_MOD: // Waiting for command modifier
    c = nextChar();
    if (c == OPT_FREQ || c == OPT_PHASE || c == OPT_SIGNAL ||
      c == OPT_1 || c == OPT_2 || c == OPT_MODULATE)
    {
      *cp++ = c;
      state = S_READ_PKT;
    }
    else
      state = S_IDLE;
    break;

  case S_READ_PKT: // Reading parameter until packet end
    c = nextChar();
    if (c == PACKET_END)
    {
      *cp = '\0';
      state = S_IDLE;
      return(cBuf);
    }
    *cp++ = c;
    break;

  default:
    state = S_IDLE;
    break;
  }

  return(NULL);
}

void processPacket(char *cp)
// Assume we have a correctly formed packet from the parsing in readPacket()
{
  uint32_t  ul;
   md_ad9833. ::channel_t chan;
   md_ad9833. ::mode_t mode;

  switch (*cp++)
  {
  case CMD_FREQ:
    switch (*cp++)
    {
    case OPT_1: chan =  md_ad9833. ::CHAN_0; break;
    case OPT_2: chan =  md_ad9833. ::CHAN_1; break;
    case OPT_MODULATE: /* do something in future */ break;
    }

    ul = strtoul(cp, NULL, 10);
    AD.setFrequency(chan, ul);
    break;

  case CMD_PHASE:
    switch (*cp++)
    {
    case OPT_1: chan =  md_ad9833. ::CHAN_0; break;
    case OPT_2: chan =  md_ad9833. ::CHAN_1; break;
    }

    ul = strtoul(cp, NULL, 10);
    AD.setPhase(chan, (uint16_t)ul);
    break;

  case CMD_OUTPUT:
    switch (*cp++)
    {
    case OPT_FREQ:
      switch (*cp)
      {
      case OPT_1: chan =  md_ad9833. ::CHAN_0; break;
      case OPT_2: chan =  md_ad9833. ::CHAN_1; break;
      case OPT_MODULATE: /* do something in future */ break;
      }
      AD.setActiveFrequency(chan);
      break;

    case OPT_PHASE:
      switch (*cp)
      {
      case OPT_1: chan =  md_ad9833. ::CHAN_0; break;
      case OPT_2: chan =  md_ad9833. ::CHAN_1; break;
      case OPT_MODULATE: /* do something in future */ break;
      }
      AD.setActivePhase(chan);
      break;

    case OPT_SIGNAL:
      switch (*cp)
      {
      case 'O': mode =  md_ad9833. ::MODE_OFF;    break;
      case 'S': mode =  md_ad9833. ::MODE_SINE;   break;
      case 'T': mode =  md_ad9833. ::MODE_TRIANGLE;  break;
      case 'Q': mode =  md_ad9833. ::MODE_SQUARE1;  break;
      }
      AD.setMode(mode);
      break;
    }
    break;
  }

  return;
}


void loop()
{
  char  *cp;

  if ((cp = readPacket()) != NULL)
    processPacket(cp);
}

输出示波器图像

vout的1khz sinewave

设置100mV / div,0.2ms / div:1 /(0.2ms * 4.8)= 1041Hz(范围准确性)。

AD9833正弦波1kHz在示波器上

vout的1khz三角波

设置100mV / div,0.2ms / div:1 /(0.2ms * 4.8)= 1041Hz(范围准确性)。

AD9833示波器上的三角波1kHzf

vout的1khz方波

设置1V / div,0.2ms / div:1 /(0.2ms * 4.8)= 1041Hz(范围准确性)。

注意:方波输出比其他信号更大幅度。

示波器上的AD9833方波1kHz

扫描生成的例子

此代码在2秒内从1MHz扫描到3MHz。

// Pins for SPI comm with the AD9833 IC
#define DATA  11     ///< SPI Data pin number
#define CLK   13     ///< SPI Clock pin number
#define FSYNC 10     ///< SPI Load pin number (FSYNC in AD9833 usage)
#define CS_DIGIPOT 9 // MCP41010 chip select - digital potentiometer.

 md_ad9833.  AD( FSY. NC); // Hardware SPI

void setup() {
  AD.begin();
}


void loop() {
unsigned long f;

    for( f = 1000000UL; f<3000000UL; f+=10000UL) {
        delay(10);
        AD.setFrequency( md_ad9833. ::CHAN_0, f);
    }
}

突破板IC引脚

AD9833引脚向下

这在10个引线MSOP中仅提供。仅限表面贴装。 

AD9833 Pinoot(MSOP)

MCP41010 引脚向前

在电路板上,使用表面贴装SOIC,但您也可以在PDIP中获得它。


 MCP41010 对PDIP或SEIC引脚

注意:该部件被指定为MCP41xxx,其中xxx = 010是一个10k罐,当xxx = 100时,它是一个100k罐。

AD8051引脚声

这有很多不同的包,但这是SOT23-5 I.E. 很小。突破板上的一个在顶部标记为H2a。
AD8051 SOT23-5非常高速的OPAMP

IC数据表

右键单击以下链接并使用“保存”以保存 PDF到您的硬盘,或单击以在新浏览器窗口中打开。

AD9833数据表

这是直接数字合成芯片 数据表 (点击在新窗口中打开)。

AD8051数据表

这是300MHz铁路到铁路opamp 数据表 (点击在新窗口中打开)

MCP41010 数据表

这是256点击数字锅。 数据表 (点击在新窗口中打开)。




新的! Comments

让你说到你刚刚阅读的东西!留下下面的框中的评论。




隐私政策 | 接触 | 关于我

网站地图 | 使用条款


 ezoic. 报告此广告

访问我们的Facebook页面:

   点击这里



最近的文章

  1. 如何使用ADS1115

    使用ADS1115精度16位ADC进行教程进行低功耗。

    阅读更多

  2. arduino. 模拟输出...易模拟输出生成

    arduino. 模拟输出:如何创建最精确的PWM模拟输出以及如何创建模拟PWM正弦波。

    阅读更多

  3. 数号和等效的快速宏。加快代码!

    了解DigitalWrite()的工作原理......现在使用17倍宏宏!

    阅读更多

  4. TCS230颜色传感芯片:如何运作以及如何使用它。

    如何使用TCS230(/ TCS3200)彩色检测器芯片并轻松将其添加到您的任何项目中。

    阅读更多

  5. 如何使用ADXL345进行运动感测等。

    使用ADXL345 Acellerometer,您可以检测到16G!您还可以了解如何使用它来点击检测等。

    阅读更多

  6. HMC5883L 3轴数字MAGENTOMTER如何运作

    HMC5883L - 如何制作数字罗盘,了解HMC5883L和QMC5883L之间的差异以及它们是否兼容。

    阅读更多



读者 Comments

"I wanted to thank
你这么好
对于所有信息
你已经提供了
你的网站's

高超 极好的 ."

- 逃亡Potthath.

"This site really is
最好的和我最喜欢的。
我发现这里有很多很有用
项目和提示。"

- 米兰

Bursach.<at>gmail.com<

"Awesome site,
非常,非常容易和好
导航!"


-
Matt_tr. <at>
wolf359.cjb.net.


学习微控制器

"Interested in
微控制器?"

注册
免费7天指南:

自由 GUIDE : CLICK HERE


"I am a newbie to PIC
我想说
 how great your
网站一直在为我。"


- 戴夫

de_scott.<at>bellsouth.net

"Your site is a great
和完美的工作。
恭喜。"


- SURESH.

IntegratedInfosys.<at>
Yahoo.com.

"I couldn't find the correct
要定义的词语
你的网页。

非常有用,揭开,
诚实明确。

非常感谢
你的时间和作品。
问候。 "


- Anon.

回到顶部