Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

pic16f887 spi communication problem

Status
Not open for further replies.

andrei_p

New Member
hi every body.
i'm trying to build a function generator using a pic16f887 and ad9833. my first problem is that i don't find any eagle library for ad9833 and i can't simulate anything. the second is my mikroc program. i'm new in using mikroc. this project is a task from school. if you could help me with the wrong part of the program. i'm using also a 4x4 keypad and a 16x2 LCD which both work fine. i tested the vout of ad9833 and it's generating only noise. please help me.


this is SPI pin connection diagram between ad9833 and pic16f887

FSYNK CONNECTED TO RE0
SDATA CONNECTED TO SDO=RC5
SCK CONNECTED TO SCK=RC3


this is my code

//*******************
unsigned short kp, cnt, oldstate = 0;
char txt[6];

void SpiComm (void);
void ConfigureSPI (void);
unsigned char WriteSPI (unsigned char);

// Keypad module connections
char keypadPort at PORTB;
// End Keypad module connections

// LCD module connections
// LCD module connections
sbit LCD_RS at RD0_bit;
sbit LCD_EN at RD1_bit;

sbit LCD_D4 at RD4_bit;
sbit LCD_D5 at RD5_bit;
sbit LCD_D6 at RD6_bit;
sbit LCD_D7 at RD7_bit;

sbit LCD_RS_Direction at TRISD0_bit;
sbit LCD_EN_Direction at TRISD1_bit;

sbit LCD_D4_Direction at TRISD4_bit;
sbit LCD_D5_Direction at TRISD5_bit;
sbit LCD_D6_Direction at TRISD6_bit;
sbit LCD_D7_Direction at TRISD7_bit;


sbit SoftSpi_SDO at RC5_bit;
sbit SoftSpi_CLK at RC3_bit;
sbit SoftSpi_SDO_Direction at TRISC5_bit;
sbit SoftSpi_SCK_Direction at TRISC3_bit;


// End LCD module connections

void main() {


cnt = 0; // Reset counter
Keypad_Init();
ANSEL=0;
ANSELH=0; // Initialize Keypad
ConfigureSPI();
SpiComm();

Lcd_Init(); // Initialize Lcd
Lcd_Cmd(_LCD_CLEAR); // Clear display
Lcd_Cmd(_LCD_CURSOR_OFF); // Cursor off
Lcd_Out(1, 1, "1");
Lcd_Out(1, 5,"meniu");
Lcd_Out(2, 1,"A-s B-f C-p");
do {
kp = 0; // Reset key code variable

// Wait for key to be pressed and released
do
//kp = Keypad_Key_Press(); // Store key code in kp variable
kp = Keypad_Key_Click(); // Store key code in kp variable
while (!kp);
// Prepare value for output, transform key to it's ASCII value
switch (kp) {


case 1: kp = 68; break; // D
case 2: kp = 67; break; // C
case 3: kp = 66; break; // B
case 4: kp = 65; break; // A
case 5: kp = 35; break; // #
case 6: kp = 57; break; // 9
case 7: kp = 54; break; // 6
case 8: kp = 51; break; // 3
case 9: kp = 48; break; // 0
case 10: kp = 56; break; // 8
case 11: kp = 53; break; // 5
case 12: kp = 50; break; // 2
case 13: kp = 42; break; // *
case 14: kp = 55; break; // 7
case 15: kp = 52; break; // 4
case 16: kp = 49; break; // 1

}

if (kp != oldstate) { // Pressed key differs from previous
cnt = 1;
oldstate = kp;
}
else { // Pressed key is same as previous
cnt++;
}

Lcd_Chr(1, 10, kp); // Print key ASCII value on Lcd

if (cnt == 255) { // If counter varialble overflow
cnt = 0;
Lcd_Out(2, 10, " ");
}




} while (1);
}





void ConfigureSPI (void){
TRISC.B3=0; /* SCK = Output */
TRISC.B4=1;
TRISC.B4=0; /* SDO = Output */
TRISA.B5=0;
SSPSTAT.CKE = 0; /* Data is transmitted on falling clock edge as per AD9833 datasheet */
SSPSTAT.SMP = 0; /* Sampling of data occurs in the middle */
}

void SpiComm (void)
{
PORTE.B0 = 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*/
PORTE.B0 = 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

PORTE.B0 = 0; /* Making FSYNC of AD9833 LOW before writing the 14 bit LSBs to FREQ0 */
WriteSPI(0b01000000); /* D15 = 0, D14 = 1 represents FREQ0 and D13 to D0 represents 14 MSBs */
WriteSPI(0b00000000); /* D7 - D0 */
PORTE.B0 = 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

PORTE.B0 = 0; /* Making FSYNC of AD9833 LOW before writing the 14 bit MSBs to FREQ0 */
WriteSPI(0b01001011); /* D15 = 0, D14 = 1 represents FREQ0 and D13 to D0 represents 14 LSBs */
WriteSPI(0b10111000); /* D7 - D0 */
PORTE.B0 = 1; /* Making FSYNC of AD9833 HIGH after writing the 14 bit MSBs to FREQ0 */

PORTE.B0 = 0; /* Making FSYNC of AD9833 LOW before writing to the Phase Register */
WriteSPI(0b11000000); /* Configured for Zero Degree Phase Shift */
WriteSPI(0b00000000);
PORTE.B0 = 1; /* Making FSYNC of AD9833 HIGH after writing to the Phase Register */

PORTE.B0 = 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 */
PORTE.B0 = 1; /* Making FSYNC of AD9833 HIGH after writing 16 bits to Control Register */
}

unsigned char WriteSPI( unsigned char data_out )
{
SSPBUF = data_out; // write byte to SSPBUF register
if ( SSPCON & 0x80 ) // test if write collision occurred
return ( -1 ); // if WCOL bit is set return negative #
else
{
while( !SSPSTAT.BF ); // wait until bus cycle complete
}
return ( 0 ); // if WCOL bit is not set return non-negative#
}
 
First and foremost - do you see the SPI control lines doing what you're expecting?
> FS going low before SCK is active and then going high again
> SCK is active with as many short bursts as information/data packets you are sending out
> SCK is iddle high and is active (i.e. toggling) when the data is being transferred
> SDO is active (i.e. toggling) when the data is being transferred


For SPI Mode3 the following:
Code:
	SSPSTAT.CKE = 0; /* Data is transmitted on falling clock edge as per AD9833 datasheet */
	SSPSTAT.SMP = 0; /* Sampling of data occurs in the middle */
should be as follows (in my opinion):
Code:
	SSPCON.SSPEN = 1
	SSPCON.CKP = 1
	SSPSTAT.CKE = 0
	SSPSTAT.SMP = 0

These are the commands I use to initialize the AD9834
Code:
	  cmd(0) = &h2118  'Control Register (reset state)
	  cmd(1) = &h70c3  'Frequency Register 0 LSB
	  cmd(2) = &h4a30  'Frequency Register 0 MSB
	  cmd(3) = &h8000  'Frequency Register 1 LSB
	  cmd(4) = &h8000  'Frequency Register 1 MSB
	  cmd(5) = &hc000  'Phase Register 0
	  cmd(6) = &he000  'Phase Register 1
	  cmd(7) = &h2018  'Control Register (exit reset state)

For the following section:
Code:
	SSPBUF = data_out; // write byte to SSPBUF register
	if ( SSPCON & 0x80 ) // test if write collision occurred
	return ( -1 ); // if WCOL bit is set return negative #
	else
	{
		while( !SSPSTAT.BF ); // wait until bus cycle complete
	}
	return ( 0 ); // if WCOL bit is not set return non-negative#
I would use the following:
Code:
	SSPBUF = data_out; // write byte to SSPBUF register
	while( !SSPSTAT.BF ); // wait until bus cycle complete
	return ( 0 ); // if WCOL bit is not set return non-negative#
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top