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.

PIC to PIC SPI

Status
Not open for further replies.

eckcotech

New Member
Hey all,

I have been searching and working on a small project that requires Pic to Pic SPI for some time now and I still have not been able to get this working.

All pics (slaves and master) are PIC18F2523. Since I never have two way communication, I have only attached master DO line to Slave DI line for slaves that I will send data to and visa-versa on slaves I will request data from, and SCK lines are all tied together. In addition to the general SPI pins, I have a separate pin for each slave coming off the master to each slave SS line. each of these lines has a pullup resistor to keep the line high when idle.

I am using MikroC for my compiler but have MPLab available.

Here's the general idea of what I am trying to do....

Master pic requests info from slave1(ADC1 slave) by pulling SS pin low
Master receives data from ADC1 Slave then sets SS pin high to end transmission.
Master transmits data to slave2(LCD1 slave). SS pin is set low before transfer and high after transfer.
LCD1 slave receives data from master and displays it on an LCD.

and here is a look at the code I am trying to use.

Master PIC........(pull a value from ADC Slave, then send it to the LCD slave)
Code:
//**********************************
// Setup SPI Pins
//**********************************

// pin5 (RA3) = LCD1
// pin2 (RA0) = adcslave1

sbit Chip_Select1 at RA0_bit; //slave pic running ADC1     0 to select 1 to deselect
sbit Chip_Select5 at RA3_bit; //slave pic running lcd1     0 to select 1 to deselect

sbit Chip_Select_Direction1 at TRISA0_bit;  //0 for output 1 for input
sbit Chip_Select_Direction5 at TRISA3_bit;  //0 for output 1 for input

sbit Spi_CLK at RC3_bit;
sbit Spi_SDI at RC4_bit;
sbit Spi_SDO at RC5_bit;
sbit Spi_CLK_Direction at TRISC3_bit;
sbit Spi_SDI_Direction at TRISC4_bit;
sbit Spi_SDO_Direction at TRISC5_bit;


//**********************************
// Global Variables
//**********************************
unsigned short i;
char ADC1Val[10];
unsigned char junk;

//**********************************
// Setup Pic for operation
//**********************************
void InitMain(void){
  Delay_ms(500);

  ADCON1 = 0x0F;
  TRISA = 0x00;
  PORTA = 0x00;
  TRISB = 0x7F;
  PORTB = 0x7F;
  Chip_Select_Direction1 = 0;    // Ready for Output Slave1
  Chip_Select_Direction5 = 0;    // Ready for Output Slave5
 
  Chip_Select5 = 1;
  Chip_Select1 = 1;
 
  UART1_Init(9600);
 
  SPI1_Init_Advanced(_SPI_MASTER_OSC_DIV4, _SPI_DATA_SAMPLE_END, _SPI_CLK_IDLE_HIGH, _SPI_LOW_2_HIGH);
  SSPSTAT = 0x00; //00000000
  SSPCON1 = 0x30; //00110000

}

unsigned char SPI_Get(void){
   SSPBUF = 0x00;
   while(!SSPSTAT.BF);
   return (SSPBUF);
}

void SPI_Put(unsigned char d){
    junk=SSPBUF;
    Delay_ms(5);
    SSPBUF = d;
}

//**********************************
// Main Program
//**********************************
void main() {
  InitMain();
  i=0;

  while(1){

     //=========================================
     // Request Data From ADC1
     //=========================================
     
     i=0;
     Chip_Select1 = 0;    //Select Slave1
     ADC1Val[i++]=SPI_Get();
     Chip_Select1 = 1;    //Deselect Slave1
     Delay_ms(15);
     ADC1Val[i]=0x00;
     
     //=========================================
     // End ADC1 Data Request
     //=========================================

     
     //=========================================
     // Send Data to LCD1
     //=========================================
     i=0;
     Chip_Select5 = 0;     //Select LCD Slave1
     Delay_us(20);
     for(i=0;i<=(strlen(ADC1Val));i++){
        SPI1_Write(ADC1Val[i]);
     }
     Delay_ms(20);
     Chip_Select5 = 1;     //Deselect LCD Slave1
     Delay_ms(150);
     //=========================================
     // End LCD1 Data Transmission
     //=========================================
  }
}


ADC1 Slave....(will gather adc values and send to master when SS is pulled low. for now, just sending the string "Hey")
Code:
char txt0[] = "Hey";
unsigned char junk;
int i = 0;

//sbit Chip_Select at RA5_bit;
sbit Spi_CLK at RC3_bit;
sbit Spi_SDI at RC4_bit;
sbit Spi_SDO at RC5_bit;

//sbit Chip_Select_Direction at TRISA5_bit;
sbit Spi_CLK_Direction at TRISC3_bit;
sbit Spi_SDI_Direction at TRISC4_bit;
sbit Spi_SDO_Direction at TRISC5_bit;


void Init_Main(){

  int cnt = 0;

  T1CON = 0x00;
  ADCON1 |= 0x0B;                        // Configure AN0-AN3 AS ANALOG
  CMCON |= 7;
  PORTA = 0x2F;
  TRISA = 0x2F;
  PORTC = 0x18;
  TRISC = 0x18;
  Spi_CLK_Direction = 1;
  Spi_SDI_Direction = 1;
  Spi_SDO_Direction = 0;

  //Setup SPI
  SSPSTAT = 0x00; //00000000
  SSPCON1 = 0x34; //00110100
 
}

void SPI_Put(unsigned char d){
    SSPBUF = d;
    while(!SSPBUF.BF);
    junk=SSPBUF;
}

void main() {
    Delay_ms(300);
    Init_Main();

    while(1){
       while(!RA5_bit){
          i=0;
          for(i=0;i<=(strlen(txt0));i++){
            SPI_Put(txt0[i]);
          }
       }
    }
}


LCD Slave.....(this listens for the master to pull SS low and then reads SPI data to be displayed on LCD)
Code:
// LCD module connections
sbit LCD8_RS at LATA2_bit;
sbit LCD8_RW at LATA1_bit;
sbit LCD8_EN at LATA0_bit;
sbit LCD8_D7 at LATB7_bit;
sbit LCD8_D6 at LATB6_bit;
sbit LCD8_D5 at LATB5_bit;
sbit LCD8_D4 at LATB4_bit;
sbit LCD8_D3 at LATB3_bit;
sbit LCD8_D2 at LATB2_bit;
sbit LCD8_D1 at LATB1_bit;
sbit LCD8_D0 at LATB0_bit;

sbit LCD8_RS_Direction at TRISA2_bit;
sbit LCD8_RW_Direction at TRISA1_bit;
sbit LCD8_EN_Direction at TRISA0_bit;
sbit LCD8_D0_Direction at TRISB0_bit;
sbit LCD8_D1_Direction at TRISB1_bit;
sbit LCD8_D2_Direction at TRISB2_bit;
sbit LCD8_D3_Direction at TRISB3_bit;
sbit LCD8_D4_Direction at TRISB4_bit;
sbit LCD8_D5_Direction at TRISB5_bit;
sbit LCD8_D6_Direction at TRISB6_bit;
sbit LCD8_D7_Direction at TRISB7_bit;
// End LCD module connections

sbit Spi_CLK at RC3_bit;
sbit Spi_SDI at RC4_bit;
sbit Spi_SDO at RC5_bit;
sbit Spi_CLK_Direction at TRISC3_bit;
sbit Spi_SDI_Direction at TRISC4_bit;
sbit Spi_SDO_Direction at TRISC5_bit;

char txt1[] = " SPI Demo ";

unsigned char mybyte[20];
int i;
int SPIRXFLAG;


void Init_main(){
  Delay_ms(300);
  ADCON1 = 0x0F;
  T1CON = 0x00;
  CMCON |= 7;
  PORTC = 0x18;
  TRISC = 0x18;
  PORTB = 0;
  TRISB = 0;
  PORTA = 0x20;
  TRISA = 0x20;
  SPIRXFLAG = 0;


  Spi_CLK_Direction = 1;
  Spi_SDI_Direction = 1;
  Spi_SDO_Direction = 0;

  Lcd8_Init();                        // Initialize LCD
  Lcd8_Cmd(_LCD_CLEAR);               // Clear display
  Lcd8_Cmd(_LCD_CURSOR_OFF);          // Cursor off
  Lcd8_Out(1,1,txt1);                 // Write "SPI Demo" on Line 1

  //Setup SPI
  SSPSTAT = 0x00; //00000000
  SSPCON1 = 0x34; //00110100
}

unsigned char SPI_Get(void){
   SSPBUF=0x00;
   while(!SSPSTAT.BF);
   return SSPBUF;
}


void main(){
  Init_main();

  while(1){

     while(!RA5_bit){                //while slave select pin is pulled low
        if(SSPSTAT.BF){              //if buffer holds data
          mybyte[i++] = SSPBUF;      //store data in mybyte char array
          SPIRXFLAG=1;               //set rx flag for later use
        }
     }

     if(SPIRXFLAG==1){               //if rx flag is set
        mybyte[i]=0x00;
        i=0;
        Lcd8_Out(2,1,mybyte);
        SPIRXFLAG=0;                 //clear rx flag
     }
  }
}

Using this code, I am able to get the first bit of the string "Hey" all the way through to the LCD but nothing else. I have tested sending just the string "Hey" from the master to the LCD slave and that works fine so I believe the issue lies in getting the data from ADC slave and transferring it.

I have been working on this for weeks now and I am frustrated to say the least, any help would be great.

Thanks!
 
Last edited:
These routines look iffy to me,
Code:
unsigned char SPI_Get(void){
   SSPBUF = 0x00;
   while(!SSPSTAT.BF);
   return (SSPBUF);
}

void SPI_Put(unsigned char d){
    junk=SSPBUF;
    Delay_ms(5);
    SSPBUF = d;
}
If you call put and then get you will get a buffer overflow due to not reading the junk data.

I think they should both do the same thing. Something like,
Code:
unsigned char SPI_Get(void){
   SSPBUF = 0x00;
   while(!SSPSTAT.BF);
   return (SSPBUF);
}

void SPI_Put(unsigned char d){
   SSPBUF = d;		//send out the data
   while(!SSPSTAT.BF);	//wait until it's gone
   junk=SSPBUF;		//read the received (junk) byte
}

Mike.
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top