AD9833介绍与应用(C语言实现)

1.特性

  • 低功耗、可编程波形发生器,能产生正弦波、三角波和方波的输出;

  • 主频时钟为25MHz时,可实现0.1Hz的分辨率;主频时钟为1MHz时,可实现0.004Hz的分辨率;

  • 三线式串行接口(SDATA、SCLK、FSYNC)写入数据,最高能以40MHz的时钟速率工作,支持SPI通信,一个输出信号接口(VOUT),输出信号没有负电压,输出最大电压值为650mv,输出最小电压值为38mv,不是为0;

  • 输出频率范围在0MHz至12.5MHz;

注意:方波输出的最大的电压值为供电电压值3.3V,并非650mv,其是作为时钟源使用。

2.引脚配置与功能描述

 

注意:MCLK是数字时钟输入,可接一个有源晶振,若直接连接到MCU上,可用PWM波或定时器去拉高拉低控制,但最好外接一个晶振,输出频率会受此时钟引脚的控制。

3.功能框图说明

 由功能框图可看出:

输入:AD9833的输入由FSYNC引脚、SCLK引脚、SDATA引脚来控制。

寄存器:AD9833有1个控制寄存器、两个频率寄存器、两个相位寄存器、1个相位累加器。

输出:VOUT输出波形主要根据10位DAC输出正弦波和三角波,或MSB直接输出以及MSB/2输出方波。

工作流程:通过FSYNC引脚、SCLK引脚、SDATA引脚对控制寄存器、频率寄存器、相位寄存器进行写入,频率寄存器中的值输入到相位累加器中,再与相位寄存器中的值来进行相位偏移,但输出会被截断至12位,并在SIN ROM中寻找相对应相位的DAC的值经过10DAC输出或MSB直接输出或MSB/2输出到VOUT上。

注意:MSB输出的是方波,是用作时钟源使用的,输出的是供电电压3.3V,MSB输出的时钟频率是MSB/2的两倍。

4.时序特性

 由时序图可看到:

  • MCLK的一个周期时间最小值为40ns,即时钟频率最大为25MHZ;

  • 进行串行数据传输是,先拉低FSYNC引脚,串行数据会在16个时钟脉冲的SCLK下降沿移入器件的输入移位寄存器中。注意FSYNC拉低后至SCLK拉低之间的建立时间为5ns。

  • 在FSYNC变为低电平时,SCLK必须为处于高电平。

5.寄存器及功能描述

5.1 频率和相位寄存器

        AD9833包含两个28位的频率寄存器和两个12位的相位寄存器:

5.2 控制寄存器

        AD9833包含一个16位的控制寄存器,可实现配置AD9833的操作,mode位之外的所有控制位均在MCLK的内部下降沿采样。

 

5.1.1 写入频率寄存器

        需将BIT D15和BIT D14设置为频率寄存器的地址,BIT D15和BIT D14设置为01,写入到频率寄存器0,BIT D15和BIT D14设置为10,写入到频率寄存器1。

         28位频率寄存器第一次写入包含14个LSB,第二次写入包含14个MSB。

        当更改频率寄存器全部内容时,需对同一个频率寄存器地址连续写入两次数据,此时需要将B28(D13)控制位置1.

        当只需更新频率寄存器的14个MSB或14个LSB时,将B28(D13)控制位置0,此时可单独更新频率寄存器的14个MSB或14个LSB,同时要将HLD(D12)这个位中确定要更新的具体14个位,HLD(D12)置0,即更新14个LSB,HLD(D12)置1,则更新14个MSB。

 5.1.2 写入相位寄存器​​​​​​​

        需将BIT D15和BIT D14设置为相位寄存器的地址,即将BIT D15和BIT D14设置为11,BIT D13确定将载入的相位寄存器,BIT D13置0时,写入到相位寄存器0,BIT D13置1时,写入到相位寄存器1,

 5.1.3 复位功能(D8控制)

        复位操作不会使相位、频率或控制寄存器复位,会使相应的内部寄存器复位为0。

        在AD9833上电时,器件应该复位一次。

        reset置0后的8个MCLK周期内,DAC输出端会出现信号。

 5.1.4 SLEEP功能

        可降低功耗。

5.1.5 VOUT输出

        VOUT输出包括DAC数据的MSB、正弦波输出或三角波输出。由OPBINTEN(D5)和mode(D1)bit控制。

6.C语言实现

6.1 ad9833.h文件

  1. #ifndef _AD9833_H
  2. #define _AD9833_H
  3. #include 'sys.h'
  4. ​
  5. ​
  6. //AD9833 GPIO
  7. #define AD9833_SDATA PAout(7) //SDATA
  8. #define AD9833_SCLK   PAout(5) //SCLK
  9. #define AD9833_FSYNC PAout(4) //FSYNC
  10. ​
  11. /* WaveMode */
  12. #define AD9833_OUT_SINUS ((0 << 5) | (0 << 1) | (0 << 3))
  13. #define AD9833_OUT_TRIANGLE ((0 << 5) | (1 << 1) | (0 << 3))
  14. #define AD9833_OUT_MSB ((1 << 5) | (0 << 1) | (1 << 3))
  15. #define AD9833_OUT_MSB2 ((1 << 5) | (0 << 1) | (0 << 3))
  16. ​
  17. /* Registers */
  18. ​
  19. #define AD9833_REG_CMD (0 << 14)
  20. #define AD9833_REG_FREQ0 (1 << 14)
  21. #define AD9833_REG_FREQ1 (2 << 14)
  22. #define AD9833_REG_PHASE0 (6 << 13)
  23. #define AD9833_REG_PHASE1 (7 << 13)
  24. ​
  25. /* Command Control Bits */
  26. ​
  27. #define AD9833_B28 (1 << 13)
  28. #define AD9833_HLB (1 << 12)
  29. #define AD9833_FSEL0 (0 << 11)
  30. #define AD9833_FSEL1 (1 << 11)
  31. #define AD9833_PSEL0 (0 << 10)
  32. #define AD9833_PSEL1 (1 << 10)
  33. #define AD9833_PIN_SW (1 << 9)
  34. #define AD9833_RESET (1 << 8)
  35. #define AD9833_CLEAR_RESET (0 << 8)
  36. #define AD9833_SLEEP1 (1 << 7)
  37. #define AD9833_SLEEP12 (1 << 6)
  38. #define AD9833_OPBITEN (1 << 5)
  39. #define AD9833_SIGN_PIB (1 << 4)
  40. #define AD9833_DIV2 (1 << 3)
  41. #define AD9833_MODE (1 << 1)
  42. ​
  43. void AD9833_Init(void);
  44. static void AD9833_Delay(void);
  45. void AD9833_WriteData(u16 txdata);
  46. void AD9833_SetFrequency(unsigned short reg, double fout);
  47. void AD9833_SetPhase(unsigned short reg, unsigned short val);
  48. void AD9833_SetWave(unsigned int WaveMode,unsigned int Freq_SFR,unsigned int Phase_SFR);
  49. void AD9833_Setup(unsigned int Freq_SFR,double Freq,unsigned int Phase_SFR,unsigned int Phase,unsigned int WaveMode);
  50. #endif

6.2 ad9833.c文件

  1. #include 'ad9833.h'
  2. ​
  3. /**************************************
  4. * 函 数 名: ad9833_init
  5. * 功能说明: ad9833初始化
  6. * 形   参: 无
  7. * 返 回 值: 无
  8. *************************************/
  9. void AD9833_Init(void)
  10. {
  11. GPIO_InitTypeDef GPIO_InitStructure;
  12. RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA,ENABLE );;
  13. GPIO_InitStructure.GPIO_Pin =GPIO_Pin_4 | GPIO_Pin_5| GPIO_Pin_7;
  14. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //通用推挽输出
  15. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  16. GPIO_Init(GPIOA, &GPIO_InitStructure);
  17. GPIO_SetBits(GPIOA,GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_7);
  18. }
  19. ​
  20. /**************************************
  21. * 函 数 名: AD9833_Delay
  22. * 功能说明: ad9833延迟
  23. * 形   参: 无
  24. * 返 回 值: 无
  25. *************************************/
  26. static void AD9833_Delay(void)
  27. {
  28. uint16_t i;
  29. for (i = 0; i < 1; i );
  30. }
  31. /**************************************
  32. * 函 数 名: ad9833_write_data
  33. * 功能说明: ad9833写入16位数据
  34. * 形   参: txdata:待写入的16位数据
  35. * 返 回 值: 无
  36. *************************************/
  37. void AD9833_WriteData(u16 txdata)
  38. {
  39. int i;
  40. AD9833_SCLK=1;
  41. AD9833_FSYNC=1;
  42. AD9833_FSYNC=0;
  43. //写16位数据
  44. for(i=0;i<16;i )
  45. {
  46. if (txdata & 0x8000)
  47. AD9833_SDATA=1;
  48. else
  49. AD9833_SDATA=0;
  50. AD9833_Delay();
  51. AD9833_SCLK=0;
  52. AD9833_Delay();
  53. AD9833_SCLK=1;
  54. txdata<<=1;
  55. }
  56. AD9833_FSYNC=1;
  57. }
  58. ​
  59. /**************************************
  60. * 函 数 名: AD9833_SetFrequency
  61. * 功能说明: ad9833设置频率寄存器
  62. * 形   参: reg:待写入的频率寄存器
  63. fout:频率值
  64. * 返 回 值: 无
  65. *************************************/
  66. void AD9833_SetFrequency(unsigned short reg, double fout)
  67. {
  68. int frequence_LSB,frequence_MSB;
  69. double   frequence_mid,frequence_DATA;
  70. long int frequence_hex;
  71. ​
  72. /*********************************计算频率的16进制值***********************************/
  73. frequence_mid=268435456/25;//适合25M晶振
  74. //如果时钟频率不为25MHZ,修改该处的频率值,单位MHz ,AD9833最大支持25MHz
  75. frequence_DATA=fout;
  76. frequence_DATA=frequence_DATA/1000000;
  77. frequence_DATA=frequence_DATA*frequence_mid;
  78. frequence_hex=frequence_DATA; //这个frequence_hex的值是32位的一个很大的数字,需要拆分成两个14位进行处理;
  79. frequence_LSB=frequence_hex; //frequence_hex低16位送给frequence_LSB
  80. frequence_LSB=frequence_LSB&0x3fff;//去除最高两位,16位数换去掉高位后变成了14位
  81. frequence_MSB=frequence_hex>>14; //frequence_hex高16位送给frequence_HSB
  82. frequence_MSB=frequence_MSB&0x3fff;//去除最高两位,16位数换去掉高位后变成了14位
  83. frequence_LSB=frequence_LSB|reg;
  84. frequence_MSB=frequence_MSB|reg;
  85. AD9833_WriteData(0x2100); //选择数据一次写入,B28位和RESET位为1
  86. AD9833_WriteData(frequence_LSB);
  87. AD9833_WriteData(frequence_MSB);
  88. }
  89. ​
  90. /**************************************
  91. * 函 数 名: ad9833_write_data
  92. * 功能说明: ad9833设置相位寄存器
  93. * 形   参: reg:待写入的相位寄存器
  94. fout:相位值
  95. * 返 回 值: 无
  96. *************************************/
  97. void AD9833_SetPhase(unsigned short reg, unsigned short val)
  98. {
  99. unsigned short phase = reg;
  100. phase |= val;
  101. AD9833_WriteData(phase);
  102. }
  103. ​
  104. /**************************************
  105. * 函 数 名: AD9833_SetWave
  106. * 功能说明: ad9833设置波形
  107. * 形   参: WaveMode:输出波形类型
  108. Freq_SFR:输出的频率寄存器类型
  109. Phase_SFR:输出的相位寄存器类型
  110. * 返 回 值: 无
  111. *************************************/
  112. void AD9833_SetWave(unsigned int WaveMode,unsigned int Freq_SFR,unsigned int Phase_SFR)
  113. {
  114. unsigned int val = 0;
  115. val = (val | WaveMode | Freq_SFR | Phase_SFR);
  116. AD9833_WriteData(val);
  117. }
  118. ​
  119. /**************************************
  120. * 函 数 名: AD9833_Setup
  121. * 功能说明: ad9833设置输出
  122. * 形   参: Freq_SFR:频率寄存器类型
  123. Freq :频率值
  124. Phase_SFR:相位寄存器类型
  125. Phase:相位值
  126. WaveMode:波形类型
  127. * 返 回 值: 无
  128. *************************************/
  129. void AD9833_Setup(unsigned int Freq_SFR,double Freq,unsigned int Phase_SFR,unsigned int Phase,unsigned int WaveMode)
  130. {
  131. unsigned int Fsel,Psel;
  132. AD9833_WriteData(0x0100); //复位AD9833,即RESET位为1
  133. AD9833_WriteData(0x2100); //选择数据一次写入,B28位和RESET位为1
  134. AD9833_SetFrequency(Freq_SFR,Freq);
  135. AD9833_SetPhase(Phase_SFR,Phase);
  136. if(Freq_SFR == AD9833_REG_FREQ0)
  137. {
  138. Fsel = AD9833_FSEL0;
  139. }
  140. else
  141. {
  142. Fsel = AD9833_FSEL1;
  143. }
  144. if(Phase_SFR == AD9833_REG_PHASE0)
  145. {
  146. Psel = AD9833_PSEL0;
  147. }
  148. else
  149. {
  150. Psel = AD9833_PSEL1;
  151. }
  152. ​
  153. AD9833_SetWave(WaveMode,Fsel,Psel);
  154. }

6.3 main.c文件

  1. #include 'sys.h'
  2. #include 'delay.h'
  3. #include 'usart.h'
  4. #include 'ad9833.h'
  5. ​
  6. int main(void)
  7. {
  8. u8 t=0;
  9. delay_init();   //延时函数初始化  
  10. uart_init(115200); //串口初始化为9600
  11. AD9833_Init();
  12. //输出三角波
  13. AD9833_Setup(AD9833_REG_FREQ0,10000.0,AD9833_REG_PHASE1,1024,AD9833_OUT_TRIANGLE);
  14. while(1)
  15. {
  16. printf('t:%dn',t);
  17. delay_ms(500);
  18. t ;
  19. }
  20. }