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.

Incorrect conversion results with ADS1242 & ADS1243

Other Parts Discussed in Thread: ADS1243, MSP430F449

Hi

I have a project where I have interfaced an ADS1243 to an MSP430F449. The ADC has a clean 3.3V supply and Vref is given a clean 1.22V reference.

 

I have had problems with incorrect readings so I tied input channel 3 to the voltage reference. Most of the time the conversions are exactly half what I’m expecting i.e. 8388607 ADC bits instead of 16777215 ADC bits. Occasionally I have the correct reading. I have checked the timing of my digital communications and I’m confident that they are ok. I have pasted my code for selecting the ADC input channel and taking a reading below. Could you please give me some pointers as to what could be going wrong?

 

Kind regards

 

Andrew 


unsigned long read_ADC24_1()

{

  unsigned long int value = 0;

  char dummy_char = 0;

 

  U0TCTL_bit.CKPL = 1;

 

  adc_CS = 1;

  read_try=0;

  adc_CS = 0;

  

  // Issue a read command to the 24bit DAC

  if ((U0TCTL & TXEPT) == 1) {

    TXBUF0 = 0x01;

  }

 

  //adc_time = 0;

  while((U0TCTL & TXEPT) == 0);

 

  read_try=0;

  tosc=0;

  while(!(IFG1 & URXIFG0)) {

    if (tosc>50) {

 

      // Issue a read command to the 24bit DAC

      if ((U0TCTL & TXEPT) == 1) {

        TXBUF0 = 0x01;

      }

 

      //adc_time = 0;

      while((U0TCTL & TXEPT) == 0) {

        //if (adc_time>=1) {

          if (read_try==15) return(0);

          if (read_try==5) {

            TXBUF0 = 0xFE; // Reset the ADC

            tosc=0;

            while(tosc<1);

            TXBUF0 = 0xF0; // Do self cal

            while(adc24_drdy==0);

            while(adc24_drdy==1);

            while(adc24_drdy==0);

            while((U0TCTL & TXEPT) == 0);

          }

          read_try++;

          // Issue a read command to the 24bit DAC

          if ((U0TCTL & TXEPT) == 1) {

            TXBUF0 = 0x01;

          }

         // adc_time=0;

       // }

 

      }

 

    }

  }

  IFG1 &= ~URXIFG0;

  dummy_char = U0RXBUF;

  read_try=0;

 

  // Wait for 50 clk cycles

  tosc=0;

  while(tosc<50);

 

  //adc_time=0;

  while(adc24_drdy==1) {

   // if (adc_time>=10) return (0);

  }

 

 

  // Read the most significant byte from the ADC

  // We need to send a "dummy" bytes to the ADC to generate a clock pulse

  // to clock out the data

  if ((U0TCTL & TXEPT) == 1) {

    TXBUF0 = 0x02;

  }

  //adc_time=0;

  while(!(IFG1 & URXIFG0)) {

   // if (adc_time>=10) return (0);

    while (adc24_drdy == 1);// return (0);

  }

  while (adc24_drdy == 1);// return (0);

  IFG1 &= ~URXIFG0;

 

  value = U0RXBUF;

 

  value <<= 8;

 

  //adc_time=0;

  while((U0TCTL & TXEPT) == 0) {

    //if (adc_time>=10) return (0);

  }

 

 // adc_time = 0;

  while(adc24_drdy==1) {

   // if (adc_time>=10) return (0);

  }

 

 

  // Read the middle byte

 

  if ((U0TCTL & TXEPT) == 1) {

    TXBUF0 = 0x03;

  }

 

 // adc_time = 0;

  while(!(IFG1 & URXIFG0)) {

    //if (adc_time>=10) return (0);

    while (adc24_drdy == 1);// return (0);

  }

 

  while (adc24_drdy == 1);// return (0);

 

 

 

  IFG1 &= ~URXIFG0;

 

  value |= U0RXBUF;

 

  value <<= 8;

 

  //adc_time = 0;

  while((U0TCTL & TXEPT) == 0) {

    //if (adc_time>=10) return (0);

  }

 

  // Read the least significant byte

  //adc_time = 0;

  while(adc24_drdy==1) {

   // if (adc_time>=10) return (0);

  }

 

 

  if ((U0TCTL & TXEPT) == 1) {

    TXBUF0 = 0x04;

  }

 

  //adc_time = 0;

  while(!(IFG1 & URXIFG0)) {

    //if (adc_time>=10) return (0);

    while (adc24_drdy == 1);// return (0);

  }

 

 // if (adc24_drdy == 1) return (0);

 

  IFG1 &= ~URXIFG0;

  value |= U0RXBUF;

 

  adc_CS = 1;

 

  return value;

}

 

unsigned long read_ADC24_2()

{

  unsigned long int value = 0;

  char dummy_char = 0;

  adc_2_CS = 1;

  read_try=0;

  adc_2_CS = 0;

 

  tosc=0;

 

  U0TCTL_bit.CKPL = 1;

 

  //while(tosc<500);

 

  TXBUF0 = 0x50; // Write to reg 00h (setup reg)

  while((U0TCTL & TXEPT) == 0);

  TXBUF0 = 0x00; // reg is 1 byte

  while((U0TCTL & TXEPT) == 0);

  TXBUF0 = 0x00; // Set disable burnout and set gain to 1

  while((U0TCTL & TXEPT) == 0);

 

  //adc_time = 0;

  while(adc24_2_drdy==1) {

    //if (adc_time>=10) return (0);

  }

  // Issue a read command to the 24bit DAC

  if ((U0TCTL & TXEPT) == 1) {

    TXBUF0 = 0x01;

  }

 

  while((U0TCTL & TXEPT) == 0);

 

  read_try=0;

  tosc=0;

  while(!(IFG1 & URXIFG0)) {

    if (tosc>50) {

 

      // Issue a read command to the 24bit DAC

      if ((U0TCTL & TXEPT) == 1) {

        TXBUF0 = 0x01;

      }

 

      //adc_time = 0;

      while((U0TCTL & TXEPT) == 0) {

        //if (adc_time>=1) {

          if (read_try==15) return(0);

          if (read_try==5) {

            TXBUF0 = 0xFE; // Reset the ADC

            tosc=0;

            while(tosc<1);

            TXBUF0 = 0xF0; // Do self cal

            while(adc24_drdy==0);

            while(adc24_drdy==1);

            while(adc24_drdy==0);

            while((U0TCTL & TXEPT) == 0);

          }

          read_try++;

          // Issue a read command to the 24bit DAC

          if ((U0TCTL & TXEPT) == 1) {

            TXBUF0 = 0x01;

          }

         // adc_time=0;

       // }

 

      }

 

    }

  }

  IFG1 &= ~URXIFG0;

  dummy_char = U0RXBUF;

  read_try=0;

 

  // Wait for 50 clk cycles

  tosc=0;

  while(tosc<50);

 

  //adc_time=0;

  while(adc24_2_drdy==1) {

   // if (adc_time>=10) return (0);

  }

 

  // Read the most significant byte from the ADC

  // We need to send a "dummy" bytes to the ADC to generate a clock pulse

  // to clock out the data

  if ((U0TCTL & TXEPT) == 1) {

    TXBUF0 = 0x02;

  }

  //adc_time=0;

  while(!(IFG1 & URXIFG0)) {

   // if (adc_time>=10) return (0);

    while (adc24_2_drdy == 1);// return (0);

  }

  while (adc24_2_drdy == 1);// return (0);

  IFG1 &= ~URXIFG0;

 

  value = U0RXBUF;

 

  value <<= 8;

 

  //adc_time=0;

  while((U0TCTL & TXEPT) == 0) {

    //if (adc_time>=10) return (0);

  }

 

 // adc_time = 0;

  while(adc24_2_drdy==1) {

   // if (adc_time>=10) return (0);

  }

 

  // Read the middle byte

 

  if ((U0TCTL & TXEPT) == 1) {

    TXBUF0 = 0x03;

  }

 

 // adc_time = 0;

  while(!(IFG1 & URXIFG0)) {

    //if (adc_time>=10) return (0);

    while (adc24_2_drdy == 1);// return (0);

  }

 

  while (adc24_2_drdy == 1);// return (0);

 

  IFG1 &= ~URXIFG0;

 

  value |= U0RXBUF;

 

  value <<= 8;

 

  //adc_time = 0;

  while((U0TCTL & TXEPT) == 0) {

    //if (adc_time>=10) return (0);

  }

 

  // Read the least significant byte

  //adc_time = 0;

  while(adc24_2_drdy==1) {

   // if (adc_time>=10) return (0);

  }

 

  if ((U0TCTL & TXEPT) == 1) {

    TXBUF0 = 0x04;

  }

 

  //adc_time = 0;

  while(!(IFG1 & URXIFG0)) {

    //if (adc_time>=10) return (0);

    while (adc24_2_drdy == 1);// return (0);

  }

 

 // if (adc24_drdy == 1) return (0);

 

  IFG1 &= ~URXIFG0;

  value |= U0RXBUF;

 

  tosc=0;

 // while(tosc<50);

 

  adc_2_CS = 1;

 

 

  tosc=0;

 // while(tosc<50);

  return value;

}

 

void set_channel_1(short channel)

{

  adc_CS = 0;

 

  U0TCTL_bit.CKPL = 1;

 

  while(adc24_drdy==1) {

    //if (adc_time>=10) return (0);

  }

 

  TXBUF0 = 0x51; // Write to reg 10h (MUX)

  while((U0TCTL & TXEPT) == 0);

  tosc=0;

  while(tosc<50);

  TXBUF0 = 0x00; // reg is 1 byte

  while((U0TCTL & TXEPT) == 0);////////////////////////////////////////

  tosc=0;

  while(tosc<50);

  TXBUF0 = 0x08 | (channel << 4); // Set negative channel to A In common and select AIN channel as positive channel

  while((U0TCTL & TXEPT) == 0);////////////////////////////////////////

 

 

  tosc=0;

  while(tosc<50);

 

  //adc_time = 0;

  while(adc24_drdy==0) {

    //if (adc_time>=10) return (0);

  }

  while(adc24_drdy==1) {

    //if (adc_time>=10) return (0);

  }

  while(adc24_drdy==0) {

    //if (adc_time>=10) return (0);

  }

  while(adc24_drdy==1) {

    //if (adc_time>=10) return (0);

  }

  while(adc24_drdy==0) {

    //if (adc_time>=10) return (0);

  }

  while(adc24_drdy==1) {

    //if (adc_time>=10) return (0);

  }

  while(adc24_drdy==0) {

    //if (adc_time>=10) return (0);

  }

  while(adc24_drdy==1) {

    //if (adc_time>=10) return (0);

  }

  while(adc24_drdy==0) {

    //if (adc_time>=10) return (0);

  }

  while(adc24_drdy==1) {

    //if (adc_time>=10) return (0);

  }

  while(adc24_drdy==0) {

    //if (adc_time>=10) return (0);

  }

  while(adc24_drdy==1) {

    //if (adc_time>=10) return (0);

  }

 

  adc_CS = 1;

}

 

  • Hi Andrew,

    Half scale errors on an SPI bus are often caused by incorrect clock phasing or polarity.  I see you set CKPL bit to '1' in your code.  What happens when you set that to '0'?  Can you post your SPI timing (i.e. an 0-scope screen capture) and provide a simple description of how you have the registers configured?

    Regards,

    Tom

  • Hi Tom,

    Thank you very much for your reply.

    I have set CKPL to '0', and the ADC works correctly. I have been doing some further investigations and it seems that my problems centre around a digital pot (AD5235) which is also attached to the SPI bus. The digital pot requires a different phase to the ADC. My code for communicating with the digital pot is.

    If I remove the calls to the digital pot from my code the ADC runs correctly. I have been very careful to ensure that the relevent chip select lines are pulled high to prevent the wrong data being written to the wrong devices.

    Kind regards

    Andrew

     

    // Sets the "pot" wiper position to "position"
    void set_digi_pot(char pot, int position)
    {
      char data[3] = {0};


    // Change clock phase for the digital pot

      U0TCTL_bit.CKPH = 1;
      U0TCTL_bit.CKPL = 0;
     
      if (pot == 0)
        data[0] = 0xB0;
     
      if (pot == 1)
        data[0] = 0xB1;
     
      data[1] = position >> 8;
      data[2] = position;
     
      digipot_cs = 0; // cs low
      spi_write(3, (unsigned char*)data);   
      digipot_cs = 1; // cs high

    //Put the clock phase back so that it's suitable for the ADC
      U0TCTL_bit.CKPH = 0;
      U0TCTL_bit.CKPL = 0;
     
    }

  • In my haste to post my last reply I forgot to ask are there any known issues with changing the SPI bus's clock and phase on the fly?

  • Hi Andrew,

    Glad to hear things are working now!  As for swapping CPOL and CPHA on the fly - there is no problem with that as far as I know so long as each part is 'de selected' before any communication actually starts. 

    Best Regards,

    Tom Hendrick