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,143
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
 

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





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 )

 
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.
Cookies are required to use this site. You must accept them to continue using the site. Learn more…