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.

AD9833 doesnot obey my code

Status
Not open for further replies.

anotherbrick

Full Member level 4
Joined
Jan 10, 2009
Messages
217
Helped
1
Reputation
2
Reaction score
1
Trophy points
1,298
Location
Istanbul , Turkey
Activity points
3,141
hello dear forum

I am trying to generate 20 Khz square wave with AD9833
however AD9833 only generate square wave with correct freq. at the init command
if I want to change the frequency afterwards inside while loop, for example sweep around 20 Khz
it changes the output to sinus wave with a stupid frequency 19830 without sweep
i.e. it doesnot obey my code ( STM32F103C8)

what I m doing wrong ? or , isnot AD9833 original ?

thanks for any advice

C:
  MX_GPIO_Init();
  /* USER CODE BEGIN 2 */
//  NVIC_Configuration();
 writeSPI(0x2100);    HAL_Delay(100); writeSPI(0x2000);
 AD9833_Init();

-----------------------
      while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
      HAL_Delay(100);
      HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_13);
      disptimer++;
      frqfl=20000.5F+(float)(disptimer*5);phsfl=100.0F
      
        AD9833_SetWaveData();
          
------------------------------------
    
    // ------------------------------------------------ Software SPI Function
void writeSPI(uint16_t word) {
    HAL_GPIO_WritePin(AD9833PORT,AD9833SS,GPIO_PIN_RESET);
    ASM_NOP();ASM_NOP();//Delay(5);
    for (uint8_t i = 0; i < 16 ; i++) {
          if(word & 0x8000) HAL_GPIO_WritePin(AD9833PORT,AD9833DATA,GPIO_PIN_SET);   //bit=1, Set High
        else HAL_GPIO_WritePin(AD9833PORT,AD9833DATA,GPIO_PIN_RESET);        //bit=0, Set Low
          ASM_NOP(); ASM_NOP();//Delay(1);
        HAL_GPIO_WritePin(AD9833PORT,AD9833SCK,GPIO_PIN_RESET);             //Data is valid on falling edge
         ASM_NOP(); ASM_NOP();//Delay(1);
        HAL_GPIO_WritePin(AD9833PORT,AD9833SCK,GPIO_PIN_SET);
        word = word<<1; //Shift left by 1 bit
        }
    HAL_GPIO_WritePin(AD9833PORT,AD9833DATA,GPIO_PIN_RESET); //Idle low
    ASM_NOP();ASM_NOP();//Delay(5);
    HAL_GPIO_WritePin(AD9833PORT,AD9833SS,GPIO_PIN_SET);
    //Delay(5);
}

--------------------------------
    // ------------------------------------------------ Sets Wave Frequency & Phase (In Degree) In PHASE0 & FREQ0 Registers
void AD9833_SetWaveData(void){
    float Frequency,Phase;
Delay(5);
    Frequency=frqfl;Phase=phsfl;
 // ---------- Tuning Word for Phase ( 0 - 360 Degree )
 if(Phase<0)Phase=0; // Changing Phase Value to Positive
 if(Phase>360)Phase=360; // Maximum value For Phase (In Degree)
 phaseVal  = ((int)(Phase*(4096/360)))|0XC000;  // 4096/360 = 11.37 change per Degree for Register And using 0xC000 which is Phase 0 Register Address

 // ---------- Tuning word for Frequency
long freq=0;
freq=(int)(((Frequency*pow(2,28))/FMCLK)+1); // Tuning Word
FRQHW=(int)((freq & 0xFFFC000) >> 14); // FREQ MSB
FRQLW=(int)(freq & 0x3FFF);  // FREQ LSB
FRQLW |= 0x4000;
FRQHW |= 0x4000;
 // ------------------------------------------------ Writing DATA
 HAL_GPIO_WritePin(AD9833PORT,AD9833DATA,GPIO_PIN_SET);
 HAL_GPIO_WritePin(AD9833PORT,AD9833SCK,GPIO_PIN_SET);
    //HAL_GPIO_WritePin(AD9833PORT,AD9833SS,GPIO_PIN_SET);
    //HAL_GPIO_WritePin(AD9833PORT,AD9833SS,GPIO_PIN_RESET); //low = selected
    Delay(1);
    //if(init) writeSPI(0x2100); // enable 16bit words and set reset bit !!!once 0x2000 yolla
    writeSPI(0x2028);
    writeSPI(FRQLW);
    writeSPI(FRQHW);
    writeSPI(phaseVal);writeSPI(0x2028);
   // if(init) writeSPI(0x2000); // clear reset bit
    //Delay(5);
    //HAL_GPIO_WritePin(AD9833PORT,AD9833SS,GPIO_PIN_SET); //high = deselected
    //AD9833_SetWave(WKNOWN);
//Delay(1);
init=0;
return;
}
------------------------------------
void AD9833_SetWave(uint16_t Wave){
  switch(Wave){        // SYNC ?
  case 0:
//  HAL_GPIO_WritePin(AD9833PORT,AD9833SS,GPIO_PIN_RESET);
    writeSPI(0x2000); // Value for Sinusoidal Wave
//    HAL_GPIO_WritePin(AD9833PORT,AD9833SS,GPIO_PIN_SET);
    WKNOWN=0;
    break;
  case 1:
   //  HAL_GPIO_WritePin(AD9833PORT,AD9833SS,GPIO_PIN_RESET);
    writeSPI(0x2028); // Value for Square Wave
  //  HAL_GPIO_WritePin(AD9833PORT,AD9833SS,GPIO_PIN_SET);
    WKNOWN=1;
    break;
  case 2:
   //     HAL_GPIO_WritePin(AD9833PORT,AD9833SS,GPIO_PIN_RESET);
    writeSPI(0x2002); // Value for Triangle Wave
  //  HAL_GPIO_WritePin(AD9833PORT,AD9833SS,GPIO_PIN_SET);
    WKNOWN=2;
    break;
  default:
    break;
  }
}
----------------------------------------
    
// ------------------------------------------------ Initializing AD9833
void AD9833_Init(void){
//    float FRQ,Phase;
HAL_GPIO_WritePin(AD9833PORT,AD9833DATA,GPIO_PIN_SET); // Set All SPI pings to High
HAL_GPIO_WritePin(AD9833PORT,AD9833SCK,GPIO_PIN_SET);  // Set All SPI pings to High
HAL_GPIO_WritePin(AD9833PORT,AD9833SS,GPIO_PIN_SET);   // Set All SPI pings to High
AD9833_SetWave(1);//WaveType);                              // Type Of Wave
//FRQ= frqfl;Phase=phsfl;
AD9833_SetWaveData();//FRQ,Phase);                         // Frequency & Phase Set
return;
}
 

HI;

Did you follow Figure 26 flow chart ... especially after change of frequency registers?

Klaus
 
hello , thank you

the only difference between my code and figure 26 is
that figure 26 init both freq and phase registers

I writeSPI(0x2028); before and after freq change which select 28 bit write and select freq0 phase0 reg. for output

( I am not using freq1 and phase1 regs )

and the libraries I found in internet dont use freq1 phase1 regs either

I am in a mode of pulling my hair :mad:
 

The conversation continued a bit over at: https://ez.analog.com/dds/f/q-a/545058/ad9833-doesnot-change-freq-after-init although the code does differ slightly.
I am always concerned when I see expressions such as "4096/360" especially when the comment afterwards says it equals "11.37" - I suggest that it will equal 11 as it is probably integer arithmetic occurring here.
In 'xx_SetWaveData', how is 'phaseVal' defined?
Also why are you bit-banging the SPI interface - the STM32F devices have a perfectly good hardware SPI module.
Susan
 
Hi,

something I noticed is that the DDS was never reseted after powering-up (within AD9833_Init(void)) by setting D8 to 1 (0x2028 --> 0x2128). See page 16 and also Fig. 27.

BR
 
hello

1) I init AD9833 at the beginning of main
2) this time I init both freq and phase regs - pls look at below code
3) I add logic analyser output - it shows capture inside while (1) in main function ) in the document of AD9833 it says even how to connect 8051
please look at the picture what can be wrong with software SPI -this is my last exit befor bridge (I will change to HW SPI if no solution)
( if it can conect to 8051 it must connect to STM32 with software SPI)
4) with this code I get the wave at below pic


AD9833-4.png


AD9833-5.jpg

C:
#include "AD9833.h"
#include "main.h"
// ------------------- Variables ----------------
uint16_t FRQLW = 0;    // MSB of Frequency Tuning Word
uint16_t FRQHW = 0;    // LSB of Frequency Tuning Word
uint16_t  phaseVal=0;  // Phase Tuning Value    uint32_t idi
uint8_t WKNOWN=0,init=1;      // Flag Variable
extern float frqfl,phsfl;
// -------------------------------- Functions --------------------------------
void Delay(volatile uint32_t delay){
    while(delay--){};
}
// ------------------------------------------------ Software SPI Function
void writeSPI(uint16_t word) {
    HAL_GPIO_WritePin(AD9833PORT,AD9833SS,GPIO_PIN_RESET);
    /*ASM_NOP();ASM_NOP();*/Delay(1);
    for (uint8_t i = 0; i < 16 ; i++) {
        Delay(1);
        if(word & 0x8000) HAL_GPIO_WritePin(AD9833PORT,AD9833DATA,GPIO_PIN_SET);   //bit=1, Set High
        else HAL_GPIO_WritePin(AD9833PORT,AD9833DATA,GPIO_PIN_RESET);        //bit=0, Set Low
          /*ASM_NOP(); ASM_NOP();*/Delay(1);
        HAL_GPIO_WritePin(AD9833PORT,AD9833SCK,GPIO_PIN_RESET);             //Data is valid on falling edge
         /*ASM_NOP(); ASM_NOP();*/Delay(1);
        HAL_GPIO_WritePin(AD9833PORT,AD9833SCK,GPIO_PIN_SET);
        word = word<<1; //Shift left by 1 bit
        }
    HAL_GPIO_WritePin(AD9833PORT,AD9833DATA,GPIO_PIN_RESET); //Idle low
    /*ASM_NOP();ASM_NOP();*/Delay(1);
    HAL_GPIO_WritePin(AD9833PORT,AD9833SS,GPIO_PIN_SET);
    Delay(1);
}

// ------------------------------------------------ Sets Output Wave Type
void AD9833_SetWave(uint16_t Wave){
  switch(Wave){        // SYNC ?
  case 0:
//  HAL_GPIO_WritePin(AD9833PORT,AD9833SS,GPIO_PIN_RESET);
    writeSPI(0x2000); // Value for Sinusoidal Wave
//    HAL_GPIO_WritePin(AD9833PORT,AD9833SS,GPIO_PIN_SET);
    WKNOWN=0;
    break;
  case 1:
   //  HAL_GPIO_WritePin(AD9833PORT,AD9833SS,GPIO_PIN_RESET);
    writeSPI(0x2028); // Value for Square Wave
  //  HAL_GPIO_WritePin(AD9833PORT,AD9833SS,GPIO_PIN_SET);
    WKNOWN=1;
    break;
  case 2:
   //     HAL_GPIO_WritePin(AD9833PORT,AD9833SS,GPIO_PIN_RESET);
    writeSPI(0x2002); // Value for Triangle Wave
  //  HAL_GPIO_WritePin(AD9833PORT,AD9833SS,GPIO_PIN_SET);
    WKNOWN=2;
    break;
  default:
    break;
  }
}

// ------------------------------------------------ Sets Wave Frequency & Phase (In Degree) In PHASE0 & FREQ0 Registers
void AD9833_SetWaveData(uint8_t sel){
    float Frequency,Phase;
Delay(5);
    Frequency=frqfl;Phase=phsfl;
 // ---------- Tuning Word for Phase ( 0 - 360 Degree )
 if(Phase<0)Phase=0; // Changing Phase Value to Positive
 if(Phase>360)Phase=360; // Maximum value For Phase (In Degree)
 phaseVal  = ((int)(Phase*(4096/360)));
 if(sel==0)phaseVal|=0XC000;  // 4096/360 = 11.37 change per Degree for Register And using 0xC000 which is Phase 0 Register Address
 if(sel==1)phaseVal|=0XE000;
 // ---------- Tuning word for Frequency
long freq=0;
freq=(int)(((Frequency*pow(2,28))/FMCLK)+1); // Tuning Word
FRQHW=(int)((freq & 0xFFFC000) >> 14); // FREQ MSB
FRQLW=(int)(freq & 0x3FFF);  // FREQ LSB
if (sel==0)FRQLW |= 0x4000;
if (sel==0)FRQHW |= 0x4000;
if (sel==1)FRQLW |= 0x8000;
if (sel==1)FRQHW |= 0x8000;

 // ------------------------------------------------ Writing DATA
 HAL_GPIO_WritePin(AD9833PORT,AD9833DATA,GPIO_PIN_SET);
 HAL_GPIO_WritePin(AD9833PORT,AD9833SCK,GPIO_PIN_SET);
    //HAL_GPIO_WritePin(AD9833PORT,AD9833SS,GPIO_PIN_SET);
    //HAL_GPIO_WritePin(AD9833PORT,AD9833SS,GPIO_PIN_RESET); //low = selected
    Delay(1);
    //if(init) writeSPI(0x2100); // enable 16bit words and set reset bit !!!once 0x2000 yolla
    writeSPI(0x2028);
    writeSPI(FRQLW);
    writeSPI(FRQHW);
    writeSPI(phaseVal);

    writeSPI(0x2028);
   // if(init) writeSPI(0x2000); // clear reset bit
    //Delay(5);
    //HAL_GPIO_WritePin(AD9833PORT,AD9833SS,GPIO_PIN_SET); //high = deselected
    //AD9833_SetWave(WKNOWN);
//Delay(1);
init=0;
return;
}

// ------------------------------------------------ Initializing AD9833
void AD9833_Init(/*uint16_t WaveType,float FRQ,float Phase*/void){
//    float FRQ,Phase;
HAL_GPIO_WritePin(AD9833PORT,AD9833DATA,GPIO_PIN_SET); // Set All SPI pings to High
HAL_GPIO_WritePin(AD9833PORT,AD9833SCK,GPIO_PIN_SET);  // Set All SPI pings to High
HAL_GPIO_WritePin(AD9833PORT,AD9833SS,GPIO_PIN_SET);   // Set All SPI pings to High
AD9833_SetWave(1);//WaveType);                              // Type Of Wave
//FRQ= frqfl;Phase=phsfl;
AD9833_SetWaveData(0);
AD9833_SetWaveData(1);
//FRQ,Phase);                         // Frequency & Phase Set
return;
}
C:
  MX_GPIO_Init();
  /* USER CODE BEGIN 2 */
//  NVIC_Configuration();
 writeSPI(0x2100);    HAL_Delay(100); writeSPI(0x2000);
 AD9833_Init();
 
 //  uint8_t buffer[64];
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
//showtime();
      HAL_Delay(100);
      HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_13);
//      disptimer++;
      frqfl=20150.0F;phsfl=100.0F;

        AD9833_SetWaveData(0);
 

Hi,

1) I init AD9833 at the beginning of main
sorry, I can not find your main() function, not even with the search function (CTRL + F). So we do not know what's going on in you man().

I still do not see a single instruction where you have reset the DDS. Please have a look at the example given in [1].

I have used the AD9837 (almost identical to the AD9833) quite a while ago. I used it to generate sine-waves and everything worked fine.
I checked my code. I used SPI with a frequency of 2.5 MHz, CPHA=0, CPOL=1, and I performed the reset by 0x2100 (sine-wave).

[1] https://www.analog.com/media/en/technical-documentation/application-notes/AN-1070.pdf?doc=AD9833.pdf

BR
 
Thank you all for your advices
it worked with HW SPI ( why it didnot work with SW SPI - it took my 3 weeks - the examples I found in the internet misleaded me )

I reset it here - from my original post ( writeSPI functions )

AD9833-6.png
 
Last edited:

Hi,

Why the screenshot? When you "refer to post#1" it's just 16 bytes ... the screenshot is 2000 times the size ... without benefit

HW vs SW SPI generally makes no difference. What counts is: timing and data.

Klaus
 
Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top