Hello, I have the module of the AD9833 wave generator chip as in the link:
https://www.google.com/search?q=ad9833 module&biw=1600&bih=799&noj=1&source=lnms&tbm=isch&sa=X&ei=tC9uVPGZLYmqywOl5IL4Ag&ved=0CAkQ_AUoAg
I'm trying to control the chip with the STM32F4 Discovery board via SPI. I need the user to be able to select the waveform type (sinusoidal, square or triangular) and select the frequency and phase for the signal. I don't have much experience with ARM based controllers but I've written a code like this:
But the code doesn't function properly. I couldn't tell if my SPI configuration or the way I send data is wrong or if there any other bugs. Where am I doing wrong and how can this be fixed? Thanks for the help!
Link for AD9833 datasheet if needed:
http://www.analog.com/static/imported-files/data_sheets/AD9833.pdf
https://www.google.com/search?q=ad9833 module&biw=1600&bih=799&noj=1&source=lnms&tbm=isch&sa=X&ei=tC9uVPGZLYmqywOl5IL4Ag&ved=0CAkQ_AUoAg
I'm trying to control the chip with the STM32F4 Discovery board via SPI. I need the user to be able to select the waveform type (sinusoidal, square or triangular) and select the frequency and phase for the signal. I don't have much experience with ARM based controllers but I've written a code like this:
Code:
#include "stm32f4xx.h"
#include "stm32f4xx_rcc.h"
#include "stm32f4xx_gpio.h"
#include "stm32f4xx_spi.h"
#define AD_MCLK 25000000
uint16_t stats = 0;
uint16_t tosend = 0;
#define constant1 268435456 //2^28, (1<<28)
#define constant2 4096 //2^12, (1<<12)
#define pi2 6.2832
#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_SINUS 1
#define AD_RECT1 2
#define AD_RECT2 3
#define AD_TRIANGLE 4
#define AD_FREQ0 18
#define AD_FREQ1 28
#define AD_PHASE0 38
#define AD_PHASE1 48
void Delay1ms(uint32_t nCount);
volatile uint32_t delay1ms;
void Delay1ms(uint32_t nCount)
{
delay1ms = nCount;
while(delay1ms);
}
void SysTick_Handler(void)
{
if(delay1ms) delay1ms--;
}
void AD9833_write(uint16_t data)
{
GPIO_ResetBits(GPIOE, GPIO_Pin_7);
SPI_I2S_SendData(SPI1, (data>>8)); //MSB_First
//while(!SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE)); // wait until transmit complete
while(SPI_I2S_GetFlagStatus (SPI1, SPI_I2S_FLAG_BSY) == SET); // wait until SPI is not busy anymore
SPI_I2S_SendData(SPI1, (uint8_t)(data & 255)); //LSB
//while(!SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE)); // wait until transmit complete
while(SPI_I2S_GetFlagStatus (SPI1, SPI_I2S_FLAG_BSY) == SET); // wait until SPI is not busy anymore
GPIO_SetBits(GPIOE, GPIO_Pin_7);
}
void AD9833_setfreq(uint32_t frequency, uint8_t reg){
double temp = ((double)frequency/(double)AD_MCLK);
uint32_t regist = temp * constant1;
tosend = regist & 0x3FFF;
if (reg == AD_FREQ0){tosend |= (1<<14);}
if (reg == AD_FREQ1){tosend |= (1<<15);}
Delay1ms(5);
AD9833_write(tosend);
Delay1ms(5);
tosend = (regist & ~0x3FFF)>>14;
if (reg == AD_FREQ0){tosend |= (1<<14);}
if (reg == AD_FREQ1){tosend |= (1<<15);}
AD9833_write(tosend);
}
void AD9833_setphase(uint16_t phase, uint8_t reg){
uint16_t regist = (uint16_t) (phase*constant2)/pi2;
tosend = (1<<15) | (1<<14);
if (reg == AD_PHASE1){tosend |= (1<<13);}
AD9833_write(tosend | regist);
}
void AD9833_setmode(uint8_t signal){
switch (signal){
case AD_OFF:
AD9833_off();
break;
case AD_SINUS:
stats &= ~((1<<AD_OPBITEN) | (1<<AD_MODE) | (1<<AD_SLEEP1));
break;
case AD_RECT2:
stats &= ~((1<<AD_MODE) | (1<<AD_DIV2) | (1<<AD_SLEEP1));
stats |= (1<<AD_OPBITEN);
break;
case AD_RECT1:
stats |= (1<<AD_OPBITEN) | (1<<AD_DIV2);
stats &= ~((1<<AD_MODE) | (1<<AD_SLEEP1));
break;
case AD_TRIANGLE:
stats &= ~((1<<AD_OPBITEN) | (1<<AD_SLEEP1));
stats |= (1<<AD_MODE);
break;
default:
stats |= (1<<AD_OPBITEN) | (1<<AD_MODE);
}
AD9833_write(stats);
}
void AD9833_reg(uint8_t reg){
switch (reg){
case AD_FREQ0:
stats &= ~(1<<AD_FSELECT);
break;
case AD_FREQ1:
stats |= (1<<AD_FSELECT);
break;
case AD_PHASE0:
stats &= ~(1<<AD_PSELECT);
break;
case AD_PHASE1:
stats |= (1<<AD_PSELECT);
break;
default:
stats &= ~((1<<AD_FSELECT) | (1<<AD_PSELECT));
}
AD9833_write(stats);
}
void init_SPI1(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
SPI_InitTypeDef SPI_InitStruct;
// enable peripheral clock
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
SPI_InitStruct.SPI_Direction = SPI_Direction_1Line_Tx;
SPI_InitStruct.SPI_Mode = SPI_Mode_Master;
SPI_InitStruct.SPI_DataSize = SPI_DataSize_16b;
SPI_InitStruct.SPI_CPOL = SPI_CPOL_High;
SPI_InitStruct.SPI_CPHA = SPI_CPHA_1Edge;
SPI_InitStruct.SPI_NSS = SPI_NSS_Soft | SPI_NSSInternalSoft_Set;
SPI_InitStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16;
SPI_InitStruct.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_Init(SPI1, &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
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);
GPIO_SetBits(GPIOE, GPIO_Pin_7); // set PE7 high
SPI_Cmd(SPI1, ENABLE); // enable SPI1
}
int main(void) {
init_SPI1();
AD9833_setmode(AD_SINUS);
AD9833_setfreq(1000, AD_FREQ0);
AD9833_setphase(0,AD_PHASE0);
while(1){
}
}
Link for AD9833 datasheet if needed:
http://www.analog.com/static/imported-files/data_sheets/AD9833.pdf