[ARM] Controlling AD9833 with STM32F4 Discovery Board

Status
Not open for further replies.

solijoli

Newbie level 1
Joined
Nov 23, 2014
Messages
1
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Activity points
8
Hello, I'm trying to control the AD9833 waveform generator circuit with the STM32F4 board via SPI. I've written the code below. I'm able to generate the desired waveforms for the signal but I can't change the frequency or the phase. Can you tell me what is wrong with the code and how can it be fixed. I also think that there might be a problem about initializing the AD9833 but I couldn't tell for sure. The datasheet can be seen from the link below. Thanks for helping!!

https://www.analog.com/static/imported-files/data_sheets/AD9833.pdf

Code:
#include "stm32f4xx.h"
#include "stm32f4xx_rcc.h"
#include "stm32f4xx_gpio.h"
#include "stm32f4xx_spi.h"


#define AD_F_MCLK 		25000000
#define AD_2POW28		268435456

#define AD_FREQ_CALC(freq) (uint32_t)(((double)AD_2POW28/(double)AD_F_MCLK*freq)*4)
#define AD_PHASE_CALC(phase_deg) (uint16_t)((512*phase_deg)/45)


#define AD_B28     		13
#define AD_HLB     		12
#define AD_FSELECT 		11
#define AD_PSELECT 		10
#define AD_RESET   		8
#define AD_SLEEP1 		7
#define AD_SLEEP12 		6
#define AD_OPBITEN 		5
#define AD_DIV2    		3
#define AD_MODE    		1

#define AD_OFF      	0
#define AD_TRIANGLE 	1
#define AD_SQUARE   	2
#define AD_SINE     	3

#define AD_FREQ0 		(1<<14)
#define AD_FREQ1  		(1<<15)
#define AD_PHASE0 		(3<<14)
#define AD_PHASE1 		((3<<14)|(1<<13))

typedef struct {
uint8_t  freq_out;
uint8_t  phase_out;
uint8_t  mode;
uint16_t command_reg;
} ad9833_settings_t;

typedef struct {
    float    freq[2];
    float    phase[2];
    float    mod_freq;
} ad9833_settings_f;


ad9833_settings_t ad_settings;
ad9833_settings_f ad_settings2;


void delay(__IO uint32_t nCount)
{
  while(nCount--)
  {
  }
}


static void AD9833_word(uint16_t data)
{
	SPI1->DR = (data>>8); // High 8 bits, MSB first
	while(!(SPI1->SR & SPI_I2S_FLAG_TXE));
	while( SPI1->SR & SPI_I2S_FLAG_BSY );
	SPI1->DR = (uint8_t) data; // Low 8 bits
	while(!(SPI1->SR & SPI_I2S_FLAG_TXE));
	while( SPI1->SR & SPI_I2S_FLAG_BSY );
}

static void AD9833_write(uint16_t data)
{
	GPIO_ResetBits(GPIOE, GPIO_Pin_7);
	delay(0xFF);
	AD9833_word(data);
	delay(0xFF);
	GPIO_SetBits(GPIOE, GPIO_Pin_7);
}


void AD9833_setFreq(uint8_t reg, double freq){
    uint32_t freq_reg;
    uint16_t reg_reg; //probably should be renamed...
    freq_reg = AD_FREQ_CALC(freq);
    ad_settings2.freq[reg] = freq;

    if (reg==1)
        reg_reg = AD_FREQ1;
    else
        reg_reg = AD_FREQ0;

    GPIO_ResetBits(GPIOE, GPIO_Pin_7);
    delay(0xFF);
    AD9833_word(reg_reg | (0x3FFF&(uint16_t)(freq_reg>>2 )));
    AD9833_word(reg_reg | (0x3FFF&(uint16_t)(freq_reg>>16)));
    delay(0xFF);
    GPIO_SetBits(GPIOE, GPIO_Pin_7);
}

void    AD9833_setFreqOut(uint8_t freq_out){
    ad_settings.freq_out = freq_out;
    switch (freq_out){
        case 0:
            ad_settings.command_reg &= ~(1<<AD_FSELECT);
            break;
        case 1:
            ad_settings.command_reg |= (1<<AD_FSELECT);
            break;
        case 2:
            //TODO
            break;
    }

    AD9833_write(ad_settings.command_reg);
}

double AD9833_getFreq(uint8_t reg){
    return ad_settings2.freq[reg];
}


void AD9833_setPhase(uint8_t reg, double phase){
    uint16_t reg_reg; //probably should be renamed...
    if (reg==1)
        reg_reg = AD_PHASE1;
    else
        reg_reg = AD_PHASE0;

    ad_settings2.phase[reg] = phase;


    AD9833_write(reg_reg | AD_PHASE_CALC(ad_settings2.phase[reg]));

}

void AD9833_setPhaseOut(uint8_t phase_out){
    ad_settings.phase_out = phase_out;
    switch (phase_out){
        case 0:
            ad_settings.command_reg &= ~(1<<AD_PSELECT);
            break;
        case 1:
            ad_settings.command_reg |= (1<<AD_PSELECT);
            break;
        case 2:
            //TODO
            break;
    }

    AD9833_write(ad_settings.command_reg);

}




void AD9833_setMode(uint8_t mode)
{
	ad_settings.mode = mode;
	switch(mode)
	{
			case AD_OFF:
	            ad_settings.command_reg |= (1<<AD_SLEEP12);
	            ad_settings.command_reg |= (1<<AD_SLEEP1);
	            break;
			case AD_TRIANGLE:
	            ad_settings.command_reg &= ~(1<<AD_OPBITEN);
	            ad_settings.command_reg |=  (1<<AD_MODE);
	            ad_settings.command_reg &= ~(1<<AD_SLEEP12);
	            ad_settings.command_reg &= ~(1<<AD_SLEEP1);
	            break;
	        case AD_SQUARE:
	            ad_settings.command_reg |=  (1<<AD_OPBITEN);
	            ad_settings.command_reg &= ~(1<<AD_MODE);
	            ad_settings.command_reg |=  (1<<AD_DIV2);
	            ad_settings.command_reg &= ~(1<<AD_SLEEP12);
	            ad_settings.command_reg &= ~(1<<AD_SLEEP1);
	            break;
	        case AD_SINE:
	            ad_settings.command_reg &= ~(1<<AD_OPBITEN);
	            ad_settings.command_reg &= ~(1<<AD_MODE);
	            ad_settings.command_reg &= ~(1<<AD_SLEEP12);
	            ad_settings.command_reg &= ~(1<<AD_SLEEP1);
	            break;
	}

	AD9833_write(ad_settings.command_reg); // Send selected MODE to AD9833
}


void init_SPI1(void)
  {

	    GPIO_InitTypeDef GPIO_InitStruct;
	    SPI_InitTypeDef SPI_InitStruct;


	    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
	    /* configure pins used by SPI1
	     * PA5 = SCK
	     * PA6 = MISO
	     * PA7 = MOSI
	     */
	    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_7 | GPIO_Pin_5;
	    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
	    GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
	    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	    GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
	    GPIO_Init(GPIOA, &GPIO_InitStruct);

	    // connect SPI1 pins to SPI alternate function
	    GPIO_PinAFConfig(GPIOA, GPIO_PinSource5, GPIO_AF_SPI1);
	    GPIO_PinAFConfig(GPIOA, GPIO_PinSource7, GPIO_AF_SPI1);

	    // enable clock for used IO pins
	    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE);

	    /* Configure the chip select pin
	       in this case we will use PE7 */
	    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_7;
	    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
	    GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
	    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	    GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;
	    GPIO_Init(GPIOE, &GPIO_InitStruct);

	    GPIOE->BSRRL |= GPIO_Pin_7; // set PE7 high

	    // enable peripheral clock
	    RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);

	    /* configure SPI1 in Mode 2
	     * CPOL = 1 --> clock is high when idle
	     * CPHA = 0 --> data is sampled at the first edge
	     */
	    SPI_InitStruct.SPI_Direction = SPI_Direction_1Line_Tx;
	    SPI_InitStruct.SPI_Mode = SPI_Mode_Master;     // transmit in master mode, NSS pin has to be always high
	    SPI_InitStruct.SPI_DataSize = SPI_DataSize_16b; // one packet of data is 8 bits wide
	    SPI_InitStruct.SPI_CPOL = SPI_CPOL_High;        // clock is low when idle
	    SPI_InitStruct.SPI_CPHA = SPI_CPHA_1Edge;      // data sampled at first edge
	    SPI_InitStruct.SPI_NSS = SPI_NSS_Soft | SPI_NSSInternalSoft_Set;
	    SPI_InitStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4; // SPI frequency is APB2 frequency / 4
	    SPI_InitStruct.SPI_FirstBit = SPI_FirstBit_MSB;// data is transmitted MSB first
	    SPI_Init(SPI1, &SPI_InitStruct);

	    SPI_Cmd(SPI1, ENABLE); // enable SPI1
	}


int main(void) {

    init_SPI1();

    AD9833_setFreq(0, 100);
    AD9833_setFreqOut(0);
    AD9833_setMode(AD_SQUARE);

	while(1){

	}

}
 

Status
Not open for further replies.
Cookies are required to use this site. You must accept them to continue using the site. Learn more…