SPI master & slave,received value changed if >127

Hello,

I am using 1 Arduino 2009 as a SPI Master, and another Arduino 2009 as a SPI Slave.

when the SPI Slave received the value, it is printed out to the Serial Monitor by using Serial.println.

Both is working fine, but if the value is larger than 127, it is received but FFFFFF is added before the value.

here is the Spi library, which is based on Spi library found in
http://www.arduino.cc/playground/Code/Spi

but I changed the type from byte to uint8_t

#ifndef Spi_h
#define Spi_h

#include "WProgram.h"
#include <inttypes.h>

#define SCK_PIN   13
#define MISO_PIN  12
#define MOSI_PIN  11
#define SS_PIN    10

class SPI
{
  public:
    SPI(void);
    void mode(uint8_t);
    void SPI_SlaveInit(void);
    uint8_t SPI_SlaveReceive(void);
    uint8_t transfer(uint8_t);
    uint8_t transfer(uint8_t, uint8_t);
};

extern SPI Spi;

#endif

Here is the cpp file

#include "WProgram.h"
#include "Spi.h"

//---------- constructor ----------------------------------------------------

SPI::SPI()
{

}

//------------------ mode ---------------------------------------------------

void SPI::mode(byte config)
{  byte tmp;
    // initialize the SPI pins
  pinMode(SCK_PIN, OUTPUT);
  pinMode(MOSI_PIN, OUTPUT);
  pinMode(MISO_PIN, INPUT);
  pinMode(SS_PIN, OUTPUT);

  // enable SPI master with configuration byte specified
  SPCR = 0;
  SPCR = (config & 0x7F) | (1<<SPE) | (1<<MSTR);
  tmp = SPSR;
  tmp = SPDR;
}
void SPI::SPI_SlaveInit(void)
{
  /* Set MISO output, all others input */
  //DDR_SPI = ( 1 <<DD_MISO);
  pinMode(SCK_PIN, INPUT);
  pinMode(MOSI_PIN, INPUT);
  pinMode(MISO_PIN, OUTPUT);
  pinMode(SS_PIN, INPUT);
  /* Enable SPI */
 // SPCR = ( 1 <<SPE)|(0<<MSTR);
   SPCR = B01000000;//SPIE=0,SPE=1,DORD=0,MSTR=0,CPOL=0,CPOL=0,SPR=00
}

uint8_t SPI::SPI_SlaveReceive(void)
{
  /*Wait for reception complete */
  while(!(SPSR & (1<<SPIF)))
      ;
    /* Return Data Register */
    return SPDR;
}
//------------------ transfer -----------------------------------------------

uint8_t SPI::transfer(uint8_t value)
{
  SPDR = value;
  while (!(SPSR & (1<<SPIF))) ;
  return SPDR;
}


uint8_t SPI::transfer(uint8_t value, uint8_t period)
{
  SPDR = value;
  if (period > 0) delayMicroseconds(period);
  while (!(SPSR & (1<<SPIF))) ;
  return SPDR;
}


//---------- preinstantiate SPI object --------------------------------------

SPI Spi = SPI();

Here's the PDE file for SPI slave

/* SPI slave */
#include "Spi.h"


void setup()
{
  Serial.begin(9600);
  Spi.SPI_SlaveInit();
}

void loop()
{
  char RX_Data;
  RX_Data = Spi.SPI_SlaveReceive();
//  Serial.println(RX_Data);
  Serial.println(RX_Data, HEX);
  Serial.println("rx");
}

Here's the PDE for SPI Master

/* SPI Master */
#include "Spi.h"


void setup()
{
  Spi.mode(B01010000);//MSB first,Master,CPOL=0,CPHA=0,SPR=00
}

int i;

void loop()
{
  for(i=0;i<255;i++)
  {
    digitalWrite(SS_PIN, LOW);
    Spi.transfer(i);
    digitalWrite(SS_PIN, HIGH);
    delay(100);
  }
//  digitalWrite(SS_PIN, LOW);
//  Spi.transfer(0xF0);
//  digitalWrite(SS_PIN, HIGH);
//  delay(100);
}

Can someone help to tell me why?

Cheers
Joseph

Hi,

Here's the output I get:

Cheers

Joseph

Try this small change to the SPI slave code...

void loop()
{
  [glow]uint8_t[/glow] RX_Data;

Hi,

I just tried, but I still get FFFFFFxx when larger than 127

Cheers

Joseph

Ugh. Sign extension can be such a pain. I can never remember the rules.

Does this help...

  Serial.println( [glow](unsigned long)[/glow]RX_Data, HEX );

Hi,

I tried once again, but this time power off and power on the 2 boards. by changing to uint8_t works!! :smiley: :smiley:

Also I tried to change them to type byte, and it is also working flawlessly

Thanks a lot for your help

Joseph

:-? Now I'm really confused. The HP C++ documentation clearly indicates that an unsigned char is sign extended when cast to a long. I guess I should have kept Googling!

Glad you're back on track!

Hi,

I found that using uint8_t prints correctly, no more FFFFFF in the front.

Actually uint8_t is just the same as byte.

I now love to use uint8_t whenever possible.

The problem is in the SPI slave PDE, which I was defining
"char i"
which should be "uint8_t i" or "byte i"

but I ain't sure what will happen if using this

Serial.println( (unsigned long)RX_Data, HEX );

As the data is a 8-bit, so should it be type cast into a unsigned long?

Cheers,

Joseph

As the data is a 8-bit, so should it be type cast into a unsigned long?

Your code is working the way you want so there's no need to cast.

I suggested casting because this call...

  Serial.println(RX_Data, HEX);

...maps to this Serial method...

    void println(long, int);

...so there's an implicit cast to long. I thought forcing the value to unsigned long first may stop the sign extension.

Thanks,

Yes, the Arduinos are talking happily now. I guess as println is type long ( 4 bytes), and that's why I get FFFFFFxx printed out

Thanks for the help

Cheers
Joseph

Do you think if I tried this with an arduino and another atmega or pic micro it would be able to communicate?

The arduino being the slave and an atmega32A sending just values would be an example.

Hello,

As there is so many flavours of SPI out there, so if you follow the datasheet, and understands how to connect and set up the software, it should be able to communicate.

In my case, I use one ATmega328 as master, and one ATmega168 as slave, and there's no problem.

Actually my next step is to have an ARM as SPI Master, ATmega as Slave.

Short answer is Yes

Cheers
Joseph

What is a better connection, SPI or UART. I have two Arduinos talking so far but if I use a different family which is better?

Hello,

I don't think there is any better between 2 methods

It really depends on what you want to achieve and what pinouts are availble. For Arduinos, the UART has been used for downloading firmware for PC. Of course you can reprogram the pins for other purpose after download.

UART is basically Tx, Rx and GND in Arduinos. In the old days, you can think of this for connecting a dump terminal to a computer using this method. So there is no master / slave in such communications

SPI consists of SCK, MISO, MOSI, and SS. So you need to define which is master, and which is slave. And you can add extra select pins for communicating with more than 1 slave. Basically the communications are based on SCK pulses

Maybe you can tell us what you're going to do with 2 AVRs connecting together

Cheers
Joseph

I was thinking of using an Arduino with and Atmega328p and an atmel atmega32A. The Arduino would receive two bytes, x and y position, to display on 4 8x8 dot matrices I already have working. The Arduino would send the atmega32A a start and stop signal, I was thinking of using 2 lines from the Arduino so when they are high the signal a start tracking and the other is an end tracking. So would uart be more effective?

Hello,

I think UART is fine for such and you are familiar with it. But I didn't have much experience in UART, but I think the Arduino Serial Library is a good starting point. I think you can use some pre-defined character(s) as comand bytes for the Atmeg32A. I cannot think of any examples right now. Maybe you can do some google search and posting your questions in this forum. I found the Arduino community is very helpful.

You can also do so with SPI. SPI has been vastly used for peripherals like touchscreen sensor chip, SPI flash etc. Your Arduino is a Master and sending out bytes via MOSI line. When Your Atmega32A is triggered by SPI slave select and getting the data from yr Arduino, your Atmega32A can reply back via MISO line

Cheers
Joseph