SPI: Reading 24 bit TDC7200 registers

I am currently a student with enough understanding of Arduino code / hardware to get by but by no means an expert as my code later may imply (Just to give a heads up before I delve into my issue).

I am communicating to the TDC7200 Time to digital converter with an ARDUINO nano 33 BLE Rev2. To start my communication, as shown in the code below, Enable is set high to initialise, and during SPI communication, the START_MEAS bit, PARITY_EN, and MEAS_MODE are accessed. These send the TRIGG signal, enable a parity bit on results, and set measurement mode 2 respectively as defined in the data sheet for the device.

SPI communication with the TDC7200 operates based on 1 byte transfers with the first bit the auto increment, second bit identifying read or write, and the other 6 stating the register address. Following this "I want this register command" the TDC7200 can be read or written to in the next 8 bit BYTE containing register information. The first half of my code accessing the CONFIG 1 register works as intended, writing and then checking through a read command printing 100 0011. The first bit is chopped off as Arduino removes leadings 0's.

My issue is that when I try to read the 24 bit register, in this case "CALIBRATION1" I only receive 0'S for each of the 3 read bytes following my "I want this register" command. I have auto increment turned on so should be able to read the 3 bytes following my "I want this register" command but still no luck. I have scoured the forum and google but haven't found an answer chain to the above with any possible fix I could follow. My pin layout is the following:

With my code being:

#include <SPI.h>

// Defining Pins used on the Arduino board
const int TDC7200_CSB = 9;
const int TDC7200_Enable = 10;
const int TDC7200_INTB = 8;
const int START = 2;
const int STOP = 3;


void setup() {
// Set Pins as inputs / outputs
pinMode(TDC7200_Enable, OUTPUT);     // TDC Enable PIN as output
pinMode(TDC7200_CSB, OUTPUT);        // Chip select pin as output
digitalWrite(TDC7200_Enable, LOW);   // Enable Pin is set low to allow TDC7200 to RESET when pulled HIGH later

//Test start/stop pulses
pinMode(TDC7200_INTB, INPUT);
pinMode(START, OUTPUT);         // START PIN as output
pinMode(STOP, OUTPUT);          // STOP PIN as output

// initialise SPI
SPI.begin();                       // Initialises the SPI bus by setting SCK, MOSI, and SS to outputs, pulls SCK, MOSI low and SS high
digitalWrite(TDC7200_CSB, HIGH);   // Unsure if SS registers that it is this pin so set High just incase
}

void loop() {

digitalWrite(TDC7200_Enable, HIGH);           // Enable Pin is set high to initialize TDC7200
delay(1.5);                                   // Recommended 1.5ms settling time for LDO before measurement

//write to CONFIG1 register
SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE0)); // Beginning new SPI transaction (speedMaximum (appropriate speed, dataOrder, dataMode)
digitalWrite(TDC7200_CSB, LOW);     // Setting slave select low for TDC7200 selection
SPI.transfer(0x40);                 // Writing to CONFIG1 register (00h) - (0100 0000 in Binary) 
SPI.transfer(0x43);                 // Setting PARITY_EN to 1, MEAS_MODE 01, and START_MEAS 1 (0100 0011)
SPI.endTransaction();               // Ends SPI transaction
digitalWrite(TDC7200_CSB, HIGH);    // Setting slave select High for TDC7200 un-selection

// Test if the registers been changed
uint8_t CONFIG1;                    // Creating unsigned 8 bit integer all 0
delay(1);                           // Short delay before reading back the value
SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE0));         // beginning new SPI transaction
digitalWrite(TDC7200_CSB, LOW);     // Setting slave select low for TDC7200 selection              
SPI.transfer(0x00);                 // Reading from CONFIG1 register (00h) - (0000 0000 in Binary)
CONFIG1 = SPI.transfer(0x00);       // Setting 8 bit unsigned integer to register value
SPI.endTransaction();               // Ends SPI transaction
digitalWrite(TDC7200_CSB, HIGH);    // setting slave select high to deselect TDC7200
Serial.println("CONFIG1 is");       // Prints "CONFIG1 is"
Serial.println(CONFIG1, BIN);       // Prints CONFIG1 value

// MCU produced start and stop pulse
digitalWrite(START, HIGH);
delay(1);
digitalWrite(START, LOW);
delay(1);
digitalWrite(STOP, HIGH);
delay(1);
digitalWrite(STOP, LOW);


  while (true) {                        // starts while loop
    int laststate = HIGH;               // identifies variable laststate and sets high
    int currentstate = digitalRead(TDC7200_INTB);    // identifies current state of INTB pin, active low when new result in
    if (laststate == HIGH && currentstate == LOW) {  // identifies if INTB pin has fallen low indicating new results to be read
      Serial.println("INTB pin signal recieved");    // If INTB low, prints "INTB pin signal recieved"
      uint8_t CALIBRATION1;        // creates unsigned 8 bit first result (actual length is 24 including parity bit but extra is undefined - arduino runs 8,16,32,64)
      uint8_t CALIBRATION2;        // creates unsigned 8 bit second result 
      uint8_t CALIBRATION3;        // creates unsigned 8 bit third result 
      delay(20);
      SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE0));  // (speedMaximum, dataOrder, dataMode)
      digitalWrite(TDC7200_CSB, LOW);      // Setting slave select low for TDC7200 selection 
      SPI.transfer(0x5B);                  // Address of Calibration1 register 1Bh == 0x1B == 011011 so 1011 0110 with first 2 bits auto inc on and read
      CALIBRATION1 = SPI.transfer(0x00);   // reads first byte
      CALIBRATION2 = SPI.transfer(0x00);   // reads second byte
      CALIBRATION3 = SPI.transfer(0x00);   // reads third byte
      digitalWrite(TDC7200_CSB, HIGH);     // Setting slave select high for TDC7200 unselection 
      SPI.endTransaction();                // End the SPI transaction

      Serial.println("CALIBRATION1 is");   // Prints "CALIBRATION1 is"
      Serial.println(CALIBRATION1, BIN);        // Prints CALIBRATION1 value

      Serial.println("CALIBRATION2 is");   // Prints "CALIBRATION1 is"
      Serial.println(CALIBRATION2, BIN);        // Prints CALIBRATION2 value

      Serial.println("CALIBRATION3 is");   // Prints "CALIBRATION3 is"
      Serial.println(CALIBRATION3, BIN);        // Prints CALIBRATION3 value
      break;                               // breaks while loop when finished
    }
 }
digitalWrite(TDC7200_Enable, LOW);  // Enable Pin is set LOW to de-initialize TDC7200
delay(1000);                        // delays until next reading for easy identification on oscilloscope
}

I have tested each pin on an oscilloscope and behaviour seems to be correct with the TRIGG signal sent, start and stop pulses received, INTB pin goes low signifying data is ready etc but I still receive zeros. Would appreciate if anyone can see anything I have missed or am doing incorrectly which could be causing my issue. If oscilloscope readings are wanted I can provide these but be warned my oscilloscope only has 2 inputs.

Thanks again

Or is it 0xBB ? The safest way could be:

SPI.transfer(0b10110110);    // First 2 bits auto inc on and read (=0) with address of Calibration1 register 1Bh == 0x1B == 011011 so 1011 0110

or even

const uint8_t TDC7200_CMD_NoInc   = 0b00000000;
const uint8_t TDC7200_CMD_AutoInc = 0b10000000;
const uint8_t TDC7200_CMD_Read    = 0b00000000;
const uint8_t TDC7200_CMD_Write   = 0b01000000;
const uint8_t TDC7200_ADDR_CALIBRATION1 = 0x1B;
...
SPI.transfer(TDC7200_CMD_AutoInc | TDC7200_CMD_Read | TDC7200_ADDR_CALIBRATION1);  // Self explanatory

I didn't check any further...

EDIT: @MaximoEsfuerzo is right: 0x9B or TDC7200_CMD_AutoInc | TDC7200_CMD_Read | TDC7200_ADDR_CALIBRATION1

1 Like
      SPI.transfer(0x5B);                  // Address of Calibration1 register 1Bh == 0x1B == 011011 so 1011 0110 with first 2 bits auto inc on and read
      CALIBRATION1 = SPI.transfer(0x00);   // reads first byte
      CALIBRATION2 = SPI.transfer(0x00);   // reads second byte
      CALIBRATION3 = SPI.transfer(0x00);   // reads third byte

The command to read register 0x1B with auto-increment is 0x9B (b10011011), not 0x5B (b01011011).
0x5B performs a write operation without auto-increment.

1 Like

Thank you for picking up on the register information, earliest I'm back in my labs is this Monday so I can have a check then to see if my issue is resolved.
I will update this comment should it be fixed :slight_smile:
Thanks again for taking the time to read what I have and offer your insight, its been much appreciated :+1:

EDIT: solution worked

Thanks for taking your time to read my code and help with my issue, I will check this solution this coming Monday. I would have tagged you both in the reply however I don't know how.

Thanks again :grinning_face:

EDIT: Solution worked

1 Like

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.