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.

ADS1258-EP: ADS1258 random reading problem

Part Number: ADS1258-EP
Other Parts Discussed in Thread: MSP430FR5989, ADS1258

Tool/software:

Hello all,

I am using ads1258-ep adc converter with msp430fr5989. My problem is that after reset I cannot reading any conversion data from ads1258. I have noticed that I couldn't read the registers that I tried the configurate before the conversion part. I have used the official ads1258 driver from website with little updates. Here is my code below.


static uint8_t WrittenregisterMap[NUM_REGISTERS];
static uint8_t ReadregisterMap[NUM_REGISTERS];


uint8_t getRegisterValue(uint8_t address){

    return ReadregisterMap[address];
}


uint8_t SendReceiveByte(uint8_t dataTx){

    uint8_t dataRx;
    uint16_t timeout = TIMEOUT;

    while(!(UCB1IFG & UCTXIFG)){
        if (--timeout == 0){
            return SPI_TIMEOUT_ERR ;
        }
    }

    UCB1TXBUF = dataTx;
    __delay_cycles(10);

    while(!(UCB1IFG & UCRXIFG)){

        if (--timeout == 0){
            return SPI_TIMEOUT_ERR ;
        }
    }

    dataRx = UCB1RXBUF;
    return dataRx;


}
uint8_t SendReceiveArrays(uint8_t *dataTx, uint8_t *dataRx, uint16_t byteLength ){
    uint16_t i;
    uint16_t timeout = TIMEOUT;

    setADS_CS(LOW);
   __delay_cycles(10);

    for (i=0; i<byteLength; i++){

      while(!(UCB1IFG & UCTXIFG)){

          if (--timeout == 0){
                return SPI_TIMEOUT_ERR ;
          }

      }

      UCB1TXBUF = dataTx[i];
      __delay_cycles(10);

      while(!(UCB1IFG & UCRXIFG)){

          if (--timeout == 0){
              return SPI_TIMEOUT_ERR ;
          }
      }
      dataRx[i] = UCB1RXBUF;

    }
   // return SPI_TIMEOUT_NOERR;

    setADS_CS(HIGH);


}

void readMultipleRegisters(uint8_t startAddress, uint8_t count){

    uint8_t i;
    setADS_CS(LOW);
    __delay_cycles(20);
    uint8_t dataTx = OPCODE_RREG | OPCODE_MUL_MASK | (startAddress & OPCODE_A_MASK);
    SendReceiveByte(dataTx);


    for (i = startAddress; i < startAddress + count; i++)
    {   __delay_cycles(20);
        // read register data bytes
        ReadregisterMap[i] = SendReceiveByte(0x00);

    }
    __delay_cycles(20);
    setADS_CS(HIGH);
    __delay_cycles(20);




}
void writeMultipleRegisters(uint8_t startAddress, uint8_t count, const uint8_t regData[])
{  

    uint8_t i;

    setADS_CS(LOW);

    __delay_cycles(20);
    uint8_t dataTx = OPCODE_WREG | OPCODE_MUL_MASK | (startAddress & OPCODE_A_MASK);
    SendReceiveByte(dataTx);
  

    for (i = startAddress; i < startAddress + count; i++)
    {    __delay_cycles(20);
        // write register data bytes
        SendReceiveByte(regData[i]);

    }
    __delay_cycles(20);
    setADS_CS(HIGH);
    __delay_cycles(20);


}

int32_t ADS_ReadData(uint8_t status[], readMode mode)
{
    uint8_t DataTx[5] = { 0 };    
    uint8_t DataRx[5] = { 0 };    
    uint8_t byteLength;
    uint8_t dataPosition;
    bool    status_byte_enabled;

    /* Build TX array and send it */
    if (mode == DIRECT)
    {
        DataTx[0] = OPCODE_READ_DIRECT;

        /* STATUS byte enable depends on MUXMOD and STAT (see table 17 in datasheet) */
        status_byte_enabled = IS_STAT_SET & !IS_MUXMOD_SET;
        byteLength = (status_byte_enabled ? 4 : 3);
        dataPosition = (status_byte_enabled ? 1 : 0);
    }
    else if (mode == COMMAND)
    {
        DataTx[0] = OPCODE_READ_COMMAND | OPCODE_MUL_MASK;

        /* STATUS byte always enabled, but undefined in fixed-channel mode (see table 17 in datasheet) */
        status_byte_enabled = true;
        byteLength = 5;
        dataPosition = 2;
    }
    SendReceiveArrays(DataTx, DataRx, byteLength);


    //
    // Parse returned SPI data
    //

    /* Check if STATUS byte is enabled and if we have a valid "status" memory pointer */
    if (status_byte_enabled && status)
    {
        status[0] = DataRx[dataPosition - 1];
    }


    /* Return the 32-bit sign-extended conversion result */
	int32_t signByte;
    if (DataRx[dataPosition] & 0x80u)   { signByte = 0xFF000000; }
    else                                { signByte = 0x00000000; }

	int32_t upperByte 	= ((int32_t) DataRx[dataPosition + 0] & 0xFF) << 16;
	int32_t middleByte  = ((int32_t) DataRx[dataPosition + 1] & 0xFF) << 8;
	int32_t lowerByte	= ((int32_t) DataRx[dataPosition + 2] & 0xFF) << 0;

	return (signByte | upperByte | middleByte | lowerByte);
}

bool ADS_RegisterConfig(){

    bool b_pass = true;
    int i =0;

    // Test configuration
    WrittenregisterMap[REG_ADDR_CONFIG0]  =  CONFIG0_DEFAULT & ~CONFIG0_MUXMOD_MASK;  // Auto-scan mode
    WrittenregisterMap[REG_ADDR_CONFIG1]  =  CONFGI1_DOSI; // Slowest data rate
    WrittenregisterMap[REG_ADDR_MUXSCH]   =  MUXSCH_DEFAULT;
    WrittenregisterMap[REG_ADDR_MUXDIF]   =  MUXDIF_DEFAULT;                          // Differential channels off
    WrittenregisterMap[REG_ADDR_MUXSG0]   =  MUXSG0_DOSI;  //0x3E
    WrittenregisterMap[REG_ADDR_MUXSG1]   =  MUXSG1_DOSI; // 0x2B
    WrittenregisterMap[REG_ADDR_SYSRED]   =  SYSRED_DEFAULT;
    WrittenregisterMap[REG_ADDR_GPIOC]    =  GPIOC_DOSI;
    WrittenregisterMap[REG_ADDR_GPIOD]    =  GPIOD_DOSI;
    WrittenregisterMap[REG_ADDR_ID]       =  0x00;

    // Write registers
    writeMultipleRegisters(REG_ADDR_CONFIG0, NUM_REGISTERS-1, WrittenregisterMap);
    __delay_cycles(1000);
    //Read registers
    readMultipleRegisters(REG_ADDR_CONFIG0, NUM_REGISTERS-1);


    for (i =0 ;i< NUM_REGISTERS-1 ; i++ ){
        b_pass &=  (getRegisterValue(i)== WrittenregisterMap[i]);
    }

  // return (b_pass ? ADS_REG_CONFIG_NOERR : ADS_REG_CONFGI_ERR);
  return 1;

}

bool  ConfigAds(){

      bool reg_conf_ok = false;

      delay_ms(50);


      toggleADS_RESET();

     /*Configure ADS Registers */

     reg_conf_ok = ADS_RegisterConfig();
     startADS_Conversions();
     delay_ms(100);



     return reg_conf_ok;


}


void InitAdsInterrupt(){

  P2IES |=  TR_ADC_DRDY; // Data ready low clock edge interr
  P2IFG &= ~ TR_ADC_DRDY; // Clear interr flag
 // P2IE |=  TR_ADC_DRDY; // Activate interr
  delay_ms(100);



}

void InitAdsSpi(){
   

   UCB1CTLW0 |= UCSWRST; // put SPI in reset state
   UCB1CTLW0 |= UCSYNC | UCCKPH | UCMSB | UCMST | UCSSEL__SMCLK; // 8 bit SPI Master , MSB first , Clock polarity high ,SMCLK
   UCB1BRW = 2; // set clock divider to achieve 1MHz clock with SMCLK at 1 Mhz
   UCB1CTLW0 &= ~ UCSWRST; // Release SPI for operation
   UCB1IE |= UCRXIE; // Enable USCI_B1 interrupt
   
   delay_ms(100);

}



void setADS_PWDN(bool state)
{
    /* --- TODO: INSERT YOUR CODE HERE --- */
   if (state == HIGH)
        P5OUT |= TR_ADC_PWDN ;
   else
        P5OUT &= ~TR_ADC_PWDN;
    

    __delay_cycles(2);
}

void SetAdsOE(bool state){

    if (state == HIGH)
        P2OUT |= TR_ADC_OE ;
    else
        P2OUT &= ~TR_ADC_OE;
    

    delay_ms(1000);


}


void setADS_CS(bool state){
 
    if (state == HIGH)
        P5OUT |= TR_ADC_CS ;
    else
        P5OUT &= ~TR_ADC_CS;
    

    __delay_cycles(2);

}



void startADS_Conversions(){
  /* Ensure device is not in PWDN mode */

       
  /* Begin continuous conversions */

   setADS_START(HIGH);

}
void setADS_START(bool state){

    if (state == HIGH)
        P5OUT |= TR_ADC_START ;
    else
        P5OUT &= ~TR_ADC_START;
    

    __delay_cycles(2);

}


void toggleADS_RESET(){

     P5OUT &= ~TR_ADC_RST;

     __delay_cycles(10); //Min 2 tCLK

     P5OUT |= TR_ADC_RST;
     __delay_cycles(10);



}
void setADS_RESET(bool state){

    if (state == HIGH)
        P5OUT |= TR_ADC_RST ;
    else
        P5OUT &= ~TR_ADC_RST;
    

    __delay_cycles(2);

}



void process_ads_data(S_ADS_DATA *ads_data , S_ADS_STATUS_DATA *ads_status_data, int32_t dataValues, uint8_t statusBytes){


    switch (statusBytes & STATUS_CHID_MASK){

           case STATUS_CHID_AIN1 :

               ads_data->Ads_Vsens_11V = dataValues;
               ads_status_data->Ads_Stat_Vsens_11V = statusBytes;
               break;

           case STATUS_CHID_AIN2 :
               ads_data->Ads_Curr_Sens2 = dataValues;
               ads_status_data->Ads_Stat_Curr_Sens2 = statusBytes;
               break;

           case STATUS_CHID_AIN3 :
               ads_data->Ads_Vt01_Out2 = dataValues;
               ads_status_data->Ads_Stat_Vt01_Out2 = statusBytes;
               break;

           case STATUS_CHID_AIN4 :
               ads_data->Ads_Curr_Sens1 = dataValues;
               ads_status_data->Ads_Stat_Curr_Sens1 = statusBytes;
               break;
           case STATUS_CHID_AIN5 :
               ads_data->Ads_Vt01_Out1 = dataValues;
               ads_status_data->Ads_Stat_Vt01_Out1 = statusBytes;
               break;

           case STATUS_CHID_AIN8 :
               ads_data->Ads_Temp1_Pwr = dataValues;
               ads_status_data->Ads_Stat_Temp1_Pwr = statusBytes;
               break;

           case STATUS_CHID_AIN9 :
               ads_data->Ads_Temp_Sens = dataValues;
               ads_status_data->Ads_Stat_Temp_Sens = statusBytes;
               break;

           case STATUS_CHID_AIN11 :
               ads_data->Ads_20V = dataValues;
               ads_status_data->Ads_Stat_20V = statusBytes;
               break;

           case STATUS_CHID_AIN13 :
               ads_data->Ads_11V = dataValues;
               ads_status_data->Ads_Stat_11V = statusBytes;
               break;
           case STATUS_CHID_OFFSET :
               ads_data->Ads_Offset = dataValues;
               ads_status_data->Ads_Stat_Offset = statusBytes;
               break;
           case STATUS_CHID_GAIN :
                ads_data->Ads_Gain = dataValues;
                ads_status_data->Ads_Stat_Gain = statusBytes;
                break;
           case STATUS_CHID_TEMP :
                ads_data->Ads_Temp = dataValues;
                ads_status_data->Ads_Stat_Temp = statusBytes;
                break;
           default:
               break;


           }


}

bool waitforDataReady(uint32_t timeout_ms){

   uint32_t  timeout = timeout_ms * 1000;

   do{

       timeout--;
   }while( (!(P2IFG & TR_ADC_DRDY)) && (timeout>0));

   P2IFG &= ~TR_ADC_DRDY;

  return (timeout>0);

}



void SetMcuClock(){

    Config_Osc_Pins(); // Osc pinlerini ayarla

    FRCTL0 = FRCTLPW | NWAITS1;
    CSCTL0_H = CSKEY_H; // Unlock CS registers
    //CSCTL1 = DCOFSEL_0 | DCORSEL; // Set DCO to 1 Mhz
    CSCTL1 = DCOFSEL_0 ; // Set DCO to 1 Mhz
    CSCTL2 = SELA__LFXTCLK | SELS__DCOCLK | SELM__DCOCLK; //ACLK'nın kaynağı OSC
    CSCTL3 = DIVA__1 | DIVS__1 | DIVM__1;
    CSCTL4 &= ~LFXTOFF;
   // CSCTL4 &= ~LFXTBYPASS;

    // LFXT1, OSC 'in stabilize olmasi icin bekle
    do {

        CSCTL5 &= ~LFXTOFFG;
        SFRIFG1 &= ~OFIFG;

    }while (SFRIFG1 & OFIFG);

    CSCTL0_H = 0;


}

void Config_ADS1258_Pins(){

   P3SEL0 |= TR_ADC_SCLK | TR_ADC_DIN | TR_ADC_DOUT    ;
   P3SEL1 &= ~(TR_ADC_SCLK | TR_ADC_DIN | TR_ADC_DOUT) ;

  // P3DIR |=  TR_ADC_SCLK | TR_ADC_DIN ; // set P3.0 P3.1  as output
   //P3DIR &= ~(TR_ADC_DOUT ); // set P3.2 as input

   P5OUT &= ~( TR_ADC_START  );
   P5OUT |=  TR_ADC_CS | TR_ADC_PWDN ; // set P5.3 output high
   P5DIR |= TR_ADC_OSC  | TR_ADC_START | TR_ADC_PWDN | TR_ADC_CS  ; // set P5.0 P5.1 P5.2 P5.3 as output;


   //P5SEL0 &= ~(TR_ADC_CS);
   P5SEL0 |= TR_ADC_OSC;
   P5SEL1 |= TR_ADC_OSC ;
  // P5SEL1 |= TR_ADC_OSC | TR_ADC_CS;


   P2OUT |=  TR_ADC_OE ;  // set  P2.5 as output high
   P2DIR |=  TR_ADC_OE | TR_ADC_RST; // set P2.5 P2.7 as output
   P2DIR &= ~( TR_ADC_DRDY); // set P2.6 as input


}
int main(void)
{

     WDTCTL = WDTPW | WDTHOLD;               // Stop WDT
    PM5CTL0 &= ~LOCKLPM5;                   // Disable GPIo power on high power impedance

    SetMcuClock();
    SetMcuPins();


    EnablePowers();
    InitAdsSpi();
    InitAdsInterrupt();



    ConfigAds();

    __bis_SR_register(GIE); //Enter LMP0 enable interrupts

    while (1)
  {

 

       __bis_SR_register(GIE);

    }
}

Any help will be appreciated.

Regards.