pic16f877a spi master slave help needed

Thread Starter

n_1_needs_help

Joined Jun 8, 2014
5
Hi,
I am trying to get some communication going using SPI between two PIC16f877a's and am failing miserably. Any alternative code to solve this problem using 877a or suggestions would be greatly appreciated. The basic problem is the slave is just not receiving anything from the master!

Rich (BB code):
//master code 
 #include <htc.h>
 #include <stdio.h>
#include "usart.h"
__CONFIG(0x3f3A);
//Defintions.h
#define SS RA5
#define SCK RC3
#define SDI RC4
#define SDO RC5
#define FALSE 0
#define TRUE 1
#define RTS RA0
#define CTS RA1

int i,j;
void main (void)
{
//initialisations and declaration of variables
unsigned char testCounter = 0, dummy;
	INTCON=0;	// purpose of disabling the interrupts.

	init_comms();
printf("\r this is a test");
//initialisations of port pins
for (i=1;i<250;i++);//1ms delay

PCFG3 = 0; // Configure PORTA digital I/O
PCFG2 = 1;
PCFG1 = 1;
TRISC3 = 0; // SCK=RC3 is the serial clock
TRISC4 = 1; // SDI=RC4 is serial data input
TRISC5 = 0; // SDO=RC5 is serial data output
TRISA0 = 0; // RA0 = RTS, an output
TRISA1 = 1; // RA1 = CTS, an input
TRISA5 = 0; // SS=RA5 is slave select output
INTCON = 0; // Disable

//initialisation of timer SPI

SMP = 0; // Input data sampled at middle data output time
CKE = 0; // Transmit occurs on idle to active clock state
CKP = 1; // Idle state for clock is a high level
SSPM3 = 0; //
SSPM2 = 0; //
SSPM1 = 0; //
SSPM0 = 0; // SPI Master mode, clock = FOSC/4
SSPEN = 1; // Enables serial port
SS = 1; // De-select Slave (pin 7)
SSPIF = 0;

//superloop program
RTS = 1; //Master signals "I'm
//ready!"
while(CTS == 0){} //Wait for Slave
//ready
while(1){
SS = 0; // Select Slave (Active low)
// Transmit data:
SSPBUF = testCounter;
//Wait for transmission complete:
while(BF==FALSE) {}
dummy = SSPBUF; // Makes BF=FALSE

printf("\r p2 ");
SS = 1; // De-select Slave
testCounter++;
for (j=1;j<2000;j++){

for (i=1;i<250;i++);//1ms delay
}
}
}
---------------------------------------------


//slave code 
 #include <htc.h>
 #include <stdio.h>
#include "usart.h"
__CONFIG(0x3f3A);

#define SS RA5
#define SCK RC3
#define SDI RC4
#define SDO RC5
#define FALSE 0
#define TRUE 1
#define RTS RA0
#define CTS RA1
int i,expectedValue;
void main (void)
{
	INTCON=0;	// purpose of disabling the interrupts.

	init_comms();
//initialisations and declarations of variables
unsigned char testCounter = 0, data;
unsigned char errorCount = 0;

//initialisations of port pins
printf("\r this is a test");
for (i=1;i<250;i++);

PCFG3 = 0; // Configure PORTA digital I/O
PCFG2 = 1;
PCFG1 = 1;
TRISC3 = 1; // SCK = RC3 clock (inputforslave)
TRISC4 = 1; // SDI = RC4 serial data input
TRISC5 = 0; // SDO = RC5 serial data output
TRISA0 = 0; // RA0 = RTS, an output
TRISA1 = 1; // RA1 = CTS, an input
TRISA5 = 1; // SS = RA5 slave select input
// Extra for displaying a LED
TRISA2=0;
TRISA3=0;
INTCON = 0; // Disable all interrupts
SSPIF = 0;

//initialisation of timer SPI
SMP = 0; // Input data sampled at middle data output time
CKE = 0; // Transmit occurs on idle to active clock state
CKP = 1; // Idle state for clock is a high level
SSPM3 = 0; //
SSPM2 = 1; //
SSPM1 = 0; //
SSPM0 = 0; // SPI Slave mode, SS pin control enabled
SSPEN = 1; // Enables serial port
SSPIF = 0;
expectedValue = errorCount = 0; // For testing and debugging
RA2=0;RA3=0;
//superloop program
RTS = 1; //Slave signals "I'm
//ready!"
while(CTS == 0){} //Wait for Master ready

while(1){
// Wait for Master to select Slave:
while(SS == 1){}
// Wait for SSPBUF to be full
//printf("\r p2 ");
//(Signifies reception complete):
while(BF==FALSE){}
data = SSPBUF; // Get data byte
//printf("\r p3 ");
printf("\r d [%c] ",data);
RA2=1;
// Wait for Master to de-select Slave while(SS == 0){}
if(data != expectedValue)
{
errorCount++;
}

printf("\r d [%c] ",data);
expectedValue++;

}

}//end of main
 
Last edited by a moderator:

JohnInTX

Joined Jun 26, 2012
3,825
Hard to tell but a few things here:
//Wait for Master to select Slave: while(SS == 1){}
You don't need/want this in the slave. SS/ is controlled by the SPI transmitter and sensed automatically by the SPI slave. Its possible that reading this returns a 0 which would sail right through your other code.

You should not use r-m-w on any of the TRIS registers, especially any that are shared with peripherals i.e.
Rich (BB code):
TRISC3 = 0; // SCK=RC3 is the serial clock 
TRISC4 = 1; // SDI=RC4 is serial data input 
TRISC5 = 0; // SDO=RC5 is serial data output
should be done as TRISC = the equivalent byte for ALL bits at once. Since this processor does not have LATx like the 18F, I would strongly recommend that you do that with all IO i.e. maintain a byte image of the port output desired, flip bits on that then assign the whole byte to the PORT. You would not believe the problems that can arise from r-m-w shared with a peripheral - until they bite you that is. Then you'd believe. I believe.

You should check WCOL and SSPOV and clear them as necessary - if you have a read overflow, it will hang the SSP until cleared.

The setups look OK per se. What does the terminal say about where you are?
 

ErnieM

Joined Apr 24, 2011
8,007
The basic problem is the slave is just not receiving anything from the master!
If I take that literally you are saying the master is not transmitting. Fine. You need rock solid master before you try the slave end anyway.

Get an EEPROM or such and make some master code to control it. Once that is in the bag you'll have a bit more experience to go at the slave end.

The slave side is the truly hard one.
 

JohnInTX

Joined Jun 26, 2012
3,825
Don't forget to ensure that SDO on the master connects to SDI on the slave and vice versa. Same for RTS connecting to CTS, master to slave and vice versa.

Good luck!
 

Thread Starter

n_1_needs_help

Joined Jun 8, 2014
5
It was working, I soldered extra pins to the board and missed a solder bridge on 1 of the extra 80 pins I soldered, and that one pin was pin 18 on the pic16f877a (SPI clock), I wonder what the odds on that are?
Thanks for all your help!
 
Top