FRDM-KL25Z with AD9850 DDS

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

FRDM-KL25Z with AD9850 DDS

Jump to solution
1,839 Views
juanm
Contributor III

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!

0 Kudos
Reply
1 Solution
1,381 Views
juanm
Contributor III

I finally solved the problem! I was watching all the SPI signals on the oscilloscope as you suggested, but everything was ok. Then, I decided to look at the reset signal, but it wasn't cleared in the initialization, then I found the error... in line 13 of my code I wrote:

#define ADReset_OFF   GPIOA_PCOR = 1<13


I missed one of this characters: <

It should be:

#define ADReset_OFF   GPIOA_PCOR = 1 << 13


It's working now. Thanks for your help!

View solution in original post

0 Kudos
Reply
4 Replies
1,381 Views
Hui_Ma
NXP TechSupport
NXP TechSupport

Hi,

Please refer attached KL25 SPI master/slave example code attached.

Wish it helps.


Have a great day,
best regards,

Ma Hui

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

1,381 Views
juanm
Contributor III

Thanks for the code. I have seen the SPI initialization, but I can't find any differences between your attached code and mine (with the exception that I'm using a GPIO as SS).

Any ideas?

0 Kudos
Reply
1,381 Views
Hui_Ma
NXP TechSupport
NXP TechSupport

Hi,

Could you get any signal output from KL25 SPI port with scope? If the SPI communication signals as expected?


Have a great day,
best regards,

Ma Hui

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

1,382 Views
juanm
Contributor III

I finally solved the problem! I was watching all the SPI signals on the oscilloscope as you suggested, but everything was ok. Then, I decided to look at the reset signal, but it wasn't cleared in the initialization, then I found the error... in line 13 of my code I wrote:

#define ADReset_OFF   GPIOA_PCOR = 1<13


I missed one of this characters: <

It should be:

#define ADReset_OFF   GPIOA_PCOR = 1 << 13


It's working now. Thanks for your help!

0 Kudos
Reply