Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

[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.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top