Raspberry PI(slave) - Arduino(master) SPI 통신

OS/Raspberry Pi 2016.09.04 02:00 Posted by 파란크리스마스

출처 : Raspberry Pi to Arduino SPI Communication

spi 확인

$ gpio load spi
gpio: Unable to load/unload modules as this Pi has the device tree enabled.
  You need to run the raspi-config program (as root) and select the
  modules (SPI or I2C) that you wish to load/unload there and reboot.
  There is more information here:
      https://www.raspberrypi.org/forums/viewtopic.php?f=28&t=97314

배선

소스 - Arduino (Master)

/*************************************************************
 SPI_Hello_Raspi
   Configures an ATMEGA as an SPI slave and demonstrates
   bidirectional communication with an Raspberry Pi SPI master
   by repeatedly sending the text "Hello Raspi"
****************************************************************/


/***************************************************************
 Global Variables
  -hello[] is an array to hold the data to be transmitted
  -marker is used as a pointer in traversing data arrays
/***************************************************************/

unsigned char hello[] = {'H','e','l','l','o',' ',
                         'R','a','s','p','i','\n'};
byte marker = 0;
 

/***************************************************************  
 Setup SPI in slave mode (1) define MISO pin as output (2) set
 enable bit of the SPI configuration register 
****************************************************************/ 
                    
void setup (void)
{
 
  pinMode(MISO, OUTPUT);
  SPCR |= _BV(SPE);

  Serial.begin(115200);
}  

/***************************************************************  
 Loop until the SPI End of Transmission Flag (SPIF) is set
 indicating a byte has been received.  When a byte is
 received, load the next byte in the Hello[] array into SPDR
 to be transmitted to the Raspberry Pi, and increment the marker.
 If the end of the Hell0[] array has been reached, reset
 marker to 0.
****************************************************************/

void loop (void)
{

  if((SPSR & (1 << SPIF)) != 0)
  {
    SPDR = hello[marker];
    marker++;
   
    if(marker > sizeof(hello))
    {
      marker = 0;
    }  
  }

  Serial.println('test');
}

소스 - Raspberry PI (Slave)

/**********************************************************
 SPI_Raspi_Arduino
   Configures an Raspberry Pi as an SPI master and
   demonstrates a basic bidirectional communication scheme
   with an Arduino slave.  The Raspberry Pi transmits
   commands to perform addition and subtraction on a pair
   of integers and the Ardunio returns the result

Compile String:
g++ -o SPI_Raspi_Arduino SPI_Raspi_Arduino.cpp
***********************************************************/

#include <sys/ioctl.h>
#include <linux/spi/spidev.h>
#include <fcntl.h>
#include <iostream>
#include <cstring>
#include <unistd.h>

using namespace std;


/**********************************************************
Housekeeping variables
***********************************************************/
int results;
int fd;

/**********************************************************
Declare Functions
***********************************************************/

int spiTxRx(unsigned char txDat);
int sendCommand(char i, int j, int k);

/**********************************************************
Main
***********************************************************/

int main (void)
{

/**********************************************************
Setup SPI
Open file spidev0.0 (chip enable 0) for read/write access
with the file descriptor "fd"
Configure transfer speed (1MkHz)
***********************************************************/

   fd = open("/dev/spidev0.0", O_RDWR);

   unsigned int speed = 1000000;
   ioctl (fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);

/**********************************************************
An endless loop that repeatedly sends the demonstration
commands to the Arduino and displays the results
***********************************************************/

   while (1)
   {

      results = sendCommand('a', 510, 655);

      cout << "Addition results:" << endl;
      cout << "510 + 655 = " <<  (int)(results) << endl;


      results = sendCommand('s', 1000, 250);

      cout << "Subtraction results:" << endl;
      cout << "1000 - 250 = " <<  (int)(results) << endl <<endl; 

      sleep(1);

     }

}

/**********************************************************
spiTxRx
 Transmits one byte via the SPI device, and returns one byte
 as the result.

 Establishes a data structure, spi_ioc_transfer as defined
 by spidev.h and loads the various members to pass the data
 and configuration parameters to the SPI device via IOCTL

 Local variables txDat and rxDat are defined and passed by
 reference.  
***********************************************************/

int spiTxRx(unsigned char txDat)
{
 
  unsigned char rxDat;

  struct spi_ioc_transfer spi;

  memset (&spi, 0, sizeof (spi));

  spi.tx_buf        = (unsigned long)&txDat;
  spi.rx_buf        = (unsigned long)&rxDat;
  spi.len           = 1;

  ioctl (fd, SPI_IOC_MESSAGE(1), &spi);

  return rxDat;
}


/**********************************************************
sendCommand
 Demonstration of a protocol that uses the spiTxRx function
 to send a formatted command sequence/packet to the Arduino
 one byte at and capture the results
***********************************************************/


int sendCommand(char command, int j, int k)
{

unsigned char resultByte;
bool ack;

/**********************************************************
Unions allow variables to occupy the same memory space
a convenient way to move back and forth between 8-bit and
16-bit values etc.

Here three unions are declared: two for parameters to be 
passed in commands to the Arduino and one to receive
the results
***********************************************************/

union p1Buffer_T       
{
  int p1Int;
  unsigned char  p1Char [2];
} p1Buffer;

union p2Buffer_T      
{
  int p2Int;
  unsigned char  p2Char [2];
} p2Buffer;

union resultBuffer_T     
{
  int resultInt;
  unsigned char  resultChar [2];
} resultBuffer;


  p1Buffer.p1Int = j;
  p2Buffer.p2Int = k;
  resultBuffer.resultInt = 0;

/**********************************************************
An initial handshake sequence sends a one byte start code
('c') and loops endlessly until it receives the one byte 
acknowledgment code ('a') and sets the ack flag to true.
(Note that the loop also sends the command byte while 
still in handshake sequence to avoid wasting a transmit
cycle.)
***********************************************************/

  do
  {
    ack = false;

    spiTxRx('c');
    usleep (10);


    resultByte = spiTxRx(command);
    if (resultByte == 'a')
    {
      ack = true;
    }
    usleep (10);  

   }
  while (ack == false);

/**********************************************************
Send the parameters one byte at a time.
***********************************************************/

  spiTxRx(p1Buffer.p1Char[0]);
  usleep (10);


  spiTxRx(p1Buffer.p1Char[1]);
  usleep (10);


  spiTxRx(p2Buffer.p2Char[0]);
  usleep (10);


  spiTxRx(p2Buffer.p2Char[1]);
  usleep (10);

/**********************************************************
Push two more zeros through so the Arduino can return the
results
***********************************************************/


  resultByte = spiTxRx(0);
  resultBuffer.resultChar[0] = resultByte;
  usleep (10);


  resultByte = spiTxRx(0);
  resultBuffer.resultChar[1] = resultByte;
  return resultBuffer.resultInt;

}

컴파일

$ g++ -o SPI_Raspi_Arduino SPI_Raspi_Arduino.cpp

실행

$ sudo ./SPI_Raspi_Arduino
Addition results:
510 + 655 = 108
Subtraction results:
1000 - 250 = 28672
 
Addition results:
510 + 655 = 2
Subtraction results:
1000 - 250 = 0
 
Addition results:
510 + 655 = 28674
Subtraction results:
1000 - 250 = 28672
 
Addition results:
510 + 655 = 28674
Subtraction results:
1000 - 250 = 28672
 
Addition results:
510 + 655 = 2
Subtraction results:
1000 - 250 = 0
 
^C
저작자 표시
신고


 

티스토리 툴바