CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

2 PIC18 can't talk using SPI connection..
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
thibow



Joined: 11 Apr 2012
Posts: 30

View user's profile Send private message

2 PIC18 can't talk using SPI connection..
PostPosted: Wed Apr 11, 2012 5:33 pm     Reply with quote

Hello, I'm trying to setup a very basic SPI communication between 2 PIC 18LF2550. I am using PIC-C Compiler from CCS v4.114.

Pin A1 of both PICs are connected to a LED and pin A0 from the slave is also connected to a LED. The Master's LED is blinking every time I send a data (0x12), so it seems to send something every 500ms as asked. I want also the slave A1's pin to be toggled and the LED to blink every time something is in the buffer and read the data. So far everything works great, both LED are blinking synchronously.

However, where I get trouble is when I come to data sent. I send a '0x12' and I ask my slave to toggle pin A0 every time this particular value is received using a if. But it seems to never read this value.

and here are my files :

=========For the MASTER==========
Code:
#include <18F2550.H>

#fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,PLL2,CPUDIV4,NOVREGEN,NOMCLR
#use delay(clock=16000000)

void main (void){

   //configure the device to be a master, data transmitted on H-to-L clock transition
   setup_spi(spi_master | spi_l_to_h | spi_clk_div_16);
   output_HIGH(pin_A1); //Led à 0
   output_HIGH(pin_A0); //Led à 0   

   enable_interrupts(global);
   enable_interrupts(INT_SSP);

   while(1){
     
   spi_write(0x12);
   delay_ms(500);
     
   }
}

#int_SSP
Void Interruption(){
   output_toggle(pin_A1);
}



============For the SLAVE============
Code:
#include <18F2550.H>

#fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,PLL2,CPUDIV4,NOVREGEN,NOMCLR
#use delay(clock=16000000)

   int8 data;

void main (void){

   //configure the device to be a master, data transmitted on H-to-L clock transition
   setup_spi(spi_slave | spi_L_to_H );
   
output_HIGH(pin_A1); //Led à 0
   output_HIGH(pin_A0); //Led à 0   

   enable_interrupts(global);
   enable_interrupts(INT_SSP);


   
   while(1){
      while(!spi_data_is_in());
         data=spi_read();
   }
}

#int_SSP
Void Interruption(){
   output_toggle(pin_A1);
   if (data==0x12){
      output_toggle(pin_A0);
   }
}



Master PIC uses an external 8Mhz Crystal clock.
I wired them like that :

MASTER-------------------------------SLAVE

18 SDO-------------------------------23 SDI
23 SDI-------------------------------18 SDO
22 SCK------------------------------- 22 SCK

according to this configuration :




If you have any guess.. Thank you !
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Apr 11, 2012 6:45 pm     Reply with quote

Code:
setup_spi(spi_slave | spi_L_to_H );
 

You have the Slave Select enabled (by default) in the statement above,
but your Master code doesn't implement Slave Select, and you don't have
a wired connection for it between the two PICs.

It's recommended that you add the connection, and that you add code to
the Master to set SS low when you transmit a byte. (Set it high initially
in your setup code).
thibow



Joined: 11 Apr 2012
Posts: 30

View user's profile Send private message

PostPosted: Wed Apr 11, 2012 7:11 pm     Reply with quote

Hello PCM Programmer, thank you very much for your help.

PCM programmer wrote:
Code:
setup_spi(spi_slave | spi_L_to_H );
 

You have the Slave Select enabled (by default) in the statement above,
but your Master code doesn't implement Slave Select, and you don't have
a wired connection for it between the two PICs.


I am sorry, I'm not sure to understand: I have the "spi_slave" only on Slave PIC, and the Master PIC has a "setup_spi(spi_master...)"

PCM programmer wrote:

It's recommended that you add the connection, and that you add code to
the Master to set SS low when you transmit a byte. (Set it high initially
in your setup code).


Do you mean that I should add "SPI_SS_DISABLED" from setup on both PICs ? I don't get it !

I should then add a wire between both PIC's pin 7 (SS) and set it high manually on start-up, (with output_HIGH(pin_A5); ) then set it low before writing and then high again ?

As there is no function in CCS I am not sure !

Thank you
jeremiah



Joined: 20 Jul 2010
Posts: 1354

View user's profile Send private message

PostPosted: Wed Apr 11, 2012 7:44 pm     Reply with quote

thibow wrote:

I should then add a wire between both PIC's pin 7 (SS) and set it high manually on start-up, (with output_HIGH(pin_A5); ) then set it low before writing and then high again ?


This is correct. You need to add a SS line and manually operate it. Use output_high() and output_low()
thibow



Joined: 11 Apr 2012
Posts: 30

View user's profile Send private message

PostPosted: Wed Apr 11, 2012 8:37 pm     Reply with quote

Great, thank you, I will then try this (tomorrow) and tell you back if it works !
thibow



Joined: 11 Apr 2012
Posts: 30

View user's profile Send private message

PostPosted: Thu Apr 12, 2012 8:06 am     Reply with quote

I've just tried out and it's working ! My second led is blinking !

Thank you very much for your help !
thibow



Joined: 11 Apr 2012
Posts: 30

View user's profile Send private message

PostPosted: Thu Apr 12, 2012 11:23 am     Reply with quote

Little problem, I have tried to read, from the master, that's ok, but now I would like to read from the slave as well. I do read from the slave, but one out of 2 reading is wrong: here is the code

=====MASTER=========
Code:
#include <18F2550.H>

#fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,PLL2,CPUDIV4,NOVREGEN,NOMCLR
#use delay(clock=16000000)

#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C5,bits=8,STOP=1)

void main (void){

   //configure the device to be a master, data transmitted on H-to-L clock transition
   setup_spi(spi_master | spi_l_to_h | spi_clk_div_16);
   output_HIGH(pin_A1); //Led à 0
   output_HIGH(pin_A0); //Led à 0   
   output_HIGH(pin_A5); // SS initialized
   int8 data;   

   enable_interrupts(global);
   enable_interrupts(INT_SSP);

   while(1){
   
   output_LOW(pin_A5);
   printf("\n\r ecriture ");
   spi_write(0x12);
   output_HIGH(pin_A5);
   delay_us(70);

   output_LOW(pin_A5);
      printf("\n lecture ");
      data=spi_read();
      output_HIGH(pin_A5);
      delay_us(70);
   
      printf("\n data :%d",data);
      output_toggle(pin_A0);

   delay_ms(500);
      
   }
}

#int_SSP
Void Interruption(){
   output_toggle(pin_A1);
   printf("\n\r interrupt");
}


=====SLAVE========
Code:
#include <18F2550.H>

#fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,PLL2,CPUDIV4,NOVREGEN,NOMCLR
#use delay(clock=16000000)

//#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C5,bits=8,STOP=1)
   int8 data;
   int i=1;
void main (void){

   //configure the device to be a slave, data transmitted on H-to-L clock transition
   setup_spi(spi_slave | spi_L_to_H );
   
   output_HIGH(pin_A1); //Led à 0
   output_HIGH(pin_A0); //Led à 0   

   enable_interrupts(global);
   enable_interrupts(INT_SSP);


   
   while(1){
  }
}

#int_SSP
Void Interruption(){

    data=spi_read();
   output_toggle(pin_A1);
   if (data==0x12){
      spi_write(data+i);
       output_toggle(pin_A0);
      i++;
   }
}



Output RS232
Code:
ecriture
 interrupt
           lecture
                    data :19
 ecriture
 interrupt
           lecture
                    data :18
 ecriture
 interrupt
           lecture
                    data :20
 ecriture
 interrupt
           lecture
                    data :18
 ecriture
 interrupt
           lecture
                    data :21
 ecriture
 interrupt
           lecture
                    data :18
 ecriture
 interrupt
           lecture
                    data :22
 ecriture
 interrupt
           lecture
                    data :18


As you can see, there is a wrong reading 18, one out of 2 reading.. I can't figure out why..
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Apr 12, 2012 11:37 am     Reply with quote

Quote:
#int_SSP
Void Interruption(){
output_toggle(pin_A1);
printf("\n\r interrupt");
}


enable_interrupts(global);
enable_interrupts(INT_SSP);

Get rid of the #int_ssp routine in the master code. Also get rid of the
lines that enable interrupts for INT_SSP and GLOBAL. You don't need
that routine on the master. And as a general comment, don't put code
that takes a long time to execute in an interrupt routine (such as the
printf statement).

Quote:

void main (void){

setup_spi(spi_master | spi_l_to_h | spi_clk_div_16);
output_HIGH(pin_A1); //Led à 0
output_HIGH(pin_A0); //Led à 0
output_HIGH(pin_A5); // SS initialized
int8 data;

Don't declare variables within code in CCS. Always declare them at
the top of the function, first thing.


Quote:
output_LOW(pin_A5);
printf("\n lecture ");
data=spi_read();
output_HIGH(pin_A5);
delay_us(70);

The master needs to generate a clock, in order to receive data from the
slave. To tell the master code to do this, you must put in a parameter in
the spi_read() function. Usually, a parameter of 0x00 is used. Edit your
code to add this parameter. Note: This is only needed in the master
code. Do not add the parameter to the spi_read() in your slave code
in the #int_ssp isr.
temtronic



Joined: 01 Jul 2010
Posts: 9243
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Thu Apr 12, 2012 11:51 am     Reply with quote

also

get into a habit of always adding 'errors' to the USE RS232(......) line.

When using the hardware UART , this will prevent the UART from 'hanging up'.

while you may not be using it in this program, sooner or later , you'll wonder WHY your code 'hangs' on serial input.....

it's second nature to me to always put 'errors' in
thibow



Joined: 11 Apr 2012
Posts: 30

View user's profile Send private message

PostPosted: Thu Apr 12, 2012 12:12 pm     Reply with quote

Thank's a lot PCM Programmer, you were right, the interrupt messed everything.
I removed Master's interruption, this didn't change anything.. I then allowed a lot of time to the master between the write and read, to let the slave deal with his interruption and let the time to write to the master.. Unfortunately it didn't solve the problem..; Even if I left 1sec in between.

Then I have deleted Slave's interrupt, and do everything in the while loop, and it works the way it should.

One question though: I thought interruption were there to simplify everything, however, it seems not to be working the way it should, finally I won't use them at all.. Why isn't the PIC able to compare a received data and send a data in a 1sec interruption..

Here is the working code :

=====MASTER=====
Code:
#include <18F2550.H>

#fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,PLL2,CPUDIV4,NOVREGEN,NOMCLR
#use delay(clock=16000000)

#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C5,bits=8,STOP=1)

signed int data;   

void main (void){

   //configure the device to be a master, data transmitted on H-to-L clock transition
   setup_spi(spi_master | spi_l_to_h | spi_clk_div_16);
   output_HIGH(pin_A1); //Led à 0
   output_HIGH(pin_A0); //Led à 0   
   output_HIGH(pin_A5); // SS initialized


   while(1){
   
   output_LOW(pin_A5);
   spi_write(0x12);
   output_HIGH(pin_A5);

   delay_ms(500);

   data=spi_read();
   
   printf("data :%d\r\n",data);
   output_toggle(pin_A0);
   output_toggle(pin_A1);

   }
}



=====SLAVE=====
Code:
#include <18F2550.H>

#fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,PLL2,CPUDIV4,NOVREGEN,NOMCLR
#use delay(clock=16000000)

signed int data;
signed int i=1;

void main (void){

   //configure the device to be a slave, data transmitted on H-to-L clock transition
   setup_spi(spi_slave | spi_L_to_H );
   
   output_HIGH(pin_A1); //Led à 0
   output_HIGH(pin_A0); //Led à 0   
   
   while(1){

      while(!spi_data_is_in());
        data=spi_read();
      delay_us(100);

      output_toggle(pin_A1);

      if (data==0x12){
         spi_write(data+i);
         delay_us(100);
          output_toggle(pin_A0);
         i++;
      }
     }
}



=====output=====
Code:
data :19
data :20
data :21
data :22
data :23
data :24
data :25
data :26
data :27
data :28
data :29
...
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Apr 12, 2012 12:21 pm     Reply with quote

You missed the last part of my post.
The master code needs to have the 0x00 parameter in the spi_read():
Code:

data=spi_read(0);


To temtronic:
He is using a software UART. The ERRORS statement doesn't do anything
on a software UART. It's ignored by the compiler.
thibow



Joined: 11 Apr 2012
Posts: 30

View user's profile Send private message

PostPosted: Thu Apr 12, 2012 12:29 pm     Reply with quote

PCM Programmer, I tried to add 0x00 in spi_read() but it messed everything up, the output was:

Code:

data: 0
data: 0
data: 0
data: -1
data: 0
data: 0
data: 0
data: -1
...



Plus, the master PIC should not be able to read what is sent to the slave, the master is never sent 18 by the slave..

There is something wrong with the buffer.. The master seems to be able to read in the slave's buffer.. it's weird
jeremiah



Joined: 20 Jul 2010
Posts: 1354

View user's profile Send private message

PostPosted: Thu Apr 12, 2012 12:50 pm     Reply with quote

You didn't lower your SS pin when you did the read. If you are using SPI you MUST lower the SS line the entire time you are writing/reading to it. The typical transaction is:

lower SS
Write/read as many bytes as you expect
raise SS


You only lower/raise for the first byte (0x12), which is not correct. Without the SS line low, the slave device has no clue you are talking to it at all. SPI is setup to use multiple devices with the individual SS lines telling them which device is currently being talked to.

EDIT: As a note, interrupts do make things simpler. You just weren't using them as they are designed to be used. They are meant to signal to your main code that something happened so that you main code can address them at its leisure. You were tossing in print statements, which take a long time, into places where you are supposed to get in and then out really quickly. I'm not sure about SPI specifically, but most communications interrupts expect you to read the relevant buffer when they trigger. You weren't doing that in your slave interrupt at all (maybe one of the more experienced guys can comment on if that is required for SPI...it is for I2C and UART though if you use those interrupts).
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Apr 12, 2012 1:05 pm     Reply with quote

This thread has an example of an SPI Master/Slave program for two PICs:
http://www.ccsinfo.com/forum/viewtopic.php?t=39145
Here's an SPI slave test program for a single PIC:
http://www.ccsinfo.com/forum/viewtopic.php?t=26888
thibow



Joined: 11 Apr 2012
Posts: 30

View user's profile Send private message

PostPosted: Thu Apr 12, 2012 1:32 pm     Reply with quote

to Jeremiah, I tried just to have interrupt on master and use low/high ss for read and write, but I still have 2 answer..
in the slave :
Code:
#int_SSP
void Interruption(){
        data=spi_read();
      delay_us(100);

      output_toggle(pin_A1);

      if (data==0x12){
         spi_write(data+i);
         delay_us(100);
          output_toggle(pin_A0);
         i++;
      }
}


master:
Code:
 while(1){
   
   output_LOW(pin_A5);
   spi_write(0x12);
   output_HIGH(pin_A5);

   delay_ms(500);
   output_LOW(pin_A5);
   data=spi_read();
   
   output_HIGH(pin_A5);
   printf("data :%d\r\n",data);
   output_toggle(pin_A0);
   output_toggle(pin_A1);

   }


output:
Code:
data :61
data :18
data :62
data :18
data :63
data :18
data :64
data :18
data :65
data :18
data :66
data :18


@PCM, I'll have a look thank you.. I really can't figure out what's happening, .. I'll give a shot using spi_read(0) and Low/high as well as some other modification ..


Last edited by thibow on Thu Apr 12, 2012 2:00 pm; edited 1 time in total
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
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