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.

ads1218 problem reading.

Other Parts Discussed in Thread: ADS1218

Hello All,

I have been trying to read the analog imputs of the ADS1218, but have no look.

I am Able to read all the registers and they are well. all of them are at the reset state, and i am also able to change them.

What happens is that i cant find any guidelines at the Ti's page nor app notes with examples.

I am trying to use the RDATA command. but  the pin DRDY is not always at high, insteady it keeps going hi and low even before i send the comand.

I am trying to control the ADS1218 with the msp430. even when i try to read the temperature. as i have setup below.

thanks in advanvce.

  • Hi Edriano,

    I'm not sure what you are trying to show me with the data in your array.  The actual conversion result is ready when DRDY transistions from high to low.  If you do not retrieve any data you will see DRDY low must of the time and then pulse when the new conversion result is available.  As the result is 24 bits, you need to capture 3 bytes of data. To retrieve the data, you set the CS low, send the RDATA command, wait 50 tosc periods for the device to setup,followed by 3 NOPs (either 0x00 or 0xff), then when complete set CS back high.  When writing the NOPs, read the data returned following each write cycle.  You will have to assemble the data and sign extend appropriately if you use a signed int for the data result variable in your program.

    I'm willing to take a look at your code if you want to send me the portion of your code that you are using to read the data.

    Best regards,

    Bob B

  • Hi Bob, thank you for your prompt answer.

    The matrix was just to show that the digital communication is ok. I can read and write all the 15 registers without problems. through SPI.

    That is the first time i am working with this ADC and still learning the manual. and doing the configurations part by part. the first thing i am trying is to make a simple read AN0 and AN1 configured by default at the start up. without calibration. the code is very crude.

    I am not sure how to star the reading as at the manual they say DRDY will go low by the time a put CS low.

    I am really seeing the DRDY most of the time low and pulsing maybe i am not knowing how to read.

    Another thing i have notice is that the VREF out is at 5V when it should be 2.5. i will change the chip tomorrow.

    the ADC routines and SPI are in the email maybe it help others with the same problem.


    /**************************************************************************************************************
    *read adc 
    **************************************************************************************************************/
    void Adc_Ler_Canal(void)
    {

    while((P5IN & 0X10) == 1)  // waith until Drdy goes 0
    {

    }

    P8OUT &= ~ADC_CS;

    adc.tx_data[0] = 0X01;

    Spi_Data(adc.tx_data, adc.rx_data, 1);
    __delay_cycles(500);

    adc.tx_data[0] = 0X00;

    adc.tx_data[1] = 0X00;

    adc.tx_data[2] = 0X00;

    Spi_Data(adc.tx_data, adc.rx_data,3);

    P8OUT |= ADC_CS;

    }
    /**************************************************************************************************************
    *Write 15 registers at once with new configuration
    **************************************************************************************************************/
    void Adc_Escreve_Registros(unsigned char numero_registros)
    {
    unsigned char i;

    adc.tx_data[0] = 0x50; //MSB - Command (0x5X = Write to Register X)
    adc.tx_data[1] = 0x0F; //Number of registers to read

    adc.tx_data[2] = 0x04; //SETUP - ID ID ID SPEED REFEN REFHI BUFEN BITORDER
    adc.tx_data[3] = 0X01; //MUX PSEL3 PSEL2 PSEL1 PSEL0 NSEL3 NSEL2 NSEL1 NSEL0
    adc.tx_data[4] = 0X00; //ACR
    adc.tx_data[5] = 0X00; //IDAC1
    adc.tx_data[6] = 0X00; //IDAC2
    adc.tx_data[7] = 0X00; //ODAC
    adc.tx_data[8] = 0X00; //DIO
    adc.tx_data[9] = 0X00; //DIR
    adc.tx_data[10] = 0X80; //DEC0
    adc.tx_data[11] = 0X07; //M/DEC1
    adc.tx_data[12] = 0X00; //OCR0
    adc.tx_data[13] = 0X00; //OCR1
    adc.tx_data[14] = 0X00; //OCR2
    adc.tx_data[15] = 0X24; //FSR0
    adc.tx_data[16] = 0X90; //FSR1
    adc.tx_data[17] = 0X67; //FSR2

    P8OUT &= ~ADC_CS;
    Spi_Data(adc.tx_data, adc.rx_data, 18);

    P8OUT |= ADC_CS;


    }
    /**************************************************************************************************************
    *Read 15 register at once
    **************************************************************************************************************/
    void Adc_Ler_Registros(unsigned char numero_registros)
    {
    unsigned char x;

    __delay_cycles(100);

    adc.tx_data[0] = 0x10;
    adc.tx_data[1] = numero_registros;

    for(x = 0 ; x <= numero_registros ; x++)
    {
    adc.rx_data[x] = 0;
    }

    P8OUT &= ~ADC_CS;

    Spi_Data(adc.tx_data, adc.rx_data, 2);

    __delay_cycles(500);

    Spi_Data(adc.tx_data, adc.rx_data, numero_registros+1);

    P8OUT |= ADC_CS;


    }
    /**************************************************************************************************************
    *Start ADC
    **************************************************************************************************************/
    void Adc_Init(void){


    P3DIR |= BIT0;
    P5DIR |= BIT2 + BIT3 + BIT5 + BIT6;
    P5DIR &= ~BIT4;
    P8DIR |= BIT7;

    P6DIR |= BIT4 + BIT5 + BIT6 + BIT7;
    P7DIR |= BIT4 + BIT5 + BIT6 + BIT7;

    P5REN |= BIT2 + BIT3 + BIT5 + BIT6;

    P3OUT |= ADC_RESET;
    P5OUT |= ADC_SYNC + ADC_PDWN;
    P5OUT &= ~(ADC_WREN + ADC_BUFEN);

    P7OUT &= 0x00;
    P6OUT &= 0x00;

    P7OUT |= 0xA0;
    P6OUT |= 0xB0;

    P8OUT |= ADC_CS;

    LCDBPCTL2 = 0X000000;
    adc.enviado = 0;

    __delay_cycles(2000000);

    void Spi_Init(void)
    {
    P8REN |= BIT4 + BIT5 + BIT6;
    P8SEL |= BIT4 + BIT5 + BIT6; // Assign P8 to UCB1CLK and...
    P8DIR |= BIT4 + BIT5;

    UCB1CTL1 |= UCSWRST; // **Put state machine in reset**
    UCB1CTL0 |= UCMST+UCSYNC+UCMSB; // 3-pin, 8-bit SPI master
    // Clock polarity high, MSB
    UCB1CTL1 |= UCSSEL_2; // SMCLK
    UCB1BR0 = 20; //Para fclk = 1Mhz - UCB1BR0 = 0x15
    UCB1BR1 = 0x00; //
    //UCB0MCTL = 0; // No modulation
    UCB1CTL1 &= ~UCSWRST; // **Initialize USCI state machine**
    //UCB1IE = UCRXIE ; // Enable USCI_A0 RX,TX interrupt
    }

    void Spi_Data(unsigned char *tx_buff, unsigned char *rx_buff, unsigned char cont){

    spi.data_flag = 1;
    spi.tx_ok = 0;
    spi.tx_buffer = tx_buff; // buffer a ser enviado
    spi.rx_data = rx_buff;
    spi.conta = cont;
    UCB1IFG |= UCTXIFG;
    UCB1IE |= UCTXIE + UCRXIE;
    //__bis_SR_register(LPM0_bits + GIE); // CPU off, enable interrupts
    //__no_operation(); // Remain in LPM0
    //__delay_cycles(2000); // Delay before next transmission

    while (spi.data_flag != 0){
    }
    }

    #pragma vector = USCI_B1_VECTOR
    __interrupt void USCI_B1_ISR(void)
    {
    switch(__even_in_range(UCB1IV,0x04))
    {
    case 0: break; // Vector 0 - no interrupt
    case 2:
    if(spi.tx_ok){
    *spi.rx_data++ = UCB1RXBUF;
    spi.conta --;
    if(!spi.conta){
    UCB1IFG &= ~UCTXIFG;
    UCB1IFG &= ~UCRXIFG;
    UCB1IE &= ~(UCTXIE + UCRXIE);
    spi.data_flag = 0;
    }
    }else{
    UCB1IFG &= ~UCRXIFG;
    }
    // __bic_SR_register_on_exit(CPUOFF);// Wake up to setup next TX
    break;
    case 4:
    UCB1TXBUF = *spi.tx_buffer++; // Transmit characters
    spi.tx_ok = 1;
    break;
    default: break;
    }
    }

  • Hi Edriano,

    Yes, DRDY will appear low most of the time and will pulse when you are not reading out the data results.  DRDY will go high after the data has been read. Your read adc routine appears to be ok, but I'm not sure how you are manipulating the result.  Once you issue RDATA and capture the results to the array spi.rx_data, you need to assemble the data as a useful value.  This is usually an integer and can be a signed or unsigned value depending on whether the result is unipolar or bipolar format.  Let's say you created a variable called data_result and it is an unsigned 32 bit variable.  When using unipolar mode, or bipolar mode when the result is positive you can assemble the data as follows:

    data_result = ((spi.rx_data[0]<<16) + (spi.rx_data[1]<<8) + spi.rx_data[2]);

    If using bipolar mode and the result is negative you will need to sign extend the value:

    if(data_result && 0x00800000) data_result |= 0xff000000;

    This results in the return code of the conversion.  If you match the code to the value obtained from an oscilloscope/logic analyzer of when the data is captured you can verify the transfer.

    Best regards,

    Bob B

  • Hi Bob,

    Yas i am aware of need to format the number, but as i said i am trying to make the chip read. and if i short circuit or put the positive analog to +2.5 volts and negative to 0 volts i can not see the change. but as the VERF out is above 2.5 Volts. maybe the chip is broken.

    Maybe i am being a little beginner, but if i am using the only one read, why DRDY keeps pulsing even though i read the data.

    What would happen if i issue the continuous read.

  • Hi Edriano,

    Issuing a STOPC does not mean that the ADS1218 stops converting.  This can often be confusing as the RDATAC mode automatically places the result into the output register after the conversion is complete. Issuing the STOPC ends the RDATAC mode.  RDATAC mode eliminates the need to issue the RDATA command, so it saves one byte of the communication.  That is the only difference in operation.

    There is no single conversion mode with this device.  The only way to stop the device from converting is to place the device in SLEEP or set the PDWN pin low to power down the device.  The DRDY signal will always show when the conversion result has completed.  To know when the conversion cycle has completed you can poll the DRDY signal to look for completed conversions or you can set DRDY to trigger an interrupt on the high to low transition.  Within the interrupt you can read out the results.

    Best regards,

    Bob B

  • Hi Bob.

    thanks for the answer.

    I have learned a lot, as i suspected the ADS1218 was with the analog part burned. and the digital ok.

    could you point me now in the right direction in what would be the best time to change the analog inputs, would it be right after i read the previws one?

    i have changed the decimation to 0x80 and i am working with a crystal of 2,4576Mhz  fmod 5,4576/128 = 19200  --> Fdata  would be 19200/128=150Hz is it wright?

    I am seing at my osciloscope 4,1ms = 243 Hz. I am using fast settling time.

  • Hi Edriano,

    The modulator rate is determined by the SPEED bit setting.  Fmod is equal to fosc divided by 128 (SPEED=0) or 256 (SPEED=1).  Your crystal determines the fosc frequency, so if the crystal is 2.4576MHz and your SPEED=0, then the fmod is 19200Hz.  If your decimation is 0x080 (128) then the data output rate is 150Hz.  So your calculated outcome is correct, I'm not sure where you came up with 54576/128. I would check that you are actually writing 0x80 and not decimal 80. 19200/80 is about 240 sps.

    As far as changing the mux inputs, the sooner you can do this the better for best settling response.  You can reset the digital filter by issuing the DSYNC command.  This has the same response as starting a new conversion cycle.  So for consistent data response you can read the data result, change the mux channels, then issue a DSYNC command.

    Best regards,

    Bob B