문제

I've got wiringpi2 and the the wiringpi2 python wrapper installed on the NOOBS Raspbian PI distro. The Adafruit 4 channel logic level converter kept the PI safe from 5v and sending data to the Arduino was as simple as this on the PI side:

import wiringpi2
wiringpi2.wiringPiSPISetup(1,5000)
wiringpi2.wiringPiSPIDataRW(1,'HELLO WORLD\n')

and the corresponding Arduino code[3].

EDIT: Apologies - from this point on, I can't post any more of the links I carefully added to show my working, sources and example code. You'll have to Google it and thank the 2-link rule.

So, I know the wiring works. But that's not the way round I actually want - I want to read a pin from the Arduino to the PI.

The Arduino SPI reference states:

This library allows you to communicate with SPI devices, with the Arduino as the master device.

The PI must be the master device. I thought I was doomed until I read Nick Gammon's excellent page about SPI which demonstrates 2 Arduinii talking to each other.

Also, the SPI transfer() command would suggest you CAN write from the Arduino.

I'm now at the stage where all the links of the the first 4 result pages of Google show as "followed" - so it's not for lack of Googling!

In theory, shouldn't this work if I use the READ method on the PI end? (Note: this is just one of many, many attempts, not the only one!)

On the Arduino:

#include <SPI.h>
void setup (void)
{
  SPI.begin();
  pinMode(MISO, OUTPUT);

  // turn on SPI in slave mode
  SPCR |= _BV(SPE);
}

void loop  (void) {
byte data[] = {0x00, 0x00, 0x00, 0x00};  // this is 24 bits (8bits/byte * 4 bytes)
// Transfer 24 bits of data
for (int i=0; i<4; i++) {
   SPI.transfer(data[i]);   // Send 8 bits
}
}

And on the PI end of things:

import wiringpi2
wiringpi2.wiringPiSPISetup(1,5000)
stuff = wiringpi2.wiringPiSPIDataRW(1,'\n')
print stuff

WiringPI says the incoming data will overwrite my data, and the SPIDataRW takes exactly 2 inputs, so shouldn't I be getting "test" back?

What am I missing here? Any pointers greatly appreciated.

도움이 되었습니까?

해결책

The SPI library assumes you want the arduino to act as a master. You can't use it to get an arduino to act as a slave. Sometimes you have to dive past the libraries into the chip's datasheet and see how things work. (and then, ideally, make a library from all your troubles)

An SPI slave device has to react to the master initiating the communication.

So the Pi, as the SPI master, will have to send dummy bytes over the MOSI line and read what the Arduino replies on the MISO line. ie, master initiate communication.

On the arduino side you can turn on the SPI interrupt with:

SPCR |= _BV(SPIE);

It's built into the atmega328 chip. So include this next bit on the arduino side to see incoming messages and set the response for the next message. The data that the arduino SPI slave responds with is whatever is in the data register when the master sends the message.

int gCurrentSpiByte;  //or set up your a buffer or whatever
ISR (SPI_STC_vect)
{
  gCurrentSpiByte = SPDR;  // grab byte from SPI Data Register
  SPDR = buf[messageCount++]; //Set the data to be sent out on the NEXT message.
}

And remember, you GOTTAGOFAST. If the arduino doesn't exit that interrupt service routine before the next SPI message comes it, it all goes to hell.

Also also, check to make sure the clock's polarity and phase are the same between the Pi and the Arduino (otherwise known as modes 0-3).

| 7    | 6    | 5    | 4    | 3    | 2    | 1    | 0    |
| SPIE | SPE  | DORD | MSTR | CPOL | CPHA | SPR1 | SPR0 |

SPIE - Enables the SPI interrupt when 1
SPE - Enables the SPI when 1
DORD - Sends data least Significant Bit First when 1, most Significant Bit first when 0
MSTR - Sets the Arduino in master mode when 1, slave mode when 0
CPOL - Sets the data clock to be idle when high if set to 1, idle when low if set to 0
CPHA - Samples data on the falling edge of the data clock when 1, rising edge when 0
SPR1 and SPR0 - Sets the SPI speed, 00 is fastest (4MHz) 11 is slowest (250KHz)

So to turn on SPI, the SPI interrupt, and to set the polarity to... whatever that is...

SPCR |= _BV(SPIE) | _BV(SPE) | _BV(CPOL) ;

Anyway, I spent a couple days banging around with the Arduino SPI and that's what I learned.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top