Go Down

Topic: SPI read write for 32bits data (Read 7454 times) previous topic - next topic

Paradigm

Hi, I had a IC that need to be read and write with 32bits data. Can the SPI.h libaray handle 32bits data transfer? How can I declare my variable? Is it long int? Can I program something like SPI.transfer(0xFFFFFFFE);? How about reading?

How can I read a 32bits data from SPI?

Anyone had a file that can read write a 32bits SPI data?

Thanks a lot

dhenry

Sending 8 bits 4 times = sending 32bits.

strykeroz


How can I declare my variable? Is it long int?
That part is up to you.  Depending on where you're receiving this data from, and what it's made up of,  you might declare it as an array of 4 bytes (or characters) or a pair of int, or as a single long.  All will give you 32 bits of data to play with, but when you do the SPI.transfer() for transmit or receive; or ShiftOut() / shiftIn() you'll be sending it in 4 byte-sized pieces (ie 8 bits at a time as dhenry posted above).

How about reading? How can I read a 32bits data from SPI?
The same way, a byte at a time.

What is the IC you're wanting to communicate with?

Cheers ! Geoff
"There is no problem so bad you can't make it worse"
- retired astronaut Chris Hadfield

Tom Carpenter

#3
Nov 19, 2012, 07:36 pm Last Edit: Nov 19, 2012, 07:42 pm by Tom Carpenter Reason: 1
You can use a 'union' to efficiently and quickly convert a long to a series of four bytes or 2 ints or vice versa:
Code: [Select]
#include <SPI.h>

union FourByte{
    unsigned long bit32;
    unsigned int bit16[2];
    unsigned char bit8[4];
};

void setup(){
  SPI.begin();
 
  //save a 32bit value
  unsigned long someValue = 0xFFFFFFFEUL;
  //transmit 32bit value:
  transfer(someValue);
 
  //read 32bit value
  someValue = transfer(0);
 
  //read and write at the same time.
  someValue = transfer(someValue);

  //concatinate ints:
  FourByte bob;
  bob.bit16[0] = 10;
  bob.bit16[1] = 20;
 
  transfer(bob.bit32); //sends 1310730 = 20*65536+10

  //concatinate bytes:
  bob.bit8[0] = 0x1; //1
  bob.bit8[1] = 2; //2
  bob.bit8[2] = 0b11; //3
  bob.bit8[3] = B100; //4
 
  transfer(bob.bit32); //transfers 0x04030201
}

unsigned long transfer(unsigned long value){
  FourByte data = {value};
  for(byte i = 0; i < 4; i++){
    data.bit8[i] = SPI.transfer(data.bit8[i]);
  }
  return data.bit32;
}
~Tom~

Paradigm

Hi,

         If I were to send 4 bytes of data to make up 32bits data transfer, for 0x12345678 to be sent, do I send 0x78 first or do I send 0x12 first?

        As for 4 bytes ready, after reading the 4 bytes, how can I combine them together to become a long int? It is a signed long int

        It is a multimeter IC chip that can measure AC voltage and current.

Paradigm

This is an example C code that I got from a website for this IC. They wrote their own function call SPI_Read. How can I use SPI.h in the arduino library to help me read this 32bits data? Sorry I made a mistake all are unsigned long.

Read_Data=SPI_Read(0x03FEFEFE);

Hope all expert can help. Thanks a lot

Graynomad

Quote
do I send 0x78 first or do I send 0x12 first?

That depends on the "endianness" of the device you are talking to.

If you don't have documentation try one way and if that doesn't work try the other way.

Quote
Read_Data=SPI_Read(0x03FEFEFE);

What's with the huge parameter to a Read function. Is this really a "transfer" that sends 0x03FEFEFE and returns 4 bytes into Read_Data?

Do you have the source to SPI_Read()?

_____
Rob
Rob Gray aka the GRAYnomad www.robgray.com

Paradigm

Sorry I do not have access to the SPI_Read() function. Just asking anyone can help with the 2 functions I need to read and write to my ICs

unsigned long SPI_read(unsigned long Address)

and

void SPI_write(unsigned long Comd)

I dont know what to put inside to this 2 functions so that I can use the SPI.transfer to let my program works. I hope all expert can help me here. Thanks a lot

Graynomad

Many people here could write functions to do this, but without knowing what the chip is there's little point really.

Do you have a data sheet for the chip?

Quote
How can I read a 32bits data from SPI?


var0 = SPI.transfer(0);
var1 = SPI.transfer(0);
var2 = SPI.transfer(0);
var3 = SPI.transfer(0);

But I doubt that will do what you want, we need the chip info.

_____
Rob
Rob Gray aka the GRAYnomad www.robgray.com

Paradigm

Hi Gray,

         Attached is the datasheet. Thanks a lot

retrolefty


Hi Gray,

         Attached is the datasheet. Thanks a lot


Well I think you might be confused. From your datasheet:

Quote

7.4 Command Interface
Commands and data are transferred most-significant bit
(MSB) first. Figure 1 on page 12, defines the serial port
timing. Commands are clocked in on SDI using SCLK.
They are a single byte (8 bits) long and fall into one of
four basic types:
1. Register Read
2. Register Write
3. Synchronizing
4. Instructions


There are 32 different byte size registers to work with on the chip, but it's designed for simple SPI byte size read and write operations.

Lefty

Paradigm

Hi Lefty,

            It says when reading data from SDO, example my instantaneous voltage (which is 32bits), I need to send the SYNC0 and SYNC1 to the SDI pins if not other command is needed. Thats why I need to send (0x04FFFEFF). Or did I misinterpret the datasheet. With CS pin, I dont need to send the SYNC0. Anyhow, my data is also 32bits. How can i read the 32bits data with SPI.transfer? Or write a sub-routine of 

unsigned long SPI_read(byte Address)

7.6.2 Synchronization (SYNC0 and SYNC1)
The serial interface is bidirectional. While reading data on the SDO output, the SDI input must be receiving
commands. If no command is needed during a read, SYNC0 or SYNC1 commands can be sent while read
data is received on SDO.
The serial port is normally initialized by de-asserting CS. An alternative method of initialization is to send 3 or
more SYNC1 commands followed by a SYNC0. This is useful in systems where CS is not used and tied low.

Pls help. Thanks a lot

SurferTim

#12
Nov 20, 2012, 01:33 pm Last Edit: Nov 20, 2012, 02:16 pm by SurferTim Reason: 1
Quote
0x04FFFEFF

If this is what you want to send, and SS is the slave select pin number, then this should do it.
Code: [Select]
digitalWrite(SS,LOW);
var0 = SPI.transfer(0x04);
var1 = SPI.transfer(0xFF);
var2 = SPI.transfer(0xFE);
var3 = SPI.transfer(0xFF);
digitalWrite(SS,HIGH);

edit: Some devices need a small pause between enabling the SPI interface and starting the transfer. I usually put a "delayMicroseconds(1);" after "digitalWrite(SS,LOW);".

Tom Carpenter

#13
Nov 20, 2012, 10:27 pm Last Edit: Nov 22, 2012, 11:02 am by Tom Carpenter Reason: 1
Modified my example from before based on the datasheet:
Code: [Select]
#include <SPI.h>

union FourByte{
   struct {
     unsigned long value:24; //24bit register values go in here
     byte command:8; //8bit command goes in here.
   };
   byte bit8[4]; //this is just used for efficient conversion of the above into 4 bytes.
};

void setup(){
 SPI.begin();
 SPI.setBitOrder(MSBFIRST);
 SPI.setDataMode(SPI_MODE3); //I believe it to be Mode3
  SPI.setClockDivider(SPI_CLOCK_DIV16);
 pinMode(SS, OUTPUT); //not really necessary as it is done by the SPI library.
 digitalWrite(SS, HIGH);
 //Page
 //example of reading data
 unsigned long voltage = SPI_read(4);//Instantaneous Voltage Channel 1
 
 //example of writing data
 union FourByte data;
 data.command = 0b01000000; //Write to config register
 data.value = 1; //This is the default value from datasheet, just using it as an example.
 SPI_write(data);
}

void loop(){
 
}

void SPI_write(union FourByte data) {
 digitalWrite(SS,LOW); //Using CS pin, so sync1/sync0 bytes not needed
 for(char i = 3; i >= 0; i--){
   SPI.transfer(data.bit8[i]); //transfer all 4 bytes of data - command first, then Big Endian transfer of the 24bit value.
 }
 digitalWrite(SS,HIGH);
}

unsigned long SPI_read(byte command){
 digitalWrite(SS,LOW); //SS goes low to mark start of transmission
 union FourByte data = {0xFEFEFE,command}; //generate the data to be sent, i.e. your command plus the Sync bytes.
 for(char i = 3; i >= 0; i--){
   data.bit8[i] = SPI.transfer(data.bit8[i]); //send the data whilst reading in the result
 }
 digitalWrite(SS,HIGH); //SS goes high to mark end of transmission
 return data.value; //return the 24bit value recieved.
}
~Tom~

Jaay

#14
Nov 22, 2012, 03:05 am Last Edit: Nov 22, 2012, 05:05 am by Nick Gammon Reason: 1
I changed to this...but still not working...

Code: [Select]
#include <SPI.h>

int CS = 10;


union FourByte{
   struct {
     unsigned long value:24; //24bit register values go in here
     byte command:8; //8bit command goes in here.
   };
   byte bit8[4]; //this is just used for efficient conversion of the above into 4 bytes.
};

void setup(){
 SPI.begin();
 SPI.setBitOrder(MSBFIRST);
 SPI.setDataMode(SPI_MODE0);
 
 Serial.begin(9600);
 pinMode(CS, OUTPUT);
 digitalWrite(CS, HIGH);
 //Page
 //example of reading data
// unsigned long voltage = SPI_read(0x04);//Instantaneous Voltage Channel 1
 
 //example of writing data
 union FourByte INI;
 INI.command = 0b11111111; //Write to config register
 INI.value = 0xFFFFFE; //This is the default value from datasheet, just using it as an example.
 SPI_write(INI);
 
 
 union FourByte data;
 data.command = 0b11101000; //Write to config register
 data.value = 0xFFFFFE; //This is the default value from datasheet, just using it as an example.
 SPI_write(data);
}

void loop(){
 unsigned long voltage = SPI_read(0x04);
 Serial.print("Voltage=");
 Serial.println(voltage);
 delay(1000);
}

void SPI_write(union FourByte data) {
 digitalWrite(CS,LOW); //Using CS pin, so sync1/sync0 bytes not needed
 for(char i = 3; i >= 0; i--){
   SPI.transfer(data.bit8[i]); //transfer all 4 bytes of data - command first, then Big Endian transfer of the 24bit value.
 }
 digitalWrite(CS,HIGH);
}

unsigned long SPI_read(byte command){
 digitalWrite(CS,LOW); //SS goes low to mark start of transmission
 union FourByte data = {0xFEFEFE,command}; //generate the data to be sent, i.e. your command plus the Sync bytes.
 for(char i = 3; i >= 0; i--){
   data.bit8[i] = SPI.transfer(data.bit8[i]); //send the data whilst reading in the result
 }
 digitalWrite(CS,HIGH); //SS goes high to mark end of transmission
 return data.value; //return the 24bit value recieved.
}



Go Up