AnsweredAssumed Answered

FRDM-KL25Z with AD9850 DDS

Question asked by juanm on Mar 8, 2015
Latest reply on Mar 15, 2015 by juanm

Hi! I have a cheap AD9850 module but I'm having troubles interfacing it with the FRDM-KL25Z board.

I found this mbed code:

 

AD9850-function-generator-SPI-driver - a mercurial repository | mbed

 

I tried it with my board and it works. I ported the code to a Coldfire V1 JM128 and it works, but when I try to port it to the FRDM-KL25Z with Codewarrior v10.6 it doesn't work... so I think I'm doing something wrong in the initialization of the peripherals.

Here is my code for the FRDM-KL25Z:

 

#include "derivative.h" /* include peripheral declarations */

#include "mcg.h"
#include "lptmr.h"

// PTA13 - Reset
// PTD0 - Chip Select

#define CS_ON  GPIOD_PSOR = (1<<0)
#define CS_OFF   GPIOD_PCOR = 1<<0 

#define ADReset_ON  GPIOA_PSOR = (1<<13)
#define ADReset_OFF   GPIOA_PCOR = 1<13 

unsigned long int reverseBits (unsigned long int source);
void SPI_InitMaster( void );
void writeSPI(unsigned long int frq, unsigned char phase);
void CLK_init(void);

int main(void)
{  
  SIM_COPC = SIM_COPC_COPT(0x00); /* Disable the WDOG module */
  pll_init(8000000, LOW_POWER, CRYSTAL,4,24,MCGOUT); //Core Clock is now at 48MHz using the 8MHZ Crystal ((8MHz/4)*24)
  lptmr_init(10000, 0);   
  SPI_InitMaster();

    // This routine produces a continuous frequency sweep
   unsigned long int targetFrq=0x147AE148; // Frequency word = ([Desired freq in MHz] * 34.3597384)
   unsigned long int increment=0xD6B; //100Hz step
    
    // Reset the AD9850. Active high logic. Minimum reset period 5 clock cycles (5/125MHz)
    ADReset_OFF;
    time_delay_ms(5);
    ADReset_ON;
    time_delay_ms(5);
    ADReset_OFF;

  for(;;) {   

  while (targetFrq<0x148bFFFF) // up to 10.001MHz
     {
         writeSPI(reverseBits(targetFrq),0); // Don't use phase so set to zero.
         targetFrq=targetFrq+increment;
        
     }
         
     while (targetFrq>0x147AE148) // down to 10MHz
     {
         writeSPI(reverseBits(targetFrq),0);
         targetFrq=targetFrq-increment;
        
     }  
     
         
  }

  return 0;
}




/****************************************************************
                  initial the spi module to master mode
*****************************************************************/
void SPI_InitMaster( void )
{
  // enable clock gate for spi module
   SIM_SCGC4 |= SIM_SCGC4_SPI0_MASK;
   
   // enable PORT
   SIM_SCGC5 |= SIM_SCGC5_PORTD_MASK|SIM_SCGC5_PORTA_MASK;

  // disable SPI
  SPI0_C1 &= ~SPI_C1_SPE_MASK;

  // configure I/O to SPI function
  //PORTD_PCR0 &= ~PORT_PCR_MUX_MASK;
  //PORTD_PCR0 |= PORT_PCR_MUX(2)|PORT_PCR_DSE_MASK;  //Use PTD0 as SPI0_SS_b

  PORTD_PCR0 = PORT_PCR_MUX(1) | PORT_PCR_DSE_MASK;  //PTD0 es SS
  PORTA_PCR13 = PORT_PCR_MUX(1) | PORT_PCR_DSE_MASK;  //PTA13 es Reset
  GPIOD_PDDR |=  (1<<0);
  GPIOA_PDDR |=  (1<<13);

    PORTD_PCR3 &= ~PORT_PCR_MUX_MASK;
  PORTD_PCR3 |= PORT_PCR_MUX(2)|PORT_PCR_DSE_MASK;  //Use PTD3 as SPI0_MISO

    PORTD_PCR2 &= ~PORT_PCR_MUX_MASK;
  PORTD_PCR2 |= PORT_PCR_MUX(2)|PORT_PCR_DSE_MASK;  //Use PTD2 as SPI0_MOSI

    PORTD_PCR1 &= ~PORT_PCR_MUX_MASK;
  PORTD_PCR1 = PORT_PCR_MUX(2)|PORT_PCR_DSE_MASK;    //Use PTD1 as SPI0_SCK

  SPI0_C1 |= SPI_C1_MSTR_MASK;


  SPI0_BR = 0b01010001; //Divido por 6 y despues por 4 entonces si el BUS CLK = 24 MHz, el SPI CLK = 1 MHz


  //SPI0_C1 |= SPI_C1_SSOE_MASK;      
  //SPI0_C2 |= SPI_C2_MODFEN_MASK;

  SPI0_C1 &= ~SPI_C1_SSOE_MASK;      
  SPI0_C2 &= ~SPI_C2_MODFEN_MASK;


  //SPI0_C1 |= SPI_C1_CPHA_MASK;
  SPI0_C1 &= (~SPI_C1_CPHA_MASK); //CPHA = 0
  //SPI0_C1 |= SPI_C1_CPOL_MASK;
  SPI0_C1 &= (~SPI_C1_CPOL_MASK); //CPOL = 0
  //SPI0_C1 |= SPI_C1_LSBFE_MASK;
  SPI0_C1 &= (~SPI_C1_LSBFE_MASK); //MSB

  SPI0_C1 |= SPI_C1_SPE_MASK; //Activa SPI
}

unsigned long int reverseBits (unsigned long int source)
{
// Unfortunately need to invert bit order of the desired frequency setting since MBED only allows for MSB first from SPI. We need LSB first for AD9850
    unsigned long int mask=0;;
    int i=0;
    unsigned long int target=0;
    unsigned long int bitTarget=0x80000000; // Hard-wired for 32-bit inversion


    for (i=0;i<32;i++) { // ditto
        mask=1<<i;    
        bitTarget=1<<(31-i); // ditto


        if (source & mask)
            target=target | bitTarget;
    } 
    return target;
}    


void writeSPI(unsigned long int frq, unsigned char phase)
{           
// Send the 40-bit packet. NB: KL25Z only supports 8-bit SPI so send five 8-bit packets
    
    // First do chip select. Need to use a GPIO to fake the chip select since MBED doesn't allow to set positive logic CS signal
    CS_ON; // assert chip select (a.k.a FQ_UD frequency update input to AD9850)
    time_delay_ms(1);
    CS_OFF;
        
    while(!(SPI0_S & SPI_S_SPTEF_MASK ) )
         {
              asm("nop");
         }
    
    SPI0_D = frq>>24;


    while(!(SPI0_S & SPI_S_SPTEF_MASK ) )
         {
              asm("nop");
         }
    
    SPI0_D = frq>>16;
    
    while(!(SPI0_S & SPI_S_SPTEF_MASK ) )
         {
              asm("nop");
         }
    
    SPI0_D = frq>>8;
    while(!(SPI0_S & SPI_S_SPTEF_MASK ) )
         {
              asm("nop");
         }
    
    SPI0_D = frq;
    while(!(SPI0_S & SPI_S_SPTEF_MASK ) )
         {
              asm("nop");
         }
    
    SPI0_D = phase;


    // Now pulse FQ_UD again to load the word into the DDS
    CS_OFF;
    time_delay_ms(1);
    CS_ON;
    time_delay_ms(1);
    CS_OFF;
}

 

The delay and clock initialization routines are from the lptmr and mcg libraries provided by Freescale.

Thanks in advance!

Outcomes