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.

Problem coding using SPI in dspic30f6010A

Status
Not open for further replies.

syamin0712

Member level 1
Joined
Jan 2, 2015
Messages
36
Helped
0
Reputation
0
Reaction score
0
Trophy points
6
Activity points
406
Hi,

I need some help to guide or overcome the error in writing coding that I have using MPlab.


Actually, I want to use dspic30f6010A as SPI Master, Frame master to communicate with my programmable waveform generator, AD9833.
I would like to produce sinewaveform with 2MHz.

Before this, I'm used the CCS C Compiler software to write the code and it was successfull.The micocontroller that Im used was PIC18f4580.
However, due to some reason, I would like to write the code using MPLAB with dspic30f family and I'm quite new with writing the code using MPLAB.

This is the code that I have before this by using PIC18F4580:
#include <18F4580.h> //This both defines the chip, and includes everything.
#fuses HS,NOWDT,NOPROTECT,NOLVP,NODEBUG

#use delay(clock=20000000)
#use spi(SPI1, MODE=2, ENABLE=PIN_E2, STREAM=AD9833)

#define RESET 0x0100 //initialize reset bit D8=1
#define WRITE_FREQ0 0x2000 //initialize LSB & MSB write consecutively, D13=1
#define RUN 0 //intialize give output after reset off
#define PHASE0_ZERO 0xC000 //initalize PHASE0 use
#define spi_14(x) spi_xfer(AD9833,(x & 0x3FFF) | 0x4000,16)
//0x4000 is the register for FREQ0

void write_val_freq0(int32 divisor)
{
//Do the maths to send 28bits to freg - more reliable than DIY
spi_14(divisor); //send 14 LSb's
spi_14((divisor>>14)); //then the next 14 bits
}

void main()
{
setup_adc_ports(NO_ANALOGS); //E2 is an analog pin - make sure this
//is setup to digital.
while(TRUE)
{
// activate control register; both LSB & MSB FREQ write consecutively
// enable reset
spi_xfer(AD9833, RESET | WRITE_FREQ0, 16);

//on FREQ0 for generate 2MHz if using MCLK=20MHz for AD9833
//26843545 in decimal
write_val_freq0(26843545); //setup FREQ0

//on PHASE0 with zero phase shift
spi_xfer(AD9833, PHASE0_ZERO, 16);

//activate control register
//disable reset; enable sinewaveform signal
spi_xfer(AD9833, RUN, 16);

//generally you don't want to keep sending data to chips 'non stop'...
//with your existing code, only a few uSec after getting here, the chip
//would be programmed back to RESET, so the waveform would stop
//since the waveform doesn't start till 8 clocks after the RESET
//goes off, there would be almost nothing on the output.....
delay_ms(1000); //output the waveform for a second
}
}

And what I'm going to do in MPLAB is actually the same code. I had set the SPI2 as the SPI module.
This is my code:
#include <p30f6010A.h>
#define FCY 117920000UL
#include <libpic30.h>

_FOSC(CSW_FSCM_OFF & FRC_PLL16); //use internal clock with PLLx16
_FWDT(WDT_OFF);
_FBORPOR(MCLR_EN & PWRT_OFF);


// AD9833 SPI Slave Device
#define unsigned int x
#define SPI_read x
#define SPI_SLAVE_WRITE 0x4000
#define SPI_14(x)

// AD9833 Registers Definition
#define RESET 0x0100 //initialize reset bit D8=1
#define WRITE_FREQ0 0x2000 //initialize LSB & MSB write consecutively, D13=1
#define RUN 0 //intialize give output after reset off
#define PHASE0_ZERO 0xC000 //initalize PHASE0 use

/* Initial the dspic30f6010A SPI Peripheral */
TRISGbits.TRISG9 = 0; //Output RG9/SS2
TRISGbits.TRISG6 = 0; //Output RG6/SCK2
TRISGbits.TRISG8 = 0; //Output RG6/SDO2

/* SPI2 Register Settings */
SPI2CONbits.DISSDO = 0; //SDO2 pin is controlled by the module.
SPI2CONbits.MODE16 = 1; //Communication is word-wide (16 bits).
//setting for SPI mode 2, CKP=1,CKE=0
SPI2CONbits.CKP = 1; //Clock polarity select. Idle is high
SPI2CONbits.CKE = 0; //Clock edge select bit to 1
//SPI Master,Frame Master Mode; MSTEN=1,FRMEN=1,SPIFSD=0
SPI2CONbits.MSTEN = 1; //Master Mode Enabled
SPI2CONbits.FRMEN = 1; // Enable pin SCK2 as output. Active low
SPI2CONbits.SPIFSD = 0; //SS2 is the output pin
SPI2STATbits.SPIEN = 1; //Enable SPI Module

void SPI_Write(unsigned int addr) //function to write
{
// Activate the SS2 SPI Select pin
PORTGbits.RG9 = 0;
// Start AD9833 OpCode transmission
SPI2BUF = (SPI_read & 0x3FFF)| SPI_SLAVE_WRITE;
// Wait for Data Transmit/Receipt complete
while(!SPI2STATbits.SPITBF);
// Start AD9833 Register Address transmission
SPI2BUF = addr;
// Wait for Data Transmit/Receipt complete
while(!SPI2STATbits.SPITBF);
// SS2 pin is not active
PORTGbits.RG9 = 1;;
}

void write_val_freq0(unsigned int divisor) //function to do the maths to send 28 bits to freq0
{
SPI_14(divisor);
SPI_14((divisor>>14));
}


int main(void)
{

while (1)
{
SPI_Write(RESET|WRITE_FREQ0); //activate control register and enable reset
write_val_freq0(26843545); //on FREQ0 for freq 2MHz; 26843545 in decimal using formula=2^28x2M/20M, 20M is MCL for AD9833
SPI_Write(PHASE0_ZERO); //on PHASE0 with zero phase shift
SPI_Write(RUN); //activate control register and disable reset

__delay_ms(1000);
}
}

I did not have any more idea how to solve the error. Does the way code written is correct?
Really appreciate any help.

The error appears:
error.jpg
 

the following
Code:
TRISGbits.TRISG9 = 0; //Output RG9/SS2
TRISGbits.TRISG6 = 0; //Output RG6/SCK2
TRISGbits.TRISG8 = 0; //Output RG6/SDO2
are executable statements, put them inside a function
 

the following
Code:
TRISGbits.TRISG9 = 0; //Output RG9/SS2
TRISGbits.TRISG6 = 0; //Output RG6/SCK2
TRISGbits.TRISG8 = 0; //Output RG6/SDO2
are executable statements, put them inside a function

HI,

I have change and put them in the int main (void function).
int main(void)
{
/* Initial the dspic30f6010A SPI Peripheral */
TRISGbits.TRISG9 = 0; //Output RG9/SS2
TRISGbits.TRISG6 = 0; //Output RG6/SCK2
TRISGbits.TRISG8 = 0; //Output RG6/SDO2

/* SPI2 Register Settings */
SPI2CONbits.DISSDO = 0; //SDO2 pin is controlled by the module.
SPI2CONbits.MODE16 = 1; //Communication is word-wide (16 bits).
//setting for SPI mode 2, CKP=1,CKE=0
SPI2CONbits.CKP = 1; //Clock polarity select. Idle is high
SPI2CONbits.CKE = 0; //Clock edge select bit to 1
//SPI Master,Frame Master Mode; MSTEN=1,FRMEN=1,SPIFSD=0
SPI2CONbits.MSTEN = 1; //Master Mode Enabled
SPI2CONbits.FRMEN = 1; // Enable pin SCK2 as output. Active low
SPI2CONbits.SPIFSD = 0; //SS2 is the output pin
SPI2STATbits.SPIEN = 1; //Enable SPI Module

while (1)
{
SPI_Write(RESET|WRITE_FREQ0); //activate control register and enable reset
write_val_freq0(26843545); //on FREQ0 for freq 2MHz; 26843545 in decimal using formula=2^28x2M/20M, 20M is MCL for AD9833
SPI_Write(PHASE0_ZERO); //on PHASE0 with zero phase shift
SPI_Write(RUN); //activate control register and disable reset

__delay_ms(1000);
}

}
However the same error is still occurred.
Does it correct the way I'm writing the code for variable x?
 

HI,

I have change and put them in the int main (void function).

However the same error is still occurred.
Does it correct the way I'm writing the code for variable x?
what is the error message you are getting
if I compile your code of post #3 using XC16 I get
Code:
Executing: "C:\Program Files (x86)\Microchip\xc16\v1.24\bin\xc16-gcc.exe" -omf=coff -mcpu=30F6010A -x c -c "test1.c" -o"test1.o" -I"." -I"Microchip\Include" -g -Wall
test1.c: In function 'main':
test1.c:44:1: warning: implicit declaration of function 'SPI_Write'
test1.c:45:1: warning: implicit declaration of function 'write_val_freq0'
test1.c:49:1: warning: implicit declaration of function '__delay_ms'
because you have not defined these functions
 

Hi,
The previous post was referred.
After 2 weeks did this coding by referring some example and notes such as:
http://www.analog.com/media/en/technical-documentation/application-notes/AN-1070.pdf


What I understand is that the dspic30f6010A will only becomes the master to send the data to the AD9833.

So, I have come out with this coding:

#include <p30f6010A.h>
#define FCY 117920000UL
#include <libpic30.h>

_FOSC(CSW_FSCM_OFF & FRC_PLL16);
_FWDT(WDT_OFF);
_FBORPOR(MCLR_EN & PWRT_OFF);
_FGS(GWRP_OFF);

/* Global Variables and Functions */
int main (void);
void Start_Init (void);

/* AD9833 define register */
unsigned long spi_send0=0x2100; //control register with LSB and MSB FREQ writes consequitively; D13=1,reset enable D8=1
unsigned long spi_send1=0x5999; // FREQ0 with LSB ,D15=0 n D14=1 followed by LSB value for 2MHz sine wave
unsigned long spi_send2=0x4666; // FREQ0 with MSB ,D15=0 n D14=1 followed by MSB value for 2MHz sine wave
unsigned long spi_send3=0xC000; // PHASE0 with zero, D15=D14=1
unsigned long spi_send4=0x2000; // control register, D13=1 and disable reset, D8=0
unsigned long data;

int main(void)
{
Start_Init(); /* Initialize start-up*/

/* Do to trigger AD9833 to produce 2MHz sinewaveform */
while(1) // Loop here forever
{

LATGbits.LATG9 = 0; //SS2/RG9 = 0
SPI2BUF = spi_send0; // Put control register enable reset value into buffer
while(SPI2STATbits.SPITBF); // Transmission complete?
data = SPI2BUF; // read from SPI2BUF to clear SPIRBF flag
LATGbits.LATG9 = 1; //SS2/RG9 = 1

LATGbits.LATG9 = 0; //SS2/RG9 = 0
SPI2BUF = spi_send1; // Put LSB FREQ0 value into buffer
while(SPI2STATbits.SPITBF); // Transmission complete?
data = SPI2BUF; // read from SPI2BUF to clear SPIRBF flag
LATGbits.LATG9 = 1; //SS2/RG9 = 1

LATGbits.LATG9 = 0; //SS2/RG9 = 0
SPI2BUF = spi_send2; // Put MSB FREQ0 value into buffer
while(SPI2STATbits.SPITBF); // Transmission complete?
data = SPI2BUF; // read from SPI2BUF to clear SPIRBF flag
LATGbits.LATG9 = 1; //SS2/RG9 = 1

LATGbits.LATG9 = 0; //SS2/RG9 = 1
SPI2BUF = spi_send3; // Put PHASE0 value into buffer
while(SPI2STATbits.SPITBF); // Transmission complete?
data = SPI2BUF;
LATGbits.LATG9 = 1; //SS2/RG9 = 1

LATGbits.LATG9 = 0; //SS2/RG9 = 0
SPI2BUF = spi_send4; // Put control register disable reset value into buffer
while(SPI2STATbits.SPITBF); // Transmission complete?
data = SPI2BUF;
LATGbits.LATG9 = 1; //SS2/RG9 = 1

__delay_ms(1000);
}
}
void Start_Init(void)
{
/*Config SPI2 as Master to communicate with AD9833 ic*/
TRISGbits.TRISG6 = 0; // SCK2 as output RG6
TRISGbits.TRISG8 = 0; // SDO2 as output RG8
TRISGbits.TRISG9 = 0; // SS2 as output

SPI2BUF = 0; // Clear Buffer1

SPI2CON = 0x043B; // Config SPI2 control register;
//FRMEN=0, SPIFSD=0,DISSDO=0,MODE16=1,SMP=0,CKE=0,SSEN=0,CKP=0 (mode 1),MSTEN=1,
//SPREN=prescale 6:1(110), PPREN=prescale 1:1 (11)

SPI2STAT = 0x8000; // Config SPI2 status register; SPIEN=1,SPISIDL=0,SPIROV=0,SPITBF=0,SPIRBF=0

SPI2CONbits.SPRE = 6; // Config secondory prescaler 6:1 (110)
SPI2CONbits.PPRE = 3; // Config primary prescaler 1:1 (11)

}

No error occurred. However, when I tested my output signal of AD9833 on the probe; the signal that I got was only around 44 kHz. What I want is actually 2 MHz sine waveform.
http://obrazki.elektroda.pl/3336942500_1457253318.jpg

Is the setting that I made is correct for the SPI initialization?Is there any configuration that I missed?
The FCY is 117.92 MHz. Thus, I'm used the primary prescaler 1:1 and secondary prescaler 6:1 because I want to send data at 20MHz.
The 20MHz is chosen because I'm use 20MHz for the clock for SCLK in AD9833. Is it correct what I understand about the prescaler?
This is because when I'm test the probe at SDO/RG8 and SCK/RG6 pin the output was in freq of 20MHz:

http://obrazki.elektroda.pl/5853256900_1457252761.jpg
http://obrazki.elektroda.pl/6850120400_1457252765.jpg


Also, does the way I wrote the code is correct? This AD9833 need the FOUR commons steps to generate the signal (enable reset in control register, FREQ0, value frequency register of signal interested, PHASE0 and disable reset in control register). The notes that I referred was:
http://hades.mech.northwestern.edu/index.php/Waveform_Generation_with_AD9833,_and_SPI
http://www.analog.com/media/en/technical-documentation/application-notes/AN-1070.pdf
http://www.analog.com/media/en/technical-documentation/data-sheets/AD9833.pdf

Any help will really appreciated.TQ.
 

The SPI waveforms look awful, is it your oscilloscope probe or bad signal ground on your PCB?
I would choose a lower data rate, at least for test.

Don't see obvious code faults.

I mean to remember that some PIC peripherals has problems to accept configuration while being enabled. I would always set SPIEN last.
 

The SPI waveform is from the oscilloscope probe. I mean the probe direct measure at pin RG8 for SDO and RG6 for SCK from dspic.

What do you mean by the lowest data rate? Is it the lower frequency for ad9833?

Do you mean the SPIEN is set in bit form after the line of PPREN setting?why?
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top