• AVR Freaks

AnsweredHot!The issues with PIC to PIC communication using SPI (PIC18F45K22)

Author
DTsebrii
New Member
  • Total Posts : 9
  • Reward points : 0
  • Joined: 2021/03/01 13:31:48
  • Location: 0
  • Status: offline
2021/03/08 20:20:18 (permalink)
0

The issues with PIC to PIC communication using SPI (PIC18F45K22)

Good day!
 
I was trying to make two PIC18F45K22 communicate with each other using SPI. To do so, I wrote a function that sends (sends on a master side and receives it on a slave side) a byte of data and then displays it on the terminal using UART. I checked the master's work during debugging, and it works as it says in the datasheet (SS is unset, SCK changes its state, and SSP1BUF receives that data).  However, when I am trying to send a byte, the slave does not receive anything. The SSP1BUF is empty on the slave side and SSP1IF is not set as well. I tried to use both a polling method and an interrupt method, but the result remains the same. Below I attached the master and slave codes.
Master Code

/*******************************************************************************
File name: pic18SPIMaster.c
Author: DTsebrii
Date: 03/07/2021
Modified: None
Description: The program to wait till a pushbutton is pressed, and then send
    a message to another uC via SPI using PIC18F45K22. Additionally,
    to troubleshoot the send message will be transmitted to the
    terminal
Pin output:
 p17 - SS p23 - SDI
 p18 - SCK p24 - SDO
 p20 - PB p25 - TXUART
 p21 - LED p26 - RCUART
*******************************************************************************/
//*** Preprocessors ************************************************************
#include <stdlib.h>
#include <stdio.h>
#include <p18f45k22.h>

#pragma config FOSC = INTIO67
#pragma config PLLCFG = OFF
#pragma config PRICLKEN = ON
#pragma config FCMEN = OFF
#pragma config IESO = OFF

#pragma config PWRTEN = OFF //
#pragma config BOREN = ON
#pragma config BORV = 285
 
#pragma config WDTEN = OFF

#pragma config PBADEN = OFF

#pragma config LVP = OFF
#pragma config MCLRE = EXTMCLR

//*** Constants ****************************************************************
#define TRUE 1
#define FALSE 0

#define SPISS PORTCbits.RC2 // CS pin
#define TRISCSET 0xD3 // 0b11010011 RC2, 3, and 5 are output
#define PBPRESS PORTDbits.RD1 // A pushbutton
#define LED PORTDbits.RD2

//*** Prototypes ***************************************************************
void ISR(); // Interrupt handler
void writeSPI(); // Send a byte to the slave using SPI
void writeUART(); // Send a byte using UART
void oscConf(); // Configuration of the oscillator
void portConf(); // Configuration of ports
void spiConf(); // Configurtion of the SSP registers
void serialConf(); // Configuration of the UART registers
void intConf();
void sysConf(); // Calling all configuration functions

#pragma code int_vector = 0x008
/*******************************************************************************
Name: int_vector
Author: DTsebrii
Date: 03/07/2021
Description:Function to call the interrupt handler
Input: None
Output: None
*******************************************************************************/
void int_vector(){
 _asm
  GOTO ISR
 _endasm
} // eo int_vector::
#pragma code

//*** Global Variables ********************************************************
volatile char pbStateFlag = FALSE; // Flag to check the pushbutton state

char msg = 'D';

//*** Functions ***************************************************************
/*******************************************************************************
Name: oscConf
Author: DTsebrii
Date: 03/07/2021
Description:Setting the Fosc to the appropriate level
Input: unsigned char freq - the value of frequency in MHz
Output: None
*******************************************************************************/
void oscConf( unsigned char freq ){
 OSCCON = 0x02; // Int osc on
 OSCCON2 = 0x04; // PLL No, CLK from OSC, MF off, Sec OSC off, Pri OSC
 OSCTUNE = 0x80; // PLL disabled, Default factory freq tuning
 switch ( freq )
 {
  case 1:
   OSCCON |= 0x30;
   break;
  case 2:
   OSCCON |= 0x40;
   break;
  case 4:
   OSCCON |= 0x50;
   break;
  case 8:
   OSCCON |= 0x60;
   break;
  case 16:
   OSCCON |= 0x70;
   break;
 } // eo switch
 while (OSCCONbits.HFIOFS != 1); // wait for osc to become stable
} // eo oscConf::

/*******************************************************************************
Name: portConf
Author: DTsebrii
Date: 03/07/2021
Description:Setting the Fosc to the appropriate level
Input:
Output: None
*******************************************************************************/
void portConf(){
   //PORTA
   ANSELA=0x00;
 LATA=0X00;
   TRISA= 0xFF;
 
 //PORTB
   ANSELB=0x00;
 LATB=0X00;
   TRISB= 0xFF;
 
 // PORTC
 ANSELC = 0x00;
 LATC = 0x00;
 TRISC = TRISCSET; // RC2, 3, and 5 are output

 //PORTD
   ANSELD=0x00;
 LATD=0X00;
   TRISD= 0xFB; // RD2 is output
 

} //eo portConf::

/*******************************************************************************
Name: intConf
Author: DTsebrii
Date: 03/07/2021
Description:Setting the interrupt related registers
Input: None
Output: None
*******************************************************************************/
void intConf(){
 INTCONbits.GIEH = 0; // Turn off the Interrupts

 // SPI Conf
 PIE2bits.BCLIE = 1; // Bus collision bits
    IPR2bits.BCLIP = 1;
    
    PIE1bits.SSPIE = 1;
    IPR1bits.SSPIP = 1;
 // Enable interrupts
 RCONbits.IPEN = 0; // Disable priority interrupts
    INTCONbits.GIEL = 1; // Enable all unmasked peripheral interrupts
 INTCONbits.GIEH = 1; // Enable all unmasked interrupts
 
} // eo intConf

/*** serialConf ***************************************************************
Author: DTsebrii
Date: 03/07/2021
Description: Sets the registers to work in UART mode
Input: None
Output: None
*******************************************************************************/
void serialConf(){
 
 SPBRG= 12; // Sets it to 8MHZ and 9600k Baudrate
 TXSTA1= 0x22; // BRGH=0, SYNC=0, TX is enabled
 RCSTA1= 0x90;
 BAUDCON1= 0x40; // BRG16=0
 
} // eo serialConf::

/*** spiConf ******************************************************************
Author: DTsebrii
Date: 03/07/2021
Description: Sets the registers to work in SPI mode
Input: None
Output: None
*******************************************************************************/
void spiConf(){
 
 SSP1CON1bits.SSPEN = 0; // Turn off the SPI to configure it
 // SSP1STAT conf
 SSP1STATbits.SMP = 0; // Input is sampled at the middle
 SSP1STATbits.CKE = 1; // From active to idle
 SSP1STAT &= 0b11000000; // Reset all I2C related bits
 // SSP1CON1 conf
 SSP1CON1 &= 0x3F; // Reset WCOL and SSPOV. They are handled by ISR
 SSP1CON1bits.CKP = 1; // Idle state is high
 SSP1CON1bits.SSPM = 0x02; // Master mode with F/64
 // Turn on SPI
 SSP1CON1bits.SSPEN = 1; // Turn on SPI
 
} // eo spiConf::

/*** sysConf ******************************************************************
Author: DTsebrii
Date: 03/07/2021
Description: Call all functions that configurates the system
Input: None
Output: None
*******************************************************************************/
void sysConf(){
 // Software Setup
 oscConf( 8 ); // Fosc = 8MHz
 portConf();
 serialConf();
 spiConf();
 intConf();
 
 // Hardware Setup
 SPISS = 1;
 
} // eo sysConf::

/*** writeSPI ******************************************************************
Author: DTsebrii
Date: 03/07/2021
Description: Store a byte in SSPBUF for a furhter transition
Input: char data - 8-byte data to be sent
Output: None
*******************************************************************************/
void writeSPI(char data){
 LATD ^= 0x04; // Toggle PB
 SSP1BUF = data; // Write the data to the SSP1BUF
 while(!SSP1STATbits.BF);
 
} // eo writeSPI::

/*** writeSPI ******************************************************************
Author: DTsebrii
Date: 03/07/2021
Description: Store a byte in SSPBUF for a furhter transition
Input: char data - 8-byte data to be sent
Output: None
*******************************************************************************/
void writeUART(char data){
 
 while(!TXSTA1bits.TRMT); // Wait untill TXBUS if empty
 TXREG1 = data;
 
} // eo writeUART::

#pragma interrupt ISR
/*******************************************************************************
Name: ISR
Author: DTsebrii
Date: 03/07/2021
Description:Function to handle interrupts
Input: None
Output: None
*******************************************************************************/
void ISR(){
 // Bus collision check
 if(PIR2bits.BCL1IF == 1){
        SSP1CON1 &= 0x3F;
        PIR2bits.BCLIF = 0;
    }
 // Master Synchronous Serial Port 1 Interrupt Flag bit
    if(PIR1bits.SSP1IF){
        PIR1bits.SSP1IF = 0;
    }
} // eo ISR::

//*** Main Routine ************************************************************
void main(){
 sysConf();
 while(TRUE){
  if(!PBPRESS && !pbStateFlag){
   pbStateFlag = TRUE;
   SPISS = 0;
   writeSPI(msg);
   SPISS = 1;
   writeUART(msg);
  } else if(PBPRESS){
   pbStateFlag = FALSE;
  }
 }
}

Slave Code:

/*******************************************************************************
File name: pic18SPISlave.c
Author: DTsebrii
Date: 03/08/2021
Modified: None
Description: The program to wait a message from a master, then transmit the
message to the terminal via UART.
Pin output:
p17 - SS p23 - SDI
p18 - SCK p24 - SDO
p25 - TXUART
p21 - LED p26 - RCUART
*******************************************************************************/
//*** Preprocessors ************************************************************
#include <stdlib.h>
#include <stdio.h>
#include <p18f45k22.h>
#pragma config FOSC = INTIO67
#pragma config PLLCFG = OFF
#pragma config PRICLKEN = ON
#pragma config FCMEN = OFF
#pragma config IESO = OFF
#pragma config PWRTEN = OFF //
#pragma config BOREN = ON
#pragma config BORV = 285

#pragma config WDTEN = OFF
#pragma config PBADEN = OFF
#pragma config LVP = OFF
#pragma config MCLRE = EXTMCLR
//*** Constants ****************************************************************
#define TRUE 1
#define FALSE 0
#define SPISS PORTCbits.RC2 // CS pin
#define TRISCSET 0xDF // 0b11011111 RC2,3,4 - in, RC5 out
#define LED PORTDDbits.RD2
//*** Prototypes ***************************************************************
void writeSPI(); // Send a byte to the slave using SPI
void writeUART(); // Send a byte using UART
void oscConf(); // Configuration of the oscillator
void portConf(); // Configuration of ports
void spiConf(); // Configurtion of the SSP registers
void serialConf(); // Configuration of the UART registers
void intConf();
void sysConf(); // Calling all configuration functions
void ISR(); // Interrupt handler
#pragma code int_vector = 0x008
/*******************************************************************************
Name: int_vector
Author: DTsebrii
Date: 03/07/2021
Description:Function to call the interrupt handler
Input: None
Output: None
*******************************************************************************/
void int_vector(){
_asm
GOTO ISR
_endasm
} // eo int_vector::
#pragma code
//*** Global Variables ********************************************************
volatile char txFlag = FALSE; // Flag to check the pushbutton state
volatile char msg;
//*** Functions ***************************************************************
/*******************************************************************************
Name: oscConf
Author: DTsebrii
Date: 03/07/2021
Description:Setting the Fosc to the appropriate level
Input: unsigned char freq - the value of frequency in MHz
Output: None
*******************************************************************************/
void oscConf( unsigned char freq ){
OSCCON = 0x02; // Int osc on
OSCCON2 = 0x04; // PLL No, CLK from OSC, MF off, Sec OSC off, Pri OSC
OSCTUNE = 0x80; // PLL disabled, Default factory freq tuning
switch ( freq )
{
case 1:
OSCCON |= 0x30;
break;
case 2:
OSCCON |= 0x40;
break;
case 4:
OSCCON |= 0x50;
break;
case 8:
OSCCON |= 0x60;
break;
case 16:
OSCCON |= 0x70;
break;
} // eo switch
while (OSCCONbits.HFIOFS != 1); // wait for osc to become stable
} // eo oscConf::
/*******************************************************************************
Name: portConf
Author: DTsebrii
Date: 03/07/2021
Description:Setting the Fosc to the appropriate level
Input:
Output: None
*******************************************************************************/
void portConf(){
//PORTA
ANSELA=0x00;
LATA=0X00;
TRISA= 0xFF;

//PORTB
ANSELB=0x00;
LATB=0X00;
TRISB= 0xFF;

// PORTC
ANSELC = 0x00;
LATC = 0x00;
TRISC = TRISCSET; // RC2, 3, and 5 are output
//PORTD
ANSELD=0x00;
LATD=0X00;
TRISD= 0xFB; // RD2 is out
} //eo portConf::
/*******************************************************************************
Name: intConf
Author: DTsebrii
Date: 03/07/2021
Description:Setting the interrupt related registers
Input: None
Output: None
*******************************************************************************/
void intConf(){
INTCONbits.GIEH = 0; // Turn off the Interrupts
// SPI Conf
PIE2bits.BCL1IE = 1; // Bus collision bits
IPR2bits.BCL1IP = 1;

PIE1bits.SSP1IE = 1;
IPR1bits.SSP1IP = 1;
// Enable interrupts
RCONbits.IPEN = 0; // Disable priority interrupts
INTCONbits.GIEL = 1; // Enable all unmasked peripheral interrupts
INTCONbits.GIEH = 1; // Enable all unmasked interrupts

} // eo intConf
/*** serialConf ***************************************************************
Author: DTsebrii
Date: 03/07/2021
Description: Sets the registers to work in UART mode
Input: None
Output: None
*******************************************************************************/
void serialConf(){

SPBRG= 12; // Sets it to 8MHZ and 9600k Baudrate
TXSTA1= 0x22; // BRGH=0, SYNC=0, TX is enabled
RCSTA1= 0x90;
BAUDCON1= 0x40; // BRG16=0

} // eo serialConf::
/*** spiConf ******************************************************************
Author: DTsebrii
Date: 03/07/2021
Description: Sets the registers to work in SPI mode
Input: None
Output: None
*******************************************************************************/
void spiConf(){

SSP1CON1bits.SSPEN = 0; // Turn off the SPI to configure it
// SSP1STAT conf
SSP1STATbits.SMP = 0; // Input is sampled at the middle
SSP1STATbits.CKE = 1; // From active to idle
SSP1STAT &= 0b11000000; // Reset all I2C related bits
// SSP1CON1 conf
SSP1CON1 &= 0x3F; // Reset WCOL and SSPOV. They are handled by ISR
SSP1CON1bits.CKP = 1; // Idle state is high
SSP1CON1bits.SSPM = 0x04; // Slave mode with SS enabled

SSP1CON3bits.BOEN = 0;
// Turn on SPI
SSP1CON1bits.SSPEN = 1; // Turn on SPI

} // eo spiConf::
/*** sysConf ******************************************************************
Author: DTsebrii
Date: 03/07/2021
Description: Call all functions that configurates the system
Input: None
Output: None
*******************************************************************************/
void sysConf(){
// Software Setup
oscConf( 8 ); // Fosc = 8MHz
portConf();
serialConf();
spiConf();
intConf();

} // eo sysConf::
/*** writeSPI ******************************************************************
Author: DTsebrii
Date: 03/07/2021
Description: Store a byte in SSPBUF for a furhter transition
Input: char data - 8-byte data to be sent
Output: None
*******************************************************************************/
void writeSPI(char data){

SSP1BUF = data; // Write the data to the SSP1BUF
while(!SSP1STATbits.BF);

} // eo writeSPI::
/*** writeSPI ******************************************************************
Author: DTsebrii
Date: 03/07/2021
Description: Store a byte in SSPBUF for a furhter transition
Input: char data - 8-byte data to be sent
Output: None
*******************************************************************************/
void writeUART(char data){

while(!TXSTA1bits.TRMT); // Wait untill TXBUS if empty
TXREG1 = data;

} // eo writeUART::
#pragma interrupt ISR
/*******************************************************************************
Name: ISR
Author: DTsebrii
Date: 03/07/2021
Description:Function to handle interrupts
Input: None
Output: None
*******************************************************************************/
void ISR(){
// Bus collision check
if(PIR2bits.BCL1IF == 1){
SSP1CON1 &= 0x3F;
PIR2bits.BCLIF = 0;
}
// Master Synchronous Serial Port 1 Interrupt Flag bit
if(PIR1bits.SSP1IF){
LATD ^= 0x04; // Toggle PB
txFlag = TRUE;
msg = SSP1BUF;
PIR1bits.SSPIF = 0;
}
} // eo ISR::
//*** Main Routine ************************************************************
void main(){
sysConf();
while(TRUE){
if(txFlag){
LATD ^= 0x04; // Toggle PB
txFlag = FALSE;
writeUART(msg);
}
} // eo superloop
}

Attached Image(s)

#1
ric
Super Member
  • Total Posts : 30223
  • Reward points : 0
  • Joined: 2003/11/07 12:41:26
  • Location: Australia, Melbourne
  • Status: online
Re: The issues with PIC to PIC communication using SPI (PIC18F45K22) 2021/03/08 20:46:44 (permalink)
0
Which C compiler are you using?
I suspect it is the ancient C18, rather than XC8.
 

I also post at: PicForum
Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
NEW USERS: Posting images, links and code - workaround for restrictions.
To get a useful answer, always state which PIC you are using!
#2
ric
Super Member
  • Total Posts : 30223
  • Reward points : 0
  • Joined: 2003/11/07 12:41:26
  • Location: Australia, Melbourne
  • Status: online
Re: The issues with PIC to PIC communication using SPI (PIC18F45K22) 2021/03/08 21:03:21 (permalink) ☼ Best Answerby DTsebrii 2021/03/09 11:07:37
+1 (1)
Your slave code indicates that you are using pin 17 [RC2] as SS on the slave, but the datasheet says that SS1 is on RA5, which is pin 7.
 
You can use any pin you like  in the Master, as it is software generated, but you must use the hardware SS pin in the Slave.
 

I also post at: PicForum
Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
NEW USERS: Posting images, links and code - workaround for restrictions.
To get a useful answer, always state which PIC you are using!
#3
ric
Super Member
  • Total Posts : 30223
  • Reward points : 0
  • Joined: 2003/11/07 12:41:26
  • Location: Australia, Melbourne
  • Status: online
Re: The issues with PIC to PIC communication using SPI (PIC18F45K22) 2021/03/08 23:02:24 (permalink)
0
Also in the Slave, this
#define LED PORTDDbits.RD2
should be
#define LED LATDbits.LATD2


 
You got away with mispelling PORTDbits because you never use "LED", rather you used:
LATD ^= 0x04; // Toggle PB

to toggle  RD2. With the correct define, you can do it with
LED ^= 1;


I also post at: PicForum
Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
NEW USERS: Posting images, links and code - workaround for restrictions.
To get a useful answer, always state which PIC you are using!
#4
DTsebrii
New Member
  • Total Posts : 9
  • Reward points : 0
  • Joined: 2021/03/01 13:31:48
  • Location: 0
  • Status: offline
Re: The issues with PIC to PIC communication using SPI (PIC18F45K22) 2021/03/09 11:18:06 (permalink)
0
ric
Your slave code indicates that you are using pin 17 [RC2] as SS on the slave, but the datasheet says that SS1 is on RA5, which is pin 7.
 
You can use any pin you like  in the Master, as it is software generated, but you must use the hardware SS pin in the Slave.



Thank you for your help, that was my problem. And sorry for the late reply, I do not why, but I cannot access a microchip forum on my main laptop: it shows always a "Service Unavailable" message.
I do not know how I skipped this from a datasheet; now master sends a byte successfully. However, I still have some work with sending a string, but this is a different story. 
 
Also, yes, I use MPLAB IDE v8.92 with a C18 compiler. The debug mode in MPLAB IDE is more convenient than in MPLAB XC8 for me now, but I feel like I will need to switch to a newer version in the recent future.
#5
Kabak
Super Member
  • Total Posts : 279
  • Reward points : 0
  • Joined: 2014/07/30 03:47:55
  • Location: 0
  • Status: offline
Re: The issues with PIC to PIC communication using SPI (PIC18F45K22) 2021/03/09 11:28:29 (permalink)
0
DTsebrii
...
And sorry for the late reply, I do not why, but I cannot access a microchip forum on my main laptop: it shows always a "Service Unavailable" message.
...



Delete cookies for https://www.microchip.com in your browser.
#6
ric
Super Member
  • Total Posts : 30223
  • Reward points : 0
  • Joined: 2003/11/07 12:41:26
  • Location: Australia, Melbourne
  • Status: online
Re: The issues with PIC to PIC communication using SPI (PIC18F45K22) 2021/03/09 15:30:55 (permalink)
0
DTsebrii
Also, yes, I use MPLAB IDE v8.92 with a C18 compiler. The debug mode in MPLAB IDE is more convenient than in MPLAB XC8 for me now, but I feel like I will need to switch to a newer version in the recent future.

You are mixing up the IDE and the compiler.
You can use XC8 version 1.xx in MPLAB 8. The later XC8 v2.xx versions require MPLAB X
You can download previous versions of compiler and IDE from https://www.microchip.com...spic-downloads-archive
 
 

I also post at: PicForum
Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
NEW USERS: Posting images, links and code - workaround for restrictions.
To get a useful answer, always state which PIC you are using!
#7
Jump to:
© 2021 APG vNext Commercial Version 4.5