Pages: [1] 2   Go Down
Author Topic: SPI master & slave,received value changed if >127  (Read 2489 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 50
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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 [glow]byte[/glow] to [glow]uint8_t[/glow]
Code:
#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

Code:
#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
Code:
/* 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
Code:
/* 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
Logged

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 50
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,

Here's the output I get:



Cheers

Joseph
Logged

Global Moderator
Dallas
Offline Offline
Shannon Member
*****
Karma: 176
Posts: 12286
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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

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

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 50
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,

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


Cheers

Joseph
Logged

Global Moderator
Dallas
Offline Offline
Shannon Member
*****
Karma: 176
Posts: 12286
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Does this help...

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

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 50
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,

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

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

Thanks a lot for your help


Joseph
Logged

Global Moderator
Dallas
Offline Offline
Shannon Member
*****
Karma: 176
Posts: 12286
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

 :-?  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!
Logged

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 50
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Code:
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
Logged

Global Moderator
Dallas
Offline Offline
Shannon Member
*****
Karma: 176
Posts: 12286
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
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...

Code:
 Serial.println(RX_Data, HEX);

...maps to this Serial method...

Code:
   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.
Logged

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 50
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 37
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
« Last Edit: February 15, 2010, 08:43:57 pm by worldisorder » Logged

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 50
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 37
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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?
Logged

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 50
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 37
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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?
Logged

Pages: [1] 2   Go Up
Jump to: