SPI communication issues

BACKGROUND:

I’m looking here to see if any of you could help me out the the SPI issues i’m having on a current project of mine. Right now, all i’m trying to do is to be able to successfully write to registers on an external device (TDC GP21) and then read a result register to see if it was written correctly.

The architecture and instruction set of the GP21 does not allow a user to actually read back the values in registers (this part is used by companies that have trade secrets, etc…). So to see if you have written the correct code for your write function, the GP21 allows you to read result register 5, which contains the upper byte (MSB) of data held in configuration register 1.

In my code, I am trying to write to config register 1 and read from result 5 to see if the MSByte matches.

ISSUE()
My issue is with using the SPI.transfer() function. I assumed it was not possible to use the SPI.transfer() to send a variable of type “long”, that SPI.transfer() should only send the first byte of information from the “long”. However when i send my variable, which is a 32 bit variable, using the SPI.transfer() function to register 1, I see only the LSByte of information stored in my result register 5. This means that somehow my LSByte of information is being stored in the MSByte of register 1. Does anyone have any suggestions on what to do differently? Can someone educate me on how the SPI function works with variables of more than 1 byte?

#include <SPI.h>
#include <LiquidCrystal.h>

//declare pins besides SPI (10-13)//
const int chipSelectPin = 9;
const int tofTrigger = 8;

//declare variables
const long confreg0 = 0x22CC2011;
const long confreg6 = 0x00101001;
  

//initialize library of LCD with correct pins//
LiquidCrystal lcd(A0, A1, A2, A3, A4, A5);


void setup() 
{
  //Initialize the LCD
  lcd.begin(16, 2);

  //set the slaveSelectPin as an output//
  pinMode (chipSelectPin, OUTPUT);
  digitalWrite (chipSelectPin, HIGH);
  
  //set the trigger to low, wait for high
  digitalWrite (tofTrigger, LOW);
 
  // initialize SPI:
  SPI.begin();
  SPI.setBitOrder(MSBFIRST); //TDC only operates in MSB first mode
  SPI.setClockDivider(SPI_CLOCK_DIV2); 
  SPI.setDataMode(SPI_MODE1);  //TDC only operates in mode 1
  configure();
  
}

void loop()
{
  
}


void configure()
{
  TDCwrite(0x01, 0x55408001, 4);
  long readreg = TDCread(0x05, 1);
  lcd.print(readreg, HEX);  
}

void TDCwrite(byte reg, long contents, int numbytes)
{
  reg = reg | 0x80;
  digitalWrite(chipSelectPin, LOW);
  SPI.transfer(reg);
  SPI.transfer(contents);
  digitalWrite(chipSelectPin, HIGH);
}

long TDCread(byte reg, int numbytes) //read function for the TDC
{
  long inbyte;
  long regcontent;
  reg = reg | 0xB0;  //opcode or'd with register to instruct TDC to read the correct reg
  digitalWrite(chipSelectPin, LOW);
  SPI.transfer(reg);  //reg to read
  regcontent = SPI.transfer(0x00); //get first byte of data
  numbytes--;
  for (int x = numbytes; x > 0; x--)
  {
    regcontent = regcontent << 8; //shift to allow for multiple bytes
    inbyte = SPI.transfer(0x00); 
    regcontent = regcontent | inbyte;
    numbytes--;
  }
  digitalWrite(chipSelectPin, HIGH);
  return(regcontent);
}

void TOeeprom ()
{
  digitalWrite(chipSelectPin, LOW);
  SPI.transfer(0xC0);
  delay(200);
  digitalWrite(chipSelectPin, HIGH);  
}

void FROMeeprom ()
{
  digitalWrite(chipSelectPin, LOW);
  SPI.transfer(0xF0);
  delay(200);
  digitalWrite(chipSelectPin, HIGH);  
}

SPI is a very basic (but fast!) single byte at a time hardware interface. On top of this hardware interface it’s up to your sketch code to define and develop the protocol needed to support the SPI device. Usually the datasheet of the SPI device covers the protocol it requires.

It’s similar to the Arduino serial library support of the processors USART hardware which is just single byte reads and writes at the hardware level. Everything above that (strings, etc) is just software defined independent of the byte at a time hardware transfers.

Lefty

That’s really my question, just using the SPI library supplied on the arduino website, i understood it as a byte by byte data transfer which is why my read function works perfectly. I was just curious as to the functionality of the following statement:

SPI.transfer(0x55408001);

why does the result register 5 contain 0x01?

If anything, the register should contain 0x55, as i have everything configured correctly using the SPI.setbitorder function.

The setbitorder function defines the order that the bits are in, not the order that the bytes in a multi-byte value are in. When the SPI.transfer function is passed the value 0x55408001, the value overflows the byte variable that the value is passed into, so only the 0x01 remains.

Thank you, that makes perfect sense to me know, I know what i need to do to fix it.