2

I've been struggling for 3 weeks looking for a solution to my problem concerning SPI communication.

So, I need to establish a SPI communication between two Arduino devices: for instance, the master sends a letter 'a' to the slave; the slave receives it and does some processing. In my case, it should set one of his 8 pins to high then read all pins and send the report back to the master.

The part where the master sends 'a' and the slave processing it works fine but the master doesn't seem to receive the correct values. Instead it always receives 0.

Here's the code:


Slave:

#include <SPI.h>;
volatile byte command = 0;
byte ett =8; //nbr of test points
byte motif= 0b000000000 ; //intiatition of my varible which will contain my pin's states
byte end[8] = { 2,3,4,5,6,7,8,9}; //array containing the pins
void setup (void) {
 Serial.begin (9600);
 // have to send on master in, *slave out*
 pinMode(MISO, OUTPUT);
 // turn on SPI in slave mode
 SPCR |= _BV(SPE);
 // turn on interrupts
 SPCR |= _BV(SPIE);
} // end of setup
// SPI interrupt routine
ISR (SPI_STC_vect) {
 byte c = SPDR;
 switch (command) {
 //////////////Slave traitement/////////////
 // no command? then this is the command
 case 0:
 command = c;
 SPDR = 0;
 break;
 case 'z': ////case 'z", set all pins to INPUT
 for (int i=0; i<8; i++){
 pinMode (end[i], INPUT);
 }
 break;
 case 'a': // //if 'a' : Set one pin to high then read all pin's satete to verify if there is any open circuit or short circuit
 for (int j = 0; j < ett; j++) {
 pinMode(end[j], INPUT); // set all pins as INPUT
 }
 motif = 0;
 pinMode(end[0], OUTPUT); // Set one pin as OUTPUT
 digitalWrite(end[0], HIGH); // Set the output pin to HIGH 
 Serial.println();
 Serial.print(" "); 
 for (int k = 0; k < ett ; k++) { // scan
 if (digitalRead(end[k]) == HIGH) {
 // if pin == HIGH add '1' to my vector
 Serial.print("| ");
 motif = motif + 1; // +1 
 } else { // if pin == LOW
 Serial.print(". ");
 }
 motif = motif << 1; // shift left
 }
 Serial.print(" -MOTIF LU= ");
 Serial.print(motif, BIN); 
 SPDR = byte (motif); //SPDR is the SPI Data Register: it contains the data that will be sent to the Master
 Serial.print(" ");
 break;
 }
}
void loop (void) {
 // if SPI not active, clear current command
 if (digitalRead (SS) == HIGH)
 command = 0;
}

Master:

#include <SPI.h>
byte CS0=10;
byte CS1=9;
void setup (void) {
 Serial.begin (9600);
 Serial.println ();
 digitalWrite(SS, HIGH); // ensure SS stays high for now
 // Put SCK, MOSI, SS pins into output mode
 // also put SCK, MOSI into LOW state, and SS into HIGH state.
 // Then put SPI hardware into Master mode and turn SPI on
 SPI.begin ();
 // Slow down the master a bit
 SPI.setClockDivider(SPI_CLOCK_DIV8);
} // end of setup
byte transferAndWait (const byte what) {
 byte a = SPI.transfer (what);
 delayMicroseconds (1000);
 return a;
} // end of transferAndWait
///traitement au niveau du maitre
void loop (void) {
 byte esclave0_testpin0;
 /////////////Set the first slave's pin to High then read all pins
 digitalWrite (CS0,LOW); //activate the slave
 transferAndWait ('a'); // set first slave's pin to high
 esclave0_testpin0 = transferAndWait ('z'); //read all slave's pins and report it in the variable esclave0_testpin0
 digitalWrite (CS0,HIGH); //disactivate the slave
 Serial.println ("test_0");
 Serial.println (esclave0_testpin0, BIN);
 delay (1000); // 1 second delay 
} // end of loop
dda
1,5951 gold badge12 silver badges17 bronze badges
asked Mar 22, 2017 at 11:30
7
  • Double check your SPI protocol. Is the order correct? A state machine might help understand the sequencing. Also avoid Serial print in ISRs. Commented Mar 22, 2017 at 13:23
  • Some tips: 1) use ctrl-t to autoformat, 2) use { and } consequently regarding new lines, 3) use more clear variable names (also for loop iterators), 4) Write also comments in code in English, 5) motif = motif + 1 , more c is motir++; Commented Mar 22, 2017 at 14:12
  • @MichelKeijzers : Thank you for the tips, but "motif =motif +1"works in my program; i'll add a screenshot of the simulation.The display on the slave monitor is correct. I made a short circuit between the first and the second pins and i i've got " -MOTIF LU= 11000000 ". Commented Mar 23, 2017 at 14:10
  • @MikaelPatel: wrote my code based on this link [gammon.com.au/forum/?id=10892&reply=2#reply2] (Part: How to get a response from a slave) . I tested its code and it worked very well. I did not change anything except the process at the slave level: instead of adding or subtracting I read the state of the slave's pins and report it to the master. Commented Mar 23, 2017 at 14:11
  • @Saha222 Yes it is the same, but it's more 'C' style to write motif++ instead of motif = motif + 1 ... or motif += 1; ...I'm glad you sorted out the problem. Commented Mar 23, 2017 at 15:44

1 Answer 1

1

In slave, command is always 0. You problably meant:

void loop(void) {
 command = (digitalRead(SS) == HIGH ? 0 : 1);
}

and at ISR:

ISR (SPI_STC_vect) {
 byte input = SPDR;
 byte output = 0;
 if (command) {
 switch (input) {
 case 'a':
 //...
 break;
 case 'z':
 //...
 break;
 }
 }
 // send data back
 SPDR = output;
}

As a best practice, avoid to implement the logic within the ISR and use global volatile variables to pass state changes to the code in the main loop. Probably you will have to implement a circular buffer to receive from and send to the SPI bus...

answered Mar 24, 2017 at 4:11

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.