This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

ADS124S08: Receiving all zeros during read operation

Part Number: ADS124S08

I am trying to interface the ads124s08 with teensy 3.6 to read data from some batteries. The code is written to configure the ADC for using an unipolar external reference of  5V, Gain set to 1, 4000 SPS and using an external clock from microcontroller. I a using arduino IDE for the purpose.

I am attaching the image of the logic analyser output which is showing the output of ADC as all zero during SPI comunication /resized-image/__size/320x240/__key/communityserver-discussions-components-files/73/WhatsApp-Image-2022_2D00_01_2D00_18-at-12.12.06-AM.jpeg

I have also attached the code that I am using for the purpose

#include<SPI.h>

//#include <TimerOne.h>

int CS_PIN = 10;
int START_PIN = 5;
int RESET_PIN = 6;
int CKEN_PIN = 13;
int DRDY_PIN = 14;
int lastSample;

int mosi =  11;
int miso =  12;

SPISettings mySPISettings(4000000, MSBFIRST, SPI_MODE1);

#define NUM_REGISTERS 18

//rgeister map 
#define ID_ADDR_MASK        0x00
#define STATUS_ADDR_MASK    0x01
#define INPMUX_ADDR_MASK    0x02
#define PGA_ADDR_MASK       0x03
#define DATARATE_ADDR_MASK  0x04
#define REF_ADDR_MASK       0x05
#define IDACMAG_ADDR_MASK   0x06
#define IDACMUX_ADDR_MASK   0x07
#define VBIAS_ADDR_MASK     0x08
#define SYS_ADDR_MASK       0x09
#define OFCAL0_ADDR_MASK    0x0A
#define OFCAL1_ADDR_MASK    0x0B
#define OFCAL2_ADDR_MASK    0x0C
#define FSCAL0_ADDR_MASK    0x0D
#define FSCAL1_ADDR_MASK    0x0E
#define FSCAL2_ADDR_MASK    0x0F
#define GPIODAT_ADDR_MASK   0x10
#define GPIOCON_ADDR_MASK   0x11

/* Opcode masks (or "Commands" if you will...) */
#define NOP_OPCODE_MASK     0x00
#define WAKE_OPCODE_MASK    0x02
#define SLEEP_OPCODE_MASK   0x04
#define RESET_OPCODE_MASK   0x06
#define START_OPCODE_MASK   0x08
#define STOP_OPCODE_MASK    0x0A
#define SFOCAL_OPCODE_MASK  0x19
#define SYOCAL_OPCODE_MASK  0x16
#define SYGCAL_OPCODE_MASK  0x17
#define RDATA_OPCODE_MASK   0x12
#define REGRD_OPCODE_MASK   0x20
#define REGWR_OPCODE_MASK   0x40

/* Define the ADC positive input channels (MUXP) */
#define ADS_P_AIN0        0x00
#define ADS_P_AIN1        0x10
#define ADS_P_AIN2        0x20
#define ADS_P_AIN3        0x30
#define ADS_P_AIN4        0x40
#define ADS_P_AIN5        0x50
#define ADS_P_AIN6        0x60
#define ADS_P_AIN7        0x70
#define ADS_P_AIN8        0x80
#define ADS_P_AIN9        0x90
#define ADS_P_AIN10       0xA0
#define ADS_P_AIN11       0xB0
#define ADS_P_AINCOM      0xC0

/* Define the ADC negative input channels (MUXN)*/
#define ADS_N_AIN0        0x00
#define ADS_N_AIN1        0x01
#define ADS_N_AIN2        0x02
#define ADS_N_AIN3        0x03
#define ADS_N_AIN4        0x04
#define ADS_N_AIN5        0x05
#define ADS_N_AIN6        0x06
#define ADS_N_AIN7        0x07
#define ADS_N_AIN8        0x08
#define ADS_N_AIN9        0x09
#define ADS_N_AIN10       0x0A
#define ADS_N_AIN11       0x0B
#define ADS_N_AINCOM      0x0C

/* Define PGA control */
#define ADS_PGA_BYPASS    0x00
#define ADS_PGA_ENABLED   0x08
/* Define Gain */
#define ADS_GAIN_1        0x00
#define ADS_GAIN_2        0x01
#define ADS_GAIN_4        0x02
#define ADS_GAIN_8        0x03
#define ADS_GAIN_16       0x04
#define ADS_GAIN_32       0x05
#define ADS_GAIN_64       0x06
#define ADS_GAIN_128      0x07

/System Control register/
#define ADS_SENDSTATUS_DISABLE  0x00
#define ADS_SENDSTATUS_ENABLE   0x01

/Reference Control register/
#define ADS_FLAG_REF_DISABLE  0x00
#define ADS_FLAG_REF_EN_L0    0x40
#define ADS_FLAG_REF_EN_BOTH  0x80
#define ADS_FLAG_REF_EN_10M   0xC0
#define ADS_REFP_BYP_DISABLE  0x20
#define ADS_REFP_BYP_ENABLE   0x00
#define ADS_REFN_BYP_DISABLE  0x10
#define ADS_REFN_BYP_ENABLE   0x00
#define ADS_REFSEL_P0         0x00
#define ADS_REFSEL_P1         0x04
#define ADS_REFSEL_INT        0x08
#define ADS_REFINT_OFF        0x00
#define ADS_REFINT_ON_PDWN    0x01
#define ADS_REFINT_ON_ALWAYS  0x02

/* Flag to signal that we are in the process of collecting data */
#define DATA_MODE_NORMAL  0x00
#define DATA_MODE_STATUS  0x01
#define DATA_MODE_CRC     0x02

class ADS124S08
{
  // Device command prototypes
  public:
    ADS124S08(void);
    void begin();
    char regRead(unsigned int regnum);
    void readRegs(unsigned int regnum, unsigned int count, uint8_t *data);
    void regWrite(unsigned int regnum, unsigned char data);
    void writeRegs(unsigned int regnum, unsigned int howmuch, unsigned char *data);
    void reStart(void);
    void sendCommand(uint8_t op_code);
    int  rData(uint8_t *dStatus, uint8_t *dData, uint8_t *dCRC);
    int  dataRead(uint8_t *dStatus, uint8_t *dData, uint8_t *dCRC);
    void selectDeviceCSLow(void);
    void releaseChipSelect(void);
    void assertStart(void);
    void deassertStart(void);
    void assertClock(void);
    void deassertClock(void);
    bool converting;
    uint8_t registers[NUM_REGISTERS];
  private:
    bool fStart;
    void DRDY_int(void);
    uint8_t _drdy_pin;
    uint8_t _start_pin;
    uint8_t _reset_pin;
}adc;

ADS124S08::ADS124S08(void) // pin config and reg map 
{
  pinMode( CS_PIN, OUTPUT );
  pinMode( START_PIN, OUTPUT );
  pinMode( RESET_PIN, OUTPUT );
  pinMode( CKEN_PIN, OUTPUT );
  pinMode( DRDY_PIN, INPUT );
  pinMode( mosi, OUTPUT );
  pinMode( miso, INPUT );

  digitalWrite( START_PIN, LOW );
  digitalWrite( RESET_PIN, HIGH );
  digitalWrite( CKEN_PIN, LOW );

  /* Default register settings */
  registers[ID_ADDR_MASK]       = 0x08;
  registers[STATUS_ADDR_MASK]   = 0x80;
  registers[INPMUX_ADDR_MASK]   = 0x01;
  registers[PGA_ADDR_MASK]      = 0x00;
  registers[DATARATE_ADDR_MASK] = 0x14;
  registers[REF_ADDR_MASK]      = 0x10;
  registers[IDACMAG_ADDR_MASK]  = 0x00;
  registers[IDACMUX_ADDR_MASK]  = 0xFF;
  registers[VBIAS_ADDR_MASK]    = 0x00;
  registers[SYS_ADDR_MASK]      = 0x10;
  registers[OFCAL0_ADDR_MASK]   = 0x00;
  registers[OFCAL1_ADDR_MASK]   = 0x00;
  registers[OFCAL2_ADDR_MASK]   = 0x00;
  registers[FSCAL0_ADDR_MASK]   = 0x00;
  registers[FSCAL1_ADDR_MASK]   = 0x00;
  registers[FSCAL2_ADDR_MASK]   = 0x40;
  registers[GPIODAT_ADDR_MASK]  = 0x00;
  registers[GPIOCON_ADDR_MASK]  = 0x00;
  fStart = false;
  releaseChipSelect();
  deassertStart();
}

void ADS124S08::begin() //start transaction 
{
  SPI.begin( );
  SPI.setBitOrder(MSBFIRST);
  SPI.setDataMode( SPI_MODE1 );
  SPI.setClockDivider(21); //the system clock can be divided by values from 1 to 255. The default value is 21, which sets the clock to 4 MHz like other Arduino boards.
  #if defined (SPI_HAS_TRANSACTION)
    mySPISettings = SPISettings(4000000, MSBFIRST, SPI_MODE1);
  #endif
}

char ADS124S08::regRead(unsigned int regnum)
{
  int i;
  uint8_t ulDataTx[3];
  uint8_t ulDataRx[3];
  ulDataTx[0] = REGRD_OPCODE_MASK + (regnum & 0x1f);
  ulDataTx[1] = 0x00;
  ulDataTx[2] = 0x00;
  selectDeviceCSLow();

  #if defined (SPI_HAS_TRANSACTION)
    SPI.beginTransaction(mySPISettings);
  #endif

  for(i = 0; i < 3; i++)
    ulDataRx[i] = SPI.transfer(ulDataTx[i]);
  if(regnum < NUM_REGISTERS)
      registers[regnum] = ulDataRx[2];

  #if defined (SPI_HAS_TRANSACTION)
    SPI.endTransaction();
  #endif

  releaseChipSelect();
  //Serial.println("regRead tx: %02x %02x %02x",ulDataTx[0],ulDataTx[1],ulDataTx[2]);
  //Serial.println("regRead rx: %02x %02x %02x",ulDataRx[0],ulDataRx[1],ulDataRx[2]);
  return ulDataRx[2];
}

void ADS124S08::readRegs(unsigned int regnum, unsigned int count, uint8_t *data)
{
  int i;
  uint8_t ulDataTx[2];
  ulDataTx[0] = REGRD_OPCODE_MASK + (regnum & 0x1f);
  ulDataTx[1] = count-1;
  selectDeviceCSLow();
  SPI.transfer(ulDataTx[0]);
  SPI.transfer(ulDataTx[1]);
  for(i = 0; i < count; i++)
  {
    data[i] = SPI.transfer(0);
    if(regnum+i < NUM_REGISTERS)
      registers[regnum+i] = data[i];
  }
  releaseChipSelect();
}

void ADS124S08::regWrite(unsigned int regnum, unsigned char data)
{
  uint8_t ulDataTx[3];
  ulDataTx[0] = REGWR_OPCODE_MASK + (regnum & 0x1f);
  ulDataTx[1] = 0x00;
  ulDataTx[2] = data;
  selectDeviceCSLow();
  SPI.transfer(ulDataTx[0]);
  SPI.transfer(ulDataTx[1]);
  SPI.transfer(ulDataTx[2]);
  releaseChipSelect();
  //Serial.println("regWrite tx: %02x %02x %02x",ulDataTx[0],ulDataTx[1],ulDataTx[2]);
  return;
}

void ADS124S08::writeRegs(unsigned int regnum, unsigned int howmuch, unsigned char *data)
{
  unsigned int i;
  uint8_t ulDataTx[2];
  ulDataTx[0] = REGWR_OPCODE_MASK + (regnum & 0x1f);
  ulDataTx[1] = howmuch-1;
  selectDeviceCSLow();
  SPI.transfer(ulDataTx[0]);
  SPI.transfer(ulDataTx[1]);
  for(i=0; i < howmuch; i++)
  {
    SPI.transfer( data[i] );
    if(regnum+i < NUM_REGISTERS)
      registers[regnum+i] = data[i];
  }
  releaseChipSelect();
  return;
}

void ADS124S08::reStart(void)
{
  sendCommand(STOP_OPCODE_MASK);
  sendCommand(START_OPCODE_MASK);
  return;
}

void ADS124S08::sendCommand(uint8_t op_code)
{
  selectDeviceCSLow();
  SPI.transfer(op_code);
  releaseChipSelect();
  return;
}

int ADS124S08::rData(uint8_t *dStatus, uint8_t *dData, uint8_t *dCRC)
{
  int result = -1;
  selectDeviceCSLow();

  // according to datasheet chapter 9.5.4.2 Read Data by RDATA Command
  sendCommand(RDATA_OPCODE_MASK);

  // if the Status byte is set - grab it
  uint8_t shouldWeReceiveTheStatusByte = (registers[SYS_ADDR_MASK] & 0x01) == DATA_MODE_STATUS;
  if( shouldWeReceiveTheStatusByte )
  {
    dStatus[0] = SPI.transfer(0x00);
    //Serial.print("status: ");
    //Serial.print(dStatus[0]);
  }

  // get the conversion data (3 bytes)
  uint8_t data[3];
  data[0] = SPI.transfer(0x00);
  data[1] = SPI.transfer(0x00);
  data[2] = SPI.transfer(0x00);
  result = data[0];
  result = (result<<8) + data[1];
  result = (result<<8) + data[2];
  //Serial.println(" 1: %02x 2: %02x, 3: %02x = %d", data[0], data[1], data[2], result);

  // is CRC enabled?
  uint8_t isCrcEnabled = (registers[SYS_ADDR_MASK] & 0x02) == DATA_MODE_CRC;
  if( isCrcEnabled )
  {
    dCRC[0] = SPI.transfer(0x00);
  }

  releaseChipSelect();
  return result;
}

int ADS124S08::dataRead(uint8_t *dStatus, uint8_t *dData, uint8_t *dCRC)
{
  uint8_t xcrc;
  uint8_t xstatus;
  int iData;
  selectDeviceCSLow();
  if((registers[SYS_ADDR_MASK] & 0x01) == DATA_MODE_STATUS)
  {
    xstatus = SPI.transfer(0x00);
    Serial.print("0:");
    Serial.print(xstatus);
    dStatus[0] = (uint8_t)xstatus;
  }

  // get the conversion data (3 bytes)
  uint8_t data[3];
  data[0] = SPI.transfer(0x00);
  data[1] = SPI.transfer(0x00);
  data[2] = SPI.transfer(0x00);

  
  Serial.print(" 1:");
  Serial.print(data[0]);
  Serial.print(" 2:");
  Serial.print(data[1]);
  Serial.print(" 3:");
  Serial.println(data[2]);
  

  iData = data[0];
  iData = (iData<<8) + data[1];
  iData = (iData<<8) + data[2];
  if((registers[SYS_ADDR_MASK] & 0x02) == DATA_MODE_CRC)
  {
    xcrc = SPI.transfer(0x00);
    dCRC[0] = (uint8_t)xcrc;
  }
  releaseChipSelect();
  return iData ;
}

void ADS124S08::selectDeviceCSLow(void){
  digitalWrite( CS_PIN, LOW );
}

void ADS124S08::releaseChipSelect(void){
  digitalWrite( CS_PIN, HIGH );
}

void ADS124S08::assertStart()
{
  fStart = true;
  digitalWrite(START_PIN ,HIGH);
}

void ADS124S08::deassertStart()
{
  fStart = false;
  digitalWrite(START_PIN, LOW);
}

void ADS124S08::assertClock()
{
  digitalWrite(CKEN_PIN, 1);
}

void ADS124S08::deassertClock()
{
  digitalWrite(CKEN_PIN, LOW);
}

void setup()
{
  Serial.begin(9600);

  delay(100);
  adc.begin();
  delay(100);
  adc.sendCommand(RESET_OPCODE_MASK);
  delay(100);

  regMap();

  configureAdc();

  Serial.println("After config");
  regMap();
  
}

void loop()
{
  long now = millis();
  //uint8_t status;
  // Check if it's X seconds since last conversion
  if( now - lastSample > 25 ){                     //delay between two conversions taken as 25ms 
    //Serial.print(sampleNumber);
    //Serial.print(" ");
    lastSample = now;
    readData();
  }
}

void configureAdc()
{
  // Make sure the device is awake
  adc.sendCommand( WAKE_OPCODE_MASK );
  // use channel 1 as positive and channel 2 as negative input
  adc.regWrite( INPMUX_ADDR_MASK, ADS_P_AIN0 + ADS_N_AIN1 ); // mux selection reg: AIN0 - +ve and AIN1 - -ve (default)
  // set PGA to 1x
  adc.regWrite( PGA_ADDR_MASK, ADS_PGA_BYPASS  + ADS_GAIN_1 ); //Gain setting reg: PGA bypassed(default), gain set to 1
  // The IDAC will only work if we enable the internal reference (ref Datasheet 9.3.7)
  //adc.regWrite( REF_ADDR_MASK, ADS_REFINT_ON_ALWAYS + ADS_REFSEL_P0 );
  // use channel 3 as IDAC 1 (excitation current source)
  //adc.regWrite( IDACMUX_ADDR_MASK, ADS_IDAC1_A2 + ADS_IDAC2_OFF );  //We are not using internal reference 
  // set IDAC 1 to output 500uA
  //adc.regWrite( IDACMAG_ADDR_MASK, ADS_IDACMAG_500 );
  // Turn on status for debugging
  adc.regWrite( SYS_ADDR_MASK, ADS_SENDSTATUS_ENABLE ); //Status bit while reading data: pg no. 70 in datasheet 
  //Configuring external register
  adc.regWrite( REF_ADDR_MASK, ADS_FLAG_REF_DISABLE +  ADS_REFP_BYP_ENABLE + ADS_REFN_BYP_DISABLE + ADS_REFSEL_P0); //REFP0 and REFN0 as external reference 
  //Configuring the data rate register
  adc.regWrite( DATARATE_ADDR_MASK, ADS_CLKSEL_EXT +  ADS_FILTERTYPE_LL + ADS_DR_4000);
  adc.reStart();
  delay(10);
  //regMap2();
}

void readData()
{
  uint8_t dStatus = 0;
  uint8_t dData;
  uint8_t dCRC = 0;
  int data = 0;

  /* Read out the results  */
  data = adc.dataRead(&dStatus, &dData, &dCRC); //call to dataRead() - the 24 bit data stored in iData will be stored in data 
  /*
   * Need to determine if Status and/or CRC is enabled to transmit as desired
   */
  /*if((adc.registers[SYS_ADDR_MASK] & 0x01) == DATA_MODE_STATUS)  //Not yet completely understood these nested if loops 
  {
    if((adc.registers[SYS_ADDR_MASK] & 0x02) == DATA_MODE_CRC)
    {
      Serial.println("Conversion Data 0x%06x with Status 0x%02x and CRC 0x%02x.", data, dStatus, dCRC);
    }
    else
    {
      //sSerial.println("Conversion Data 0x%06x with Status 0x%02x. DEC %02d", data, dStatus,data);
    }
  }
  else if((adc.registers[SYS_ADDR_MASK] & 0x02) == DATA_MODE_CRC)
  {
    Serial.println("Conversion Data 0x%06x with CRC 0x%02x.", data, dCRC);
  }
  else*/
  //{
    Serial.println(data,DEC);  //This is where the raw conversion result should be available 
  //}

  
  /* Set ADC back to the previous configuration */
  //adc.sendCommand(STOP_OPCODE_MASK);
  //adc.sendCommand(SLEEP_OPCODE_MASK);

  //return dStatus;
}

void regMap(void)
{
  unsigned int index;
  char cTemp;
  Serial.println("Register Contents");
  Serial.println("---------------------");
  for(index=0; index < 18 ; index++)
  {
    cTemp = adc.regRead(index);
    Serial.println(index, cTemp);
  }
}

  • Hi A. Avinash Prabhu,

    Welcome to the E2E forum!  It is difficult to read the image you sent, but it appears to be a shot from a Saleae.  If you can save the data to a file and attach the file it would be easier for me to troubleshoot.

    A couple of considerations.  The first is what are you expecting back as data?  You are essentially sending NOPs repeatedly.  Instead I would recommend sending the RREG command and read back the default values from the register to verify the communication is working.  The next step would be to write the desired register configuration and then read back the configuration to verify it was written correctly.

    Also, make sure that you are not violating any timing.  For example, make sure CS low to first SCLK edge is within the required timing and also last SCLK edge to CS going high timing.  This information is shown in Figure 1 on page 15 of the ADS124S08 datasheet.

    As far as your code, I would recommend that you set the RESET pin low, then set the CLK pin low before bringing the RESET pin back high.  Depending on the internal state of the CLK pin, the setting of the pin low after reset may actually disable the internal clock.  So all pin states other than the RESET pin should be at the desired initial state prior to the RESET pin going high.

    Best regards,

    Bob B

  • #include<SPI.h>
    
    //#include <TimerOne.h>
    
    int CS_PIN = 10;
    int START_PIN = 5;
    int RESET_PIN = 6;
    int CKEN_PIN = 13;
    int DRDY_PIN = 14;
    int lastSample;
    
    int mosi =  11;
    int miso =  12;
    
    SPISettings mySPISettings(4000000, MSBFIRST, SPI_MODE1);
    
    #define NUM_REGISTERS 18
    
    //rgeister map 
    #define ID_ADDR_MASK        0x00
    #define STATUS_ADDR_MASK    0x01
    #define INPMUX_ADDR_MASK    0x02
    #define PGA_ADDR_MASK       0x03
    #define DATARATE_ADDR_MASK  0x04
    #define REF_ADDR_MASK       0x05
    #define IDACMAG_ADDR_MASK   0x06
    #define IDACMUX_ADDR_MASK   0x07
    #define VBIAS_ADDR_MASK     0x08
    #define SYS_ADDR_MASK       0x09
    #define OFCAL0_ADDR_MASK    0x0A
    #define OFCAL1_ADDR_MASK    0x0B
    #define OFCAL2_ADDR_MASK    0x0C
    #define FSCAL0_ADDR_MASK    0x0D
    #define FSCAL1_ADDR_MASK    0x0E
    #define FSCAL2_ADDR_MASK    0x0F
    #define GPIODAT_ADDR_MASK   0x10
    #define GPIOCON_ADDR_MASK   0x11
    
    /* Opcode masks (or "Commands" if you will...) */
    #define NOP_OPCODE_MASK     0x00
    #define WAKE_OPCODE_MASK    0x02
    #define SLEEP_OPCODE_MASK   0x04
    #define RESET_OPCODE_MASK   0x06
    #define START_OPCODE_MASK   0x08
    #define STOP_OPCODE_MASK    0x0A
    #define SFOCAL_OPCODE_MASK  0x19
    #define SYOCAL_OPCODE_MASK  0x16
    #define SYGCAL_OPCODE_MASK  0x17
    #define RDATA_OPCODE_MASK   0x12
    #define REGRD_OPCODE_MASK   0x20
    #define REGWR_OPCODE_MASK   0x40
    
    /* Define the ADC positive input channels (MUXP) */
    #define ADS_P_AIN0        0x00
    #define ADS_P_AIN1        0x10
    #define ADS_P_AIN2        0x20
    #define ADS_P_AIN3        0x30
    #define ADS_P_AIN4        0x40
    #define ADS_P_AIN5        0x50
    #define ADS_P_AIN6        0x60
    #define ADS_P_AIN7        0x70
    #define ADS_P_AIN8        0x80
    #define ADS_P_AIN9        0x90
    #define ADS_P_AIN10       0xA0
    #define ADS_P_AIN11       0xB0
    #define ADS_P_AINCOM      0xC0
    
    /* Define the ADC negative input channels (MUXN)*/
    #define ADS_N_AIN0        0x00
    #define ADS_N_AIN1        0x01
    #define ADS_N_AIN2        0x02
    #define ADS_N_AIN3        0x03
    #define ADS_N_AIN4        0x04
    #define ADS_N_AIN5        0x05
    #define ADS_N_AIN6        0x06
    #define ADS_N_AIN7        0x07
    #define ADS_N_AIN8        0x08
    #define ADS_N_AIN9        0x09
    #define ADS_N_AIN10       0x0A
    #define ADS_N_AIN11       0x0B
    #define ADS_N_AINCOM      0x0C
    
    /* Define PGA control */
    #define ADS_PGA_BYPASS    0x00
    #define ADS_PGA_ENABLED   0x08
    /* Define Gain */
    #define ADS_GAIN_1        0x00
    #define ADS_GAIN_2        0x01
    #define ADS_GAIN_4        0x02
    #define ADS_GAIN_8        0x03
    #define ADS_GAIN_16       0x04
    #define ADS_GAIN_32       0x05
    #define ADS_GAIN_64       0x06
    #define ADS_GAIN_128      0x07
    
    /*System Control register*/
    #define ADS_SENDSTATUS_DISABLE  0x00
    #define ADS_SENDSTATUS_ENABLE   0x01
    
    /*Reference Control register*/
    #define ADS_FLAG_REF_DISABLE  0x00
    #define ADS_FLAG_REF_EN_L0    0x40
    #define ADS_FLAG_REF_EN_BOTH  0x80
    #define ADS_FLAG_REF_EN_10M   0xC0
    #define ADS_REFP_BYP_DISABLE  0x20
    #define ADS_REFP_BYP_ENABLE   0x00
    #define ADS_REFN_BYP_DISABLE  0x10
    #define ADS_REFN_BYP_ENABLE   0x00
    #define ADS_REFSEL_P0         0x00
    #define ADS_REFSEL_P1         0x04
    #define ADS_REFSEL_INT        0x08
    #define ADS_REFINT_OFF        0x00
    #define ADS_REFINT_ON_PDWN    0x01
    #define ADS_REFINT_ON_ALWAYS  0x02
    
    /* Flag to signal that we are in the process of collecting data */
    #define DATA_MODE_NORMAL  0x00
    #define DATA_MODE_STATUS  0x01
    #define DATA_MODE_CRC     0x02
    
    /*DataRate Register*/
    #define ADS_GLOBALCHOP      0x80
    #define ADS_CLKSEL_EXT      0x40
    #define ADS_CONVMODE_SS     0x20
    #define ADS_FILTERTYPE_LL   0x10
    
    /* Define the data rate */
    #define ADS_DR_2_5      0x00
    #define ADS_DR_5        0x01
    #define ADS_DR_10       0x02
    #define ADS_DR_16       0x03
    #define ADS_DR_20       0x04
    #define ADS_DR_50       0x05
    #define ADS_DR_60       0x06
    #define ADS_DR_100      0x07
    #define ADS_DR_200      0x08
    #define ADS_DR_400      0x09
    #define ADS_DR_800      0x0A
    #define ADS_DR_1000     0x0B
    #define ADS_DR_2000     0x0C
    #define ADS_DR_4000     0x0D
    
    class ADS124S08
    {
      // Device command prototypes
      public:
        ADS124S08(void);
        void begin();
        char regRead(unsigned int regnum);
        void readRegs(unsigned int regnum, unsigned int count, uint8_t *data);
        void regWrite(unsigned int regnum, unsigned char data);
        void writeRegs(unsigned int regnum, unsigned int howmuch, unsigned char *data);
        void reStart(void);
        void sendCommand(uint8_t op_code);
        int  rData(uint8_t *dStatus, uint8_t *dData, uint8_t *dCRC);
        int  dataRead(uint8_t *dStatus, uint8_t *dData, uint8_t *dCRC);
        void selectDeviceCSLow(void);
        void releaseChipSelect(void);
        void assertStart(void);
        void deassertStart(void);
        void assertClock(void);
        void deassertClock(void);
        bool converting;
        uint8_t registers[NUM_REGISTERS];
      private:
        bool fStart;
        void DRDY_int(void);
        uint8_t _drdy_pin;
        uint8_t _start_pin;
        uint8_t _reset_pin;
    }adc;
    
    ADS124S08::ADS124S08(void) // pin config and reg map 
    {
      pinMode( CS_PIN, OUTPUT );
      pinMode( START_PIN, OUTPUT );
      pinMode( RESET_PIN, OUTPUT );
      pinMode( CKEN_PIN, OUTPUT );
      pinMode( DRDY_PIN, INPUT );
      pinMode( mosi, OUTPUT );
      pinMode( miso, INPUT );
    
      digitalWrite( RESET_PIN, LOW); 
      digitalWrite( START_PIN, LOW );
      digitalWrite( CKEN_PIN, LOW );
      digitalWrite( RESET_PIN, HIGH );
    
      /* Default register settings */
      registers[ID_ADDR_MASK]       = 0x08;
      registers[STATUS_ADDR_MASK]   = 0x80;
      registers[INPMUX_ADDR_MASK]   = 0x01;
      registers[PGA_ADDR_MASK]      = 0x00;
      registers[DATARATE_ADDR_MASK] = 0x14;
      registers[REF_ADDR_MASK]      = 0x10;
      registers[IDACMAG_ADDR_MASK]  = 0x00;
      registers[IDACMUX_ADDR_MASK]  = 0xFF;
      registers[VBIAS_ADDR_MASK]    = 0x00;
      registers[SYS_ADDR_MASK]      = 0x10;
      registers[OFCAL0_ADDR_MASK]   = 0x00;
      registers[OFCAL1_ADDR_MASK]   = 0x00;
      registers[OFCAL2_ADDR_MASK]   = 0x00;
      registers[FSCAL0_ADDR_MASK]   = 0x00;
      registers[FSCAL1_ADDR_MASK]   = 0x00;
      registers[FSCAL2_ADDR_MASK]   = 0x40;
      registers[GPIODAT_ADDR_MASK]  = 0x00;
      registers[GPIOCON_ADDR_MASK]  = 0x00;
      fStart = false;
      releaseChipSelect();
      deassertStart();
    }
    
    void ADS124S08::begin() //start transaction 
    {
      SPI.begin( );
      SPI.setBitOrder(MSBFIRST);
      SPI.setDataMode( SPI_MODE1 );
      SPI.setClockDivider(21); //the system clock can be divided by values from 1 to 255. The default value is 21, which sets the clock to 4 MHz like other Arduino boards.
      #if defined (SPI_HAS_TRANSACTION)
        mySPISettings = SPISettings(4000000, MSBFIRST, SPI_MODE1);
      #endif
    }
    
    char ADS124S08::regRead(unsigned int regnum)
    {
      int i;
      uint8_t ulDataTx[3];
      uint8_t ulDataRx[3];
      ulDataTx[0] = REGRD_OPCODE_MASK + (regnum & 0x1f);
      ulDataTx[1] = 0x00;
      ulDataTx[2] = 0x00;
      selectDeviceCSLow();
      delay(10);
    
      #if defined (SPI_HAS_TRANSACTION)
        SPI.beginTransaction(mySPISettings);
      #endif
    
      for(i = 0; i < 3; i++)
        ulDataRx[i] = SPI.transfer(ulDataTx[i]);
      if(regnum < NUM_REGISTERS)
          registers[regnum] = ulDataRx[2];
    
      #if defined (SPI_HAS_TRANSACTION)
         SPI.endTransaction();
      #endif
      delay(10);
      releaseChipSelect();
      //Serial.println("regRead tx: %02x %02x %02x",ulDataTx[0],ulDataTx[1],ulDataTx[2]);
      //Serial.println("regRead rx: %02x %02x %02x",ulDataRx[0],ulDataRx[1],ulDataRx[2]);
      return ulDataRx[2];
    }
    
    void ADS124S08::readRegs(unsigned int regnum, unsigned int count, uint8_t *data)
    {
      int i;
      uint8_t ulDataTx[2];
      ulDataTx[0] = REGRD_OPCODE_MASK + (regnum & 0x1f);
      ulDataTx[1] = count-1;
      selectDeviceCSLow();
      SPI.transfer(ulDataTx[0]);
      SPI.transfer(ulDataTx[1]);
      for(i = 0; i < count; i++)
      {
        data[i] = SPI.transfer(0);
        if(regnum+i < NUM_REGISTERS)
          registers[regnum+i] = data[i];
      }
      releaseChipSelect();
    }
    
    void ADS124S08::regWrite(unsigned int regnum, unsigned char data)
    {
      uint8_t ulDataTx[3];
      ulDataTx[0] = REGWR_OPCODE_MASK + (regnum & 0x1f);
      ulDataTx[1] = 0x00;
      ulDataTx[2] = data;
      selectDeviceCSLow();
      SPI.transfer(ulDataTx[0]);
      SPI.transfer(ulDataTx[1]);
      SPI.transfer(ulDataTx[2]);
      releaseChipSelect();
      //Serial.println("regWrite tx: %02x %02x %02x",ulDataTx[0],ulDataTx[1],ulDataTx[2]);
      return;
    }
    
    void ADS124S08::writeRegs(unsigned int regnum, unsigned int howmuch, unsigned char *data)
    {
      unsigned int i;
      uint8_t ulDataTx[2];
      ulDataTx[0] = REGWR_OPCODE_MASK + (regnum & 0x1f);
      ulDataTx[1] = howmuch-1;
      selectDeviceCSLow();
      SPI.transfer(ulDataTx[0]);
      SPI.transfer(ulDataTx[1]);
      for(i=0; i < howmuch; i++)
      {
        SPI.transfer( data[i] );
        if(regnum+i < NUM_REGISTERS)
          registers[regnum+i] = data[i];
      }
      releaseChipSelect();
      return;
    }
    
    void ADS124S08::reStart(void)
    {
      sendCommand(STOP_OPCODE_MASK);
      sendCommand(START_OPCODE_MASK);
      return;
    }
    
    void ADS124S08::sendCommand(uint8_t op_code)
    {
      selectDeviceCSLow();
      SPI.transfer(op_code);
      releaseChipSelect();
      return;
    }
    
    int ADS124S08::rData(uint8_t *dStatus, uint8_t *dData, uint8_t *dCRC)
    {
      int result = -1;
      selectDeviceCSLow();
    
      // according to datasheet chapter 9.5.4.2 Read Data by RDATA Command
      sendCommand(RDATA_OPCODE_MASK);
    
      // if the Status byte is set - grab it
      uint8_t shouldWeReceiveTheStatusByte = (registers[SYS_ADDR_MASK] & 0x01) == DATA_MODE_STATUS;
      if( shouldWeReceiveTheStatusByte )
      {
        dStatus[0] = SPI.transfer(0x00);
        //Serial.print("status: ");
        //Serial.print(dStatus[0]);
      }
    
      // get the conversion data (3 bytes)
      uint8_t data[3];
      data[0] = SPI.transfer(0x00);
      data[1] = SPI.transfer(0x00);
      data[2] = SPI.transfer(0x00);
      result = data[0];
      result = (result<<8) + data[1];
      result = (result<<8) + data[2];
      //Serial.println(" 1: %02x 2: %02x, 3: %02x = %d", data[0], data[1], data[2], result);
    
      // is CRC enabled?
      uint8_t isCrcEnabled = (registers[SYS_ADDR_MASK] & 0x02) == DATA_MODE_CRC;
      if( isCrcEnabled )
      {
        dCRC[0] = SPI.transfer(0x00);
      }
    
      releaseChipSelect();
      return result;
    }
    
    int ADS124S08::dataRead(uint8_t *dStatus, uint8_t *dData, uint8_t *dCRC)
    {
      uint8_t xcrc;
      uint8_t xstatus;
      int iData;
      selectDeviceCSLow();
      if((registers[SYS_ADDR_MASK] & 0x01) == DATA_MODE_STATUS)
      {
        xstatus = SPI.transfer(0x00);
        Serial.print("0:");
        Serial.print(xstatus);
        dStatus[0] = (uint8_t)xstatus;
      }
    
      // get the conversion data (3 bytes)
      uint8_t data[3];
      data[0] = SPI.transfer(0x00);
      data[1] = SPI.transfer(0x00);
      data[2] = SPI.transfer(0x00);
    
      
      Serial.print(" 1:");
      Serial.print(data[0]);
      Serial.print(" 2:");
      Serial.print(data[1]);
      Serial.print(" 3:");
      Serial.println(data[2]);
      
    
      iData = data[0];
      iData = (iData<<8) + data[1];
      iData = (iData<<8) + data[2];
      if((registers[SYS_ADDR_MASK] & 0x02) == DATA_MODE_CRC)
      {
        xcrc = SPI.transfer(0x00);
        dCRC[0] = (uint8_t)xcrc;
      }
      releaseChipSelect();
      return iData ;
    }
    
    void ADS124S08::selectDeviceCSLow(void){
      digitalWrite( CS_PIN, LOW );
    }
    
    void ADS124S08::releaseChipSelect(void){
      digitalWrite( CS_PIN, HIGH );
    }
    
    void ADS124S08::assertStart()
    {
      fStart = true;
      digitalWrite(START_PIN ,HIGH);
    }
    
    void ADS124S08::deassertStart()
    {
      fStart = false;
      digitalWrite(START_PIN, LOW);
    }
    
    void ADS124S08::assertClock()
    {
      digitalWrite(CKEN_PIN, 1);
    }
    
    void ADS124S08::deassertClock()
    {
      digitalWrite(CKEN_PIN, LOW);
    }
    
    void setup()
    {
      Serial.begin(9600);
    
      delay(100);
      adc.begin();
      delay(100);
      adc.sendCommand(RESET_OPCODE_MASK);
      delay(100);
      /*uint8_t STATUS_REG = adc.regRead(STATUS_ADDR_MASK); //Reading Status register before config using RREG command 
      Serial.println( STATUS_REG, HEX );
      delay(10);
      uint8_t INPMUX_REG = adc.regRead(INPMUX_ADDR_MASK); //Reading Input mux register before config using RREG command 
      Serial.println( INPMUX_REG, HEX );
      delay(10);
      uint8_t PGA_REG = adc.regRead(PGA_ADDR_MASK); //Reading Gain register before config using RREG command 
      Serial.println( PGA_REG, HEX );
      delay(10);
      uint8_t DATARATE_REG = adc.regRead(DATARATE_ADDR_MASK); //Reading datarate register before config using RREG command 
      Serial.println( DATARATE_REG, HEX );
      delay(10);
      uint8_t REF_REG = adc.regRead(REF_ADDR_MASK); //Reading reference control register before config using RREG command 
      Serial.println( REF_REG, HEX );
      delay(10);
       /*digitalWrite(RESET_PIN, LOW); 
       delay(100);
       digitalWrite(RESET_PIN, HIGH);*/
      regMap2();
    
      configureAdc();
    
      Serial.println("After config");
      delay(100);
      /*STATUS_REG = adc.regRead(STATUS_ADDR_MASK); //Reading Status register after config using RREG command 
      Serial.println( STATUS_REG, HEX );
      delay(10);
      INPMUX_REG = adc.regRead(INPMUX_ADDR_MASK); //Reading Input mux register after config using RREG command 
      Serial.println( INPMUX_REG, HEX );
      delay(10);
      PGA_REG = adc.regRead(PGA_ADDR_MASK); //Reading Gain register after config using RREG command 
      Serial.println( PGA_REG, HEX );
      delay(10);
      DATARATE_REG = adc.regRead(DATARATE_ADDR_MASK); //Reading datarate after before config using RREG command 
      Serial.println( DATARATE_REG, HEX );
      delay(10);
      REF_REG = adc.regRead(REF_ADDR_MASK); //Reading reference control register after config using RREG command 
      Serial.println( REF_REG, HEX );
      delay(10);*/
      
      regMap2();
      
    }
    
    void loop()
    {
      long now = millis();
      //uint8_t status;
      // Check if it's X seconds since last conversion
      if( now - lastSample > 25 ){                     //delay between two conversions taken as 25ms 
        //Serial.print(sampleNumber);
        //Serial.print(" ");
        lastSample = now;
        readData();
      }
    }
    
    void configureAdc()
    {
      // Make sure the device is awake
      //adc.sendCommand( WAKE_OPCODE_MASK );
      // use channel 1 as positive and channel 2 as negative input
      adc.regWrite( INPMUX_ADDR_MASK, ADS_P_AIN0 + ADS_N_AIN1 ); // mux selection reg: AIN0 - +ve and AIN1 - -ve (default)
      // set PGA to 1x
      adc.regWrite( PGA_ADDR_MASK, ADS_PGA_BYPASS  + ADS_GAIN_1 ); //Gain setting reg: PGA bypassed(default), gain set to 1
      // The IDAC will only work if we enable the internal reference (ref Datasheet 9.3.7)
      //adc.regWrite( REF_ADDR_MASK, ADS_REFINT_ON_ALWAYS + ADS_REFSEL_P0 );
      // use channel 3 as IDAC 1 (excitation current source)
      //adc.regWrite( IDACMUX_ADDR_MASK, ADS_IDAC1_A2 + ADS_IDAC2_OFF );  //We are not using internal reference 
      // set IDAC 1 to output 500uA
      //adc.regWrite( IDACMAG_ADDR_MASK, ADS_IDACMAG_500 );
      // Turn on status for debugging
      adc.regWrite( SYS_ADDR_MASK, ADS_SENDSTATUS_ENABLE ); //Status bit while reading data: pg no. 70 in datasheet 
      //Configuring external register
      adc.regWrite( REF_ADDR_MASK, ADS_FLAG_REF_DISABLE +  ADS_REFP_BYP_ENABLE + ADS_REFN_BYP_DISABLE + ADS_REFSEL_P0); //REFP0 and REFN0 as external reference// int ref for checking 
      //DataRate register 
      adc.regWrite( DATARATE_ADDR_MASK, ADS_CLKSEL_EXT +  ADS_FILTERTYPE_LL + ADS_DR_4000 );
      adc.reStart();
      delay(10);
      //regMap2();
    }
    
    void readData()
    {
      uint8_t dStatus = 0;
      uint8_t dData;
      uint8_t dCRC = 0;
      int data = 0;
    
      /* Read out the results  */
      data = adc.dataRead(&dStatus, &dData, &dCRC); //call to dataRead() - the 24 bit data stored in iData will be stored in data 
      /*
       * Need to determine if Status and/or CRC is enabled to transmit as desired
       */
      /*if((adc.registers[SYS_ADDR_MASK] & 0x01) == DATA_MODE_STATUS)  //Not yet completely understood these nested if loops 
      {
        if((adc.registers[SYS_ADDR_MASK] & 0x02) == DATA_MODE_CRC)
        {
          Serial.println("Conversion Data 0x%06x with Status 0x%02x and CRC 0x%02x.", data, dStatus, dCRC);
        }
        else
        {
          //sSerial.println("Conversion Data 0x%06x with Status 0x%02x. DEC %02d", data, dStatus,data);
        }
      }
      else if((adc.registers[SYS_ADDR_MASK] & 0x02) == DATA_MODE_CRC)
      {
        Serial.println("Conversion Data 0x%06x with CRC 0x%02x.", data, dCRC);
      }
      else*/
      //{
        Serial.println(data,DEC);  //This is where the raw conversion result should be available 
      //}
    
      
      /* Set ADC back to the previous configuration */
      //adc.sendCommand(STOP_OPCODE_MASK);
      //adc.sendCommand(SLEEP_OPCODE_MASK);
    
      //return dStatus;
    }
    
    /*void regMap(void)
    {
      unsigned int index;
      char cTemp;
      Serial.println("Register Contents");
      Serial.println("---------------------");
      for(index=0; index < 18 ; index++)
      {
        cTemp = adc.regRead(index);
        Serial.println(index, cTemp);
      }
    }*/
    void regMap2(void)
    {
      unsigned int index;
      uint8_t cTemp[18];
      adc.readRegs(0,18,cTemp);
      Serial.println("Register Contents");
      Serial.println("---------------------");
    
      for(index=0; index < 18 ; index++)
      {
        Serial.println("");
        Serial.print(index,":" );
        Serial.println( cTemp[index], HEX );
      }
    }

    Thank You for the quick response

    We implemented the changes you mentioned and tried testing the code, but when tried to read the contents of the registers we are receiving all 1's both before and after writing to the register. I am hereby attaching the csv file generated by logic analyser, the updated code , waiting for your response eagerly

    5340.digital.csv

  • Hi,

    Unfortunately the csv file takes a lot of manipulation of the data to be able to read it.  If you are using a Saleae it would be a lot easier for me to view the .logicdata or .sal file (depending on the software version being used.)

    Verify that the ADS124S08 supplies are operating at the nominal operating voltage (AVDD/AVSS, IOVDD and DVDD).  If one of the supplies is inactive the ADC will be held in a reset state.  Also verify that the RESET pin is also logic high.  Don't just assume that the code is working, but instead verify with a voltmeter, scope or logic probe.

    It is not clear what is happening in the analyzer screen shot you are showing.  Can you explain what is supposed to be happening?  Also note the short pulse on the 4th byte transmitted.  Data should change on the rising edge of SCLK and be stable on the falling edge.  Also note that the 5th byte is not decoded by the logic analyzer.  Here CS is going high before the end of the last SCLK.

    In the end, the communication is not working as you expect.  Taking a look at your code for a register read, we see that the values appear to be correct, but you need to verify that the transmission is correct.  A single register read for the Status register should appear as 0x21, 0x00, 0x00 for the transmit on the MOSI, and after power up the Status register should appear as 0x80 on MISO on the 3rd byte of SCLKs.

    When troubleshooting try not to do too much with your code.  Take one step of action at a time and verify.  For example, make sure that the RESET command is being transmitted properly at the beginning.  If this command is showing correctly add a single register read that is non-zero such as the ID or Status register.  Work through each function until you have verified the correct operation.

    Another thing to verify early on in your troubleshooting is the SPI timing.  It appears that you intend to use an SCLK frequency of 4MHz, but if you look at the period on the logic analyzer it looks to be closer to 100kHz (approximately 10 clocks in 0.1ms).

    Best regards,

    Bob B