Go Down

Topic: SPI Communication using ONLY arduino libraries- no AVR code! (Read 5428 times) previous topic - next topic

eriknyquist

Jan 08, 2013, 12:02 pm Last Edit: Jan 08, 2013, 12:16 pm by eriknyquist Reason: 1
I am trying to suss out how to get SPI communication going between two UNOs using only the Arduino libraries, so that my program will work the same on my chipKit UNO32 and my Leaflabs Maple board. I have a super simple master test program here;

Code: [Select]

#include <SPI.h>

char x = 'A';
void setup()
{
SPI.begin();

pinMode(SS, OUTPUT);
digitalWrite(SS, HIGH);
}

void loop()
{
SPI.transfer(x);
delay(500);
}



but I'm having trouble writing the slave side, mainly because I don't fully understand the SPI.transfer(); function. Does this function control both sending AND recieving data on the SPI bus? if anyone could show me some slave code (Arduino libraries only!)  that would work with the master code above that would be awesome!

johnwasser

You have to take SS low for the duration of the sending/receiving.
Code: [Select]

void loop() {
    digitalWrite(SS, LOW);
    SPI.transfer(x);
    digitalWrite(SS, HIGH);
    delay(500);
}

Send Bitcoin tips to: 1G2qoGwMRXx8az71DVP1E81jShxtbSh5Hp

nickgammon

All should be revealed here:

http://gammon.com.au/spi
Please post technical questions on the forum, not by personal message. Thanks!

More info: http://www.gammon.com.au/electronics

eriknyquist

Nick, that's a very helpful page indeed but I'm wondering is it possible to make an equivalent slave program without directly addressing the AVR registers? for example when you turn on SPI in slave mode;
Code: [Select]

SPCR |= _BV(SPE);

because this won't work on my chipKit UNO32 board.

johnwasser


I'm wondering is it possible to make an equivalent slave program without directly addressing the AVR registers? for example when you turn on SPI in slave mode;
Code: [Select]

SPCR |= _BV(SPE);

because this won't work on my chipKit UNO32 board.

I don't think the Arduino SPI library covers slave mode so you are out of luck.  You'll have to figure out how to do it on the PIC processor.
Send Bitcoin tips to: 1G2qoGwMRXx8az71DVP1E81jShxtbSh5Hp

nickgammon

Turn that line into a function. Find an equivalent on the PIC. You will probably need some "glue" routines anyway unless both libraries work in exactly the same way and have the same names.
Please post technical questions on the forum, not by personal message. Thanks!

More info: http://www.gammon.com.au/electronics

eriknyquist

dammit you're right, Arduino API doesn't cover slave mode.....why arduino?? why??
Anyway thanks for your help guys, Nick I'm sure I'll find a way around it, maybe I'll just bite the bullet and write a SPI slave lib. If i do then I'll make sure to share it up here!

retrolefty


dammit you're right, Arduino API doesn't cover slave mode.....why arduino?? why??
Anyway thanks for your help guys, Nick I'm sure I'll find a way around it, maybe I'll just bite the bullet and write a SPI slave lib. If i do then I'll make sure to share it up here!


Are you sure?:

http://arduino.cc/forum/index.php/topic,22187.0.html

Lefty

johnwasser



dammit you're right, Arduino API doesn't cover slave mode.....why arduino?? why??
Anyway thanks for your help guys, Nick I'm sure I'll find a way around it, maybe I'll just bite the bullet and write a SPI slave lib. If i do then I'll make sure to share it up here!


Are you sure?:

http://arduino.cc/forum/index.php/topic,22187.0.html

Lefty


Looks like that example uses direct register manipulation on the Slave side:
Code: [Select]

void SlaveInit(void) {
  // Set MISO output, all others input
  pinMode(SCK_PIN, INPUT);
  pinMode(MOSI_PIN, INPUT);
  pinMode(MISO_PIN, OUTPUT);
  pinMode(SS_PIN, INPUT);

  // Enable SPI
  SPCR = B00000000;
  SPCR = (1<<SPE);
}

byte ReadByte(void) {
  while(!(SPSR & (1<<SPIF))) ;
  return SPDR;
}

void WriteByte(byte value) {
  SPDR = value;
  while (!(SPSR & (1<<SPIF))) ;
  return;
}


That code won't fly on the PIC processor.
Send Bitcoin tips to: 1G2qoGwMRXx8az71DVP1E81jShxtbSh5Hp

eriknyquist

yup exactly. Lefty, implementing a SPI slave with an arduino is of course possible, but it's not supported by the arduino libraries. If you want to do it then you have to refer to the datasheet for the '328 and write directly to the registers, a task that is normally hidden by the fluffy arduino libraries.
The datasheet for the PIC32 MCU is unfortunately not as clear as the 328, was looking through it today and I can see no easy way of doing this yet (i.e. I can't just swap out the register names for the names of the corresponding registers in the PIC).

retrolefty


yup exactly. Lefty, implementing a SPI slave with an arduino is of course possible, but it's not supported by the arduino libraries. If you want to do it then you have to refer to the datasheet for the '328 and write directly to the registers, a task that is normally hidden by the fluffy arduino libraries.
The datasheet for the PIC32 MCU is unfortunately not as clear as the 328, was looking through it today and I can see no easy way of doing this yet (i.e. I can't just swap out the register names for the names of the corresponding registers in the PIC).


I guess I miss your point or complaint. The arduino supplied SPI library (SPI.h and SPI.cpp) is nothing but filled with AVR register names. So you want to use arduino SPI API or not? Or are you talking about some other arduino library/API ?

Lefty




johnwasser


I guess I miss your point or complaint. The arduino supplied SPI library (SPI.h and SPI.cpp) is nothing but filled with AVR register names. So you want to use arduino SPI API or not? Or are you talking about some other arduino library/API ?


The "chipKit UNO32" uses a 32-bit PIC processor rather than an ATmega.  They implement the Arduino core libraries so in many cases you can write an Arduino sketch and have it run on the chipkit UNO32.  You can't run any Arduino sketches that require direct register manipulation.  Since the Arduino core SPI library only supports Master mode you can't write a Slave mode SPI sketch that will run on both an Arduino and a chipkit UNO32.
Send Bitcoin tips to: 1G2qoGwMRXx8az71DVP1E81jShxtbSh5Hp

retrolefty



I guess I miss your point or complaint. The arduino supplied SPI library (SPI.h and SPI.cpp) is nothing but filled with AVR register names. So you want to use arduino SPI API or not? Or are you talking about some other arduino library/API ?


The "chipKit UNO32" uses a 32-bit PIC processor rather than an ATmega.  They implement the Arduino core libraries so in many cases you can write an Arduino sketch and have it run on the chipkit UNO32.  You can't run any Arduino sketches that require direct register manipulation.  Since the Arduino core SPI library only supports Master mode you can't write a Slave mode SPI sketch that will run on both an Arduino and a chipkit UNO32.


So his complaint should really be issued against the chipKit implementers of their "Arduino API like core"? I assume they have implemented PIC hardware serial commands that mimic the arduino hardware serial library functions that uses AVR registers? Why would they support a standard comm such as serial and not the standard SPI communications? My confusion is most based on his "Arduino API doesn't cover slave mode.....why arduino?? " comment. Arduino does support SPI slave mode for AVR chips, why is this a Arduino API fault?

Lefty

nickgammon

Yes, I don't really see the problem. To make the same code work on different chips you would need some sort of "glue" interface library that, inside, uses #ifdef to select the Arduino API call or the PIC API call.
Please post technical questions on the forum, not by personal message. Thanks!

More info: http://www.gammon.com.au/electronics

skyjumper

When coding micro controllers, its not unreasonable to expect some of the code to be hardware specific. The differences are probably beyond just register names. Different chips work differently. Some macro definitions may be all you need to solve it though.

Go Up