|
|
View previous topic :: View next topic |
Author |
Message |
marcoscab1166
Joined: 19 May 2019 Posts: 6
|
Help translating AD9833 code from C18 (?) to CCS |
Posted: Thu Jan 02, 2020 8:05 am |
|
|
Hi, i found this code on some chinese website for the AD9833 spi comunication.
I liked it because it seems preety simple, at least for start.
But im having troubles translating it to CCS. If anyone can help me with this ill be thankfull.
Or, if you have already a library for the AD9833 writen for CCS ill be even more thankfull.
The code:
Code: |
#include<p18f4550.h>
void ConfigureProcessor (void); /* Configuring the processor for 8 Mhz internal clock */
void SpiComm (void); /* Function for SPI transmission */
void ConfigureSPI (void); /* Configuring the SPI Module */
unsigned char WriteSPI ( unsigned char );
void main (void)
{
ConfigureProcessor();
ConfigureSPI();
while(1)
{
SpiComm();
}
}
void ConfigureProcessor (void)
{
OSCTUNEbits.INTSRC = 0;
OSCCONbits.SCS0 = 0;
OSCCONbits.SCS1 = 1;
OSCCONbits.IRCF0 = 1; /* 8 MHz Internal Clock */
OSCCONbits.IRCF1 = 1;
OSCCONbits.IRCF2 = 1;
INTCON2bits.RBPU = 0;
PORTEbits.RDPU = 0;
TRISB = 0;
STATUS = 0;
}
void ConfigureSPI (void)
{
TRISBbits.TRISB1 = 0; /* SCK = Output */
TRISBbits.TRISB0 = 1; /* SDI = Output, as PIC is only doing SPI transmission */
/* in master mode, So configured with opposite value */
TRISCbits.TRISC7 = 0; /* SDO = Output */
TRISAbits.TRISA5 = 0; /* SS pin disabled as SPI is in master mode */
SSPSTATbits.CKE = 0; /* Data is transmitted on falling clock edge as per AD9833 datasheet */
SSPSTATbits.SMP = 0; /* Sampling of data occurs in the middle */
SSPCON1 = 0x30; /* SSPSEN = 1 and Clock Idle is HIGH, and FOSC/4 */
}
void SpiComm (void)
{
PORTBbits.RB2 = 0; /* Making FSYNC of AD9833 LOW before writing to Control Register */
WriteSPI(0b00100001); /* D15 - D8, Writing to Control Regsiter */
WriteSPI(0b00000000); /* Setting for Sine Wave Output D5 = 0, and D1 = 0*/
PORTBbits.RB2 = 1; /* Making FSYNC of AD9833 HIGH after writing 16 bits to Control Register */
// Here I am Writing 01100010010011 (D13 - D0), 14 LSB bits to FREQ0 Register
PORTBbits.RB2 = 0; /* Making FSYNC of AD9833 LOW before writing the 14 bit LSBs to FREQ0 */
WriteSPI(0b01011000); /* D15 = 0, D14 = 1 represents FREQ0 and D13 to D0 represents 14 LSBs */
WriteSPI(0b10010011); /* D7 - D0 */
PORTBbits.RB2 = 1; /* Making FSYNC of AD9833 HIGH after writing the 14 bit LSBs to FREQ0 */
// Here I am writing 00000000000010 (D13 to D0), 14 MSB bits to FREQ0 Register
PORTBbits.RB2 = 0; /* Making FSYNC of AD9833 LOW before writing the 14 bit MSBs to FREQ0 */
WriteSPI(0b01000000); /* D15 = 0, D14 = 1 represents FREQ0 and D13 to D0 represents 14 MSBs */
WriteSPI(0b00000010); /* D7 - D0 */
PORTBbits.RB2 = 1; /* Making FSYNC of AD9833 HIGH after writing the 14 bit MSBs to FREQ0 */
PORTBbits.RB2 = 0; /* Making FSYNC of AD9833 LOW before writing to the Phase Register */
WriteSPI(0b11000000); /* Configured for Zero Degree Phase Shift */
WriteSPI(0b00000000);
PORTBbits.RB2 = 1; /* Making FSYNC of AD9833 HIGH after writing to the Phase Register */
PORTBbits.RB2 = 0; /* Making FSYNC of AD9833 LOW before writing to Control Register, HERE RESETTING THE AD9833, as D8 = 0 */
WriteSPI(0b00100000); /* D15 - D8, Writing to Control Regsiter */
WriteSPI(0b00000000); /* Setting for Sine Wave Output */
PORTBbits.RB2 = 1; /* Making FSYNC of AD9833 HIGH after writing 16 bits to Control Register */
}
unsigned char WriteSPI( unsigned char data_out ) /* From C18 Compiler Library */
{
SSPBUF = data_out; // write byte to SSPBUF register
if ( SSPCON1 & 0x80 ) // test if write collision occurred
return ( -1 ); // if WCOL bit is set return negative #
else
{
while( !SSPSTATbits.BF ); // wait until bus cycle complete
}
return ( 0 ); // if WCOL bit is not set return non-negative#
}
|
|
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9226 Location: Greensville,Ontario
|
|
Posted: Thu Jan 02, 2020 8:21 am |
|
|
Sorry I don't hve that peripheral to test with, but....You should look at the examples CCS supplies as well as the manual. From those, you'll be able to reduce that cumbersome code into 4-6 lines of CCS C !
One 'trick' is to copy the 'SPI mode defines' posted here. Maybe 'search' for them as I can't recall if they're in this forum or the 'code library. |
|
|
marcoscab1166
Joined: 19 May 2019 Posts: 6
|
|
Posted: Thu Jan 02, 2020 5:46 pm |
|
|
Ok, so i get tired of trying to translate. I started my own code with some pieces of other peoples code.
Most of the things come from here
https://www.ccsinfo.com/forum/viewtopic.php?t=54297
And this other link, that is on the topic above but i think its very important for people to read it all.
http://hades.mech.northwestern.edu/index.php/Waveform_Generation_with_AD9833
Sorry for creating another topic about this, but i'm trying to make it more like a library so other people can have a little easier job.
Tomorrow i'll be testing it with the AD9833 module, but for now the SPI function works pretty well.
After testing it and correcting the probable issues im gonna upload the fixed version and data of tests.
Code: |
// D15, D14
#define FREQ1_WR set(control_reg, 15);clear(control_reg, 14)
#define FREQ0_WR clear(control_reg, 15);set(control_reg, 14)
#define PHASE set(control_reg, 15);set(control_reg, 14)
#define CONTROL clear(control_reg, 15);clear(control_reg, 14)
// D13 if D15, D14 = 00
#define INDIVIDUAL clear(control_reg, 13)
#define CONSECUTIVELY set(control_reg, 13)
// D13 if D15, D14 = 11
#define PHASE0_WR 0 clear(control_reg, 13)
#define PHASE1_WR 1 set(control_reg, 13)
// D12
#define LSB_IND clear(control_reg, 12)
#define MSB_IND set(control_reg, 12)
// D11
#define FREQ0_OUT clear(control_reg, 11)
#define FREQ1_OUT set(control_reg, 11)
// D10
#define PHASE0_OUT clear(control_reg, 10)
#define PHASE1_OUT set(control_reg, 10)
//D9 is reserved, is 0
// D8
#define RES_OFF clear(control_reg, 8)
#define RES_ON set(control_reg, 8)
// D7
#define INTCLK_ON clear(control_reg, 7)
#define INTCLK_OFF set(control_reg, 7)
// D6
#define DAC_ON clear(control_reg, 6)
#define DAC_OFF set(control_reg, 6)
// D5
#define OUT_SQ set(control_reg, 5)
#define OUT_D1 clear(control_reg, 5)
// D4 is reserved, must be 0
// D3
#define SQ_DIV2 clear(control_reg, 3)
#define SQ_NRML set(control_reg, 3)
// D2 reserved, must be 0
// D1 if D5 is 1
#define OUT_D5 clear(control_reg, 1)
#define OUT_SN clear(control_reg, 1)
#define OUT_TR set(control_reg, 1)
// D0 is reserved, must be 0
#define SQUARE 0
#define SINE 1
#define TRIANGULAR 2
unsigned int16 control_reg;
unsigned int16 module_config[2];
int8 signal_type = SQUARE;
#define spi_14(x) spi_xfer(AD9833, (x & 0x3FFF) | 0x4000 , 16) //for frequency registers
#define spi_15(x) spi_xfer(AD9833, (x & 0x3FFF) | 0xC000 , 16) //for phase registers
// To determine in wich unit will be passed the frequency ( MHz, KHz or just Hz)
// change the following define:
// 1 for MHz, 1000 for KHz and 1000000 for Hz
#define FREQ_EXP 1 //
void AD9833_set(unsigned int module, unsigned int32 frequency, unsigned int32 phase_rad, signal_type){
float frequency_register;
float phase_register;
CONTROL;
CONSECUTIVELY;
LSB_IND;
FREQ0_OUT;
PHASE0_OUT;
RES_ON;
INTCLK_ON;
SQ_NRML;
if(signal_type==SQUARE){
DAC_OFF;
OUT_SQ;
OUT_D5;
} else if(signal_type==SINE){
DAC_ON;
OUT_D1;
OUT_SN;
} else if(signal_type==TRIANGULAR){
DAC_ON;
OUT_D1;
OUT_TR;
}
spi_xfer(AD9833, control_reg , 16);
frequency_register = (frequency * 268435456) / ( 25 * FREQ_EXP);
//Do the maths to send 28bits to freg - more reliable than DIY
spi_14((unsigned int32)frequency_register); //send 14 LSb's
spi_14(((unsigned int32)frequency_register>>14)); //then the next 14 bits
phase_register=(phase_rad * 4096) / 360;
spi_15((unsigned int32)phase_register); //send 12 bits of phase
RES_OFF;
spi_xfer(AD9833, control_reg , 16);
module_config[module]=control_reg;
module_frequency[module]=frequency;
}
|
|
|
|
marcoscab1166
Joined: 19 May 2019 Posts: 6
|
|
Posted: Sun Jan 05, 2020 3:58 pm |
|
|
Well, i fixed the code in the last message, changing the formula to convert the frequency value in MHz, KHz or Hz to their respective register values.
The unit that will be considered is set by the #define FREQ_EXP.
It also can be changed to use a variable so you can change the unit on the go, but i work just in MHz on this case so i preferred to keep it that way.
I dunno if the phase formula works properly, so if anyone wants to keep an eye on that, I'll be thankful. I'm in a rush for finishing this job and the phase register is not relevant for me right now. |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|