C语言实现AD9833介绍及应用

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文件

    #ifndef _AD9833_H
    #define _AD9833_H
    #include "sys.h"
    ​
    ​
    //AD9833 GPIO
    #define AD9833_SDATA  PAout(7)  //SDATA
    #define AD9833_SCLK   PAout(5)  //SCLK
    #define AD9833_FSYNC  PAout(4)  //FSYNC
    ​
    /* WaveMode */
    #define AD9833_OUT_SINUS    ((0 << 5) | (0 << 1) | (0 << 3))
    #define AD9833_OUT_TRIANGLE ((0 << 5) | (1 << 1) | (0 << 3))
    #define AD9833_OUT_MSB      ((1 << 5) | (0 << 1) | (1 << 3))
    #define AD9833_OUT_MSB2     ((1 << 5) | (0 << 1) | (0 << 3))
    ​
    /* Registers */
    ​
    #define AD9833_REG_CMD      (0 << 14)
    #define AD9833_REG_FREQ0    (1 << 14)
    #define AD9833_REG_FREQ1    (2 << 14)
    #define AD9833_REG_PHASE0   (6 << 13)
    #define AD9833_REG_PHASE1   (7 << 13)
    ​
    /* Command Control Bits */
    ​
    #define AD9833_B28          (1 << 13)
    #define AD9833_HLB          (1 << 12)
    #define AD9833_FSEL0        (0 << 11)
    #define AD9833_FSEL1        (1 << 11)
    #define AD9833_PSEL0        (0 << 10)
    #define AD9833_PSEL1        (1 << 10)
    #define AD9833_PIN_SW       (1 << 9)
    #define AD9833_RESET        (1 << 8)
    #define AD9833_CLEAR_RESET  (0 << 8)
    #define AD9833_SLEEP1       (1 << 7)
    #define AD9833_SLEEP12      (1 << 6)
    #define AD9833_OPBITEN      (1 << 5)
    #define AD9833_SIGN_PIB     (1 << 4)
    #define AD9833_DIV2         (1 << 3)
    #define AD9833_MODE         (1 << 1)
    ​
    void AD9833_Init(void);
    static void AD9833_Delay(void);
    void AD9833_WriteData(u16 txdata);
    void AD9833_SetFrequency(unsigned short reg, double fout);
    void AD9833_SetPhase(unsigned short reg, unsigned short val);
    void AD9833_SetWave(unsigned int WaveMode,unsigned int Freq_SFR,unsigned int Phase_SFR);
    void AD9833_Setup(unsigned int Freq_SFR,double Freq,unsigned int Phase_SFR,unsigned int Phase,unsigned int WaveMode);
    
    #endif

    6.2 ad9833.c文件

    #include "ad9833.h"
    ​
    /**************************************
    *   函 数 名: ad9833_init
    *   功能说明: ad9833初始化
    *   形    参: 无
    *   返 回 值: 无
    *************************************/
    void AD9833_Init(void)
    {
        GPIO_InitTypeDef GPIO_InitStructure;
        RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA,ENABLE );;
        
        GPIO_InitStructure.GPIO_Pin =GPIO_Pin_4 | GPIO_Pin_5| GPIO_Pin_7;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;  //通用推挽输出
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOA, &GPIO_InitStructure);
        GPIO_SetBits(GPIOA,GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_7);
    }
    ​
    /**************************************
    *   函 数 名: AD9833_Delay
    *   功能说明: ad9833延迟
    *   形    参: 无
    *   返 回 值: 无
    *************************************/
    static void AD9833_Delay(void)
    {
        uint16_t i;
        for (i = 0; i < 1; i++);
    }
    /**************************************
    *   函 数 名: ad9833_write_data
    *   功能说明: ad9833写入16位数据
    *   形    参: txdata:待写入的16位数据
    *   返 回 值: 无
    *************************************/
    void AD9833_WriteData(u16 txdata)
    {
        int i;
        AD9833_SCLK=1;
        AD9833_FSYNC=1;
        AD9833_FSYNC=0;
        //写16位数据
        for(i=0;i<16;i++)
        {
            
            if (txdata & 0x8000)
                AD9833_SDATA=1;
            else
                AD9833_SDATA=0;
            AD9833_Delay();
            AD9833_SCLK=0;
            AD9833_Delay();
            AD9833_SCLK=1;
            txdata<<=1;
        }
        AD9833_FSYNC=1;
    }
    ​
    /**************************************
    *   函 数 名: AD9833_SetFrequency
    *   功能说明: ad9833设置频率寄存器
    *   形    参: reg:待写入的频率寄存器   
                  fout:频率值
    *   返 回 值: 无
    *************************************/
    void AD9833_SetFrequency(unsigned short reg, double fout)
    {
        int frequence_LSB,frequence_MSB;
        double   frequence_mid,frequence_DATA;
        long int frequence_hex;
    ​
        /*********************************计算频率的16进制值***********************************/
        frequence_mid=268435456/25;//适合25M晶振
        //如果时钟频率不为25MHZ,修改该处的频率值,单位MHz ,AD9833最大支持25MHz
        frequence_DATA=fout;
        frequence_DATA=frequence_DATA/1000000;
        frequence_DATA=frequence_DATA*frequence_mid;
        frequence_hex=frequence_DATA;  //这个frequence_hex的值是32位的一个很大的数字,需要拆分成两个14位进行处理;
        frequence_LSB=frequence_hex; //frequence_hex低16位送给frequence_LSB
        frequence_LSB=frequence_LSB&0x3fff;//去除最高两位,16位数换去掉高位后变成了14位
        frequence_MSB=frequence_hex>>14; //frequence_hex高16位送给frequence_HSB
        frequence_MSB=frequence_MSB&0x3fff;//去除最高两位,16位数换去掉高位后变成了14位
        frequence_LSB=frequence_LSB|reg;
        frequence_MSB=frequence_MSB|reg;
        AD9833_WriteData(0x2100); //选择数据一次写入,B28位和RESET位为1
        AD9833_WriteData(frequence_LSB);
        AD9833_WriteData(frequence_MSB);
    }
    ​
    /**************************************
    *   函 数 名: ad9833_write_data
    *   功能说明: ad9833设置相位寄存器
    *   形    参: reg:待写入的相位寄存器   
                  fout:相位值
    *   返 回 值: 无
    *************************************/
    void AD9833_SetPhase(unsigned short reg, unsigned short val)
    {
        unsigned short phase = reg;
        phase |= val;
        AD9833_WriteData(phase);
    }
    ​
    /**************************************
    *   函 数 名: AD9833_SetWave
    *   功能说明: ad9833设置波形
    *   形    参: WaveMode:输出波形类型 
                  Freq_SFR:输出的频率寄存器类型
                  Phase_SFR:输出的相位寄存器类型
    *   返 回 值: 无
    *************************************/
    void AD9833_SetWave(unsigned int WaveMode,unsigned int Freq_SFR,unsigned int Phase_SFR)
    {
        unsigned int val = 0;
        val = (val | WaveMode | Freq_SFR | Phase_SFR);
        AD9833_WriteData(val);
    }
    ​
    /**************************************
    *   函 数 名: AD9833_Setup
    *   功能说明: ad9833设置输出
    *   形    参: Freq_SFR:频率寄存器类型
                  Freq    :频率值
                  Phase_SFR:相位寄存器类型
                  Phase:相位值
                  WaveMode:波形类型
    *   返 回 值: 无
    *************************************/
    void AD9833_Setup(unsigned int Freq_SFR,double Freq,unsigned int Phase_SFR,unsigned int Phase,unsigned int WaveMode)
    {
        unsigned int Fsel,Psel;
        AD9833_WriteData(0x0100); //复位AD9833,即RESET位为1
        AD9833_WriteData(0x2100); //选择数据一次写入,B28位和RESET位为1
        AD9833_SetFrequency(Freq_SFR,Freq);
        AD9833_SetPhase(Phase_SFR,Phase);
        if(Freq_SFR == AD9833_REG_FREQ0)
        {
            Fsel = AD9833_FSEL0;
        }
        else 
        {
            Fsel = AD9833_FSEL1;
        }
        if(Phase_SFR == AD9833_REG_PHASE0)
        {
            Psel = AD9833_PSEL0;
        }
        else 
        {
            Psel = AD9833_PSEL1;
        }
    ​
        AD9833_SetWave(WaveMode,Fsel,Psel);
    }

    6.3 main.c文件

    #include "sys.h"
    #include "delay.h"
    #include "usart.h"
    #include "ad9833.h"
    ​
     int main(void)
     {      
        u8 t=0;
        delay_init();            //延时函数初始化    
        uart_init(115200);   //串口初始化为9600
        AD9833_Init();
         //输出三角波
        AD9833_Setup(AD9833_REG_FREQ0,10000.0,AD9833_REG_PHASE1,1024,AD9833_OUT_TRIANGLE);
        while(1)
        {
            printf("t:%d\n",t);
            delay_ms(500);
            t++;
        }
     }
    物联沃分享整理
    物联沃-IOTWORD物联网 » C语言实现AD9833介绍及应用

    发表回复