Hackster is hosting Hackster Holidays, Finale: Livestream & Giveaway Drawing. Watch previous episodes or stream live on Tuesday!Stream Hackster Holidays, Finale on Tuesday!
Grisha Anofriev
Published © TAPR-OHL

RF Signal Generator DDS 600MHz@1.5GHz Arduino Shield AD9910

The way to create a high-precision generator from 100 kHz to 600 MHz based on DDS from Analog Devices - AD9910.

BeginnerShowcase (no instructions)1 hour8,218
RF Signal Generator DDS 600MHz@1.5GHz Arduino Shield AD9910

Things used in this project

Hardware components

AD9910 Arduino Shield
×1
Arduino Mega 2560
Arduino Mega 2560
×1
0.96" OLED 64x128 Display Module
ElectroPeak 0.96" OLED 64x128 Display Module
×1
AD9910 Arduino Shield DDS9910
×1
1GHz Reference Oscillator TCXO Low Noise -130dBc/Hz at 10kHz
×1

Software apps and online services

Arduino IDE
Arduino IDE
DDS9912 Arduino Shield Firmware

Story

Read more

Schematics

Block Diagram

Code

AD9910.cpp

C/C++
most important functions
/*****************************************************************************
  Initialization DDS
  * Config SPI, Reset DDS and ReConfig SPI
  * Enable/Disable internal PLL, mux, div, charge pump current, Set VCO
  
    Input Parametr:
  * PLL - 1 enable, if 0 disable
  * Divider - This input REF CLOCK divider by 2, if 1 - Divider by 2, if 0 - Divider OFF
  * 
  * Set Current Output - 0..255, 127 - Default equal to 0 dB 
*****************************************************************************/
void DDS_Init(bool PLL, bool Divider, uint32_t Ref_Clk)
 {
   
   DDS_GPIO_Init();
   
   // It is very important for DDS AD9910 to set the initial port states
   HAL_GPIO_WritePin(DDS_MASTER_RESET_GPIO_PORT, DDS_MASTER_RESET_PIN, GPIO_PIN_SET);   // RESET = 1
   HAL_GPIO_WritePin(DDS_MASTER_RESET_GPIO_PORT, DDS_MASTER_RESET_PIN, GPIO_PIN_RESET); // RESET = 0
   HAL_GPIO_WritePin(DDS_IO_UPDATE_GPIO_PORT, DDS_IO_UPDATE_PIN, GPIO_PIN_RESET);       // IO_UPDATE = 0   
   HAL_GPIO_WritePin(DDS_SPI_CS_GPIO_PORT, DDS_SPI_CS_PIN, GPIO_PIN_SET);               // CS = 1
   HAL_GPIO_WritePin(DDS_OSK_GPIO_PORT, DDS_OSK_PIN, GPIO_PIN_SET);                     // OSK = 1
   HAL_GPIO_WritePin(DDS_PROFILE_0_GPIO_PORT, DDS_PROFILE_0_PIN, GPIO_PIN_RESET);
   HAL_GPIO_WritePin(DDS_PROFILE_1_GPIO_PORT, DDS_PROFILE_1_PIN, GPIO_PIN_RESET);
   HAL_GPIO_WritePin(DDS_PROFILE_2_GPIO_PORT, DDS_PROFILE_2_PIN, GPIO_PIN_RESET);
   
   DDS_SPI_Init();
   
   HAL_GPIO_WritePin(DDS_SPI_CS_GPIO_PORT, DDS_SPI_CS_PIN, GPIO_PIN_RESET);    
   strBuffer[0] = CFR1_addr;
   strBuffer[1] = 0;// RAM_enable;//RAM_Playback_Amplitude;// | RAM_enable;//0x00; 
   strBuffer[2] = 0;//Inverse_sinc_filter_enable;//0; //Continuous_Profile_0_1; //0;//0x80;//0x00;
   strBuffer[3] = 0; //OSK_enable | Select_auto_OSK;//0x00;
   strBuffer[4] = SDIO_input_only ;
   HAL_SPI_Transmit(&hspi1, (uint8_t*)strBuffer, 5, 1000);
   HAL_GPIO_WritePin(DDS_SPI_CS_GPIO_PORT, DDS_SPI_CS_PIN, GPIO_PIN_SET);
   
   DDS_UPDATE();
   
   HAL_GPIO_WritePin(DDS_SPI_CS_GPIO_PORT, DDS_SPI_CS_PIN, GPIO_PIN_RESET);    
   strBuffer[0] = CFR2_addr;
   strBuffer[1] = Enable_amplitude_scale_from_single_tone_profiles;//1;//0x00;
   strBuffer[2] = 0;//SYNC_CLK_enable;// | Read_effective_FTW;
   strBuffer[3] = 0;//0x08;//PDCLK_enable;
   strBuffer[4] = Sync_timing_validation_disable;// | Parallel_data_port_enable;
   HAL_SPI_Transmit(&hspi1, (uint8_t*)strBuffer, 5, 1000);
   HAL_GPIO_WritePin(DDS_SPI_CS_GPIO_PORT, DDS_SPI_CS_PIN, GPIO_PIN_SET);
   
   DDS_UPDATE();

  switch (PLL)
  {
    case false:
      /******************* External Oscillator 60 - 1000Mhz (Overclock up to 1500Mhz) ***************/ 
      HAL_GPIO_WritePin(DDS_SPI_CS_GPIO_PORT, DDS_SPI_CS_PIN, GPIO_PIN_RESET);    
      strBuffer[0] = CFR3_addr;
      strBuffer[1] = 0;//DRV0_REFCLK_OUT_High_output_current;//
      strBuffer[2] = 0;
      if (Divider) strBuffer[3] = REFCLK_input_divider_ResetB;
        else strBuffer[3] = REFCLK_input_divider_ResetB | REFCLK_input_divider_bypass;
      strBuffer[4] = 0; // SYSCLK= REF_CLK * N
      HAL_SPI_Transmit(&hspi1, (uint8_t*)strBuffer, 5, 1000);
      HAL_GPIO_WritePin(DDS_SPI_CS_GPIO_PORT, DDS_SPI_CS_PIN, GPIO_PIN_SET);
      DDS_UPDATE();
      //**************************
    break;
    case true:
      /******************* External Oscillator TCXO 3.2 - 60 MHz ***********************************************/ 
      HAL_GPIO_WritePin(DDS_SPI_CS_GPIO_PORT, DDS_SPI_CS_PIN, GPIO_PIN_RESET);    
      strBuffer[0] = CFR3_addr;
      strBuffer[1] = VCO5;  // | DRV0_REFCLK_OUT_High_output_current;
      strBuffer[2] = Icp287uA;   
      strBuffer[3] = REFCLK_input_divider_ResetB | PLL_enable; // REFCLK_input_divider_bypass; //
      strBuffer[4]=((uint32_t)DDS_Core_Clock/Ref_Clk)*2; // multiplier for PLL
      #if DBG==1
      Serial.print(F("PLL Multiplier="));
      Serial.println(strBuffer[4]);
      #endif
      HAL_SPI_Transmit(&hspi1, (uint8_t*)strBuffer, 5, 1000);
      HAL_GPIO_WritePin(DDS_SPI_CS_GPIO_PORT, DDS_SPI_CS_PIN, GPIO_PIN_SET);
      DDS_UPDATE();
    /**********************/
    break;
  }
   
   HAL_GPIO_WritePin(DDS_SPI_CS_GPIO_PORT, DDS_SPI_CS_PIN, GPIO_PIN_RESET);    
   strBuffer[0] = FSC_addr;
   strBuffer[1] = 0;
   strBuffer[2] = 0;
   strBuffer[3] = 0;
   if (DACCurrentIndex==0) strBuffer[4] = 0x7F; //DAC current Normal
    else strBuffer[4] = 0xFF;// Max carrent 255 = 31mA //DAC current HI
   HAL_SPI_Transmit(&hspi1, (uint8_t*)strBuffer, 5, 1000);
   HAL_GPIO_WritePin(DDS_SPI_CS_GPIO_PORT, DDS_SPI_CS_PIN, GPIO_PIN_SET);
   
   DDS_UPDATE();
   
   HAL_GPIO_WritePin(DDS_SPI_CS_GPIO_PORT, DDS_SPI_CS_PIN, GPIO_PIN_RESET);    
   strBuffer[0] = 0x0E;
   strBuffer[1] = 0x3F;
   strBuffer[2] = 0xFF;
   strBuffer[3] = 0x00;
   strBuffer[4] = 0x00;
   
   strBuffer[5] = 0x19;
   strBuffer[6] = 0x99;
   strBuffer[7] = 0x99;
   strBuffer[8] = 0x9A; // 100mhz
   HAL_SPI_Transmit(&hspi1, (uint8_t*)strBuffer, 9, 1000);
   HAL_GPIO_WritePin(DDS_SPI_CS_GPIO_PORT, DDS_SPI_CS_PIN, GPIO_PIN_SET);
   
   DDS_UPDATE(); 
}   

/*****************************************************************************************
   F_OUT - Set Frequency in HZ 
   Num_Prof - Single Tone Mode 0..7
   Amplitude_dB - amplitude in dB from 0 to -84 (only negative values)
*****************************************************************************************/
void DDS_Fout (uint32_t *F_OUT, int16_t Amplitude_dB, uint8_t Num_Prof)
{
   #if DBG==1
   Serial.print(F("*F_OUT="));
   Serial.println(*F_OUT); 
   Serial.print(F("DDS_Core_Clock="));
   Serial.println(DDS_Core_Clock); 
   float FoutByDDScore=(double)*F_OUT / (double)DDS_Core_Clock;
   Serial.print(F("FoutByDDScore="));
   Serial.println(FoutByDDScore, 6); 
   #endif
   
   FTW = ((uint32_t)(4294967296.0 *((float)*F_OUT / (float)DDS_Core_Clock)));
   jlob = & FTW;	

	 HAL_GPIO_WritePin(DDS_SPI_CS_GPIO_PORT, DDS_SPI_CS_PIN, GPIO_PIN_RESET); 	 
	 strBuffer[0] = Num_Prof; // Single_Tone_Profile_0;

   //ASF  - Amplitude 14bit 0...16127
	 strBuffer[1] =  (uint16_t)powf(10,(Amplitude_dB+84.288)/20.0) >> 8;     
	 strBuffer[2] =  (uint16_t)powf(10,(Amplitude_dB+84.288)/20.0);         
	 strBuffer[3] = 0x00;
	 strBuffer[4] = 0x00;
	 
	 strBuffer[5] = *(((uint8_t*)jlob)+ 3);
	 strBuffer[6] = *(((uint8_t*)jlob)+ 2);
	 strBuffer[7] = *(((uint8_t*)jlob)+ 1);
	 strBuffer[8] = *(((uint8_t*)jlob));
		
   HAL_SPI_Transmit(&hspi1, (uint8_t*)strBuffer, 9, 1000);
	 HAL_GPIO_WritePin(DDS_SPI_CS_GPIO_PORT, DDS_SPI_CS_PIN, GPIO_PIN_SET);
	 
	 DDS_UPDATE(); 
	 
}	

AD9910 Full repository for Arduino Mega 2560

Just compile, upload and have fun.

Credits

Grisha Anofriev
6 projects • 36 followers
Thanks to Arduino Team and Analog Devices.

Comments