Pages: [1] 2 3   Go Down
Author Topic: SPI read write for 32bits data  (Read 4770 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Jr. Member
**
Karma: 0
Posts: 58
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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
Logged

Offline Offline
Edison Member
*
Karma: 116
Posts: 2205
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Sending 8 bits 4 times = sending 32bits.
Logged

Brisbane, Australia
Offline Offline
Edison Member
*
Karma: 29
Posts: 1071
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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
Logged

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

Leeds, UK
Offline Offline
Edison Member
*
Karma: 71
Posts: 1641
Once the magic blue smoke is released, it won't go back in!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
#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;
}
« Last Edit: November 19, 2012, 01:42:55 pm by Tom Carpenter » Logged

~Tom~

Offline Offline
Jr. Member
**
Karma: 0
Posts: 58
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Offline Offline
Jr. Member
**
Karma: 0
Posts: 58
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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
Logged

nr Bundaberg, Australia
Offline Offline
Tesla Member
***
Karma: 121
Posts: 8439
Scattered showers my arse -- Noah, 2348BC.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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
Logged

Rob Gray aka the GRAYnomad www.robgray.com

Offline Offline
Jr. Member
**
Karma: 0
Posts: 58
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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
Logged

nr Bundaberg, Australia
Offline Offline
Tesla Member
***
Karma: 121
Posts: 8439
Scattered showers my arse -- Noah, 2348BC.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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
Logged

Rob Gray aka the GRAYnomad www.robgray.com

Offline Offline
Jr. Member
**
Karma: 0
Posts: 58
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi Gray,

         Attached is the datasheet. Thanks a lot

* CS5464_F3.pdf (476.9 KB - downloaded 35 times.)
Logged

Left Coast, CA (USA)
Offline Offline
Brattain Member
*****
Karma: 331
Posts: 16514
Measurement changes behavior
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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
Logged

Offline Offline
Jr. Member
**
Karma: 0
Posts: 58
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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
Logged

Miramar Beach, Florida
Offline Offline
Faraday Member
**
Karma: 115
Posts: 5377
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
0x04FFFEFF
If this is what you want to send, and SS is the slave select pin number, then this should do it.
Code:
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);".
« Last Edit: November 20, 2012, 08:16:42 am by SurferTim » Logged

Leeds, UK
Offline Offline
Edison Member
*
Karma: 71
Posts: 1641
Once the magic blue smoke is released, it won't go back in!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Modified my example from before based on the datasheet:
Code:
#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.
}
« Last Edit: November 22, 2012, 05:02:39 am by Tom Carpenter » Logged

~Tom~

Offline Offline
Newbie
*
Karma: 0
Posts: 12
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I changed to this...but still not working...

Code:
#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.
}

« Last Edit: November 21, 2012, 11:05:07 pm by Nick Gammon » Logged

Pages: [1] 2 3   Go Up
Jump to: