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.

ADS1291 have problem retrieving converted data

Other Parts Discussed in Thread: ADS1291, MSP430F5529, MSP430F5522

hello everyone. 

i have problem retrieving converted data from ADS1291.

this is my ADS1291 Circuit.

and i have already test this ADS1291 Circuit on bread board with MSP430F5529 development board. 

and it's can work perfectly.

But  now. i am using ADS1291 external CLK=2.048MZ  and SPI CLOCK=4MHZ    with  MSP430F5522    , and i have MSP430F5522 external CLK=8MHZ.

and i found that i can't read/write ADS1291 correctly.

and after some try and error.

i found that i can write/read ADS1291 register correctly if i add a delay when i write ADS1291 register.

here is my MSP430F5522 source code

#include <msp430f5529.h>
#include <math.h>


#define   START            0x80         // P2.7
#define   PWDN             0xFE         // P2.0
#define   RESET_BT         0xBF         // P2.6
#define   DRDY_0           0x02         // P2.1
#define   CS_0             0xEF         // P4.4



char STAT0[3], RESU0[24], STAT1[3], RESU1[24];
char LOFF_P0, LOFF_N0, LOFF_P1, LOFF_N1, header, rx_data, rx_on=0, tx_on=0;



void configure_uart(void)
{
  P3SEL |= BIT3 + BIT4;                     // P3.3,4 = USCI_A0 TXD/RXD
  UCA0CTL1 |= UCSWRST;                      // **Put state machine in reset**
  UCA0CTL1 |= UCSSEL_2;                     // SMCLK
  UCA0BR0 = 0x08;                           // 8MMHz 921600 (see User's Guide)
  UCA0BR1 = 0x00;                           // 8MMHz 921600
  UCA0MCTL |= UCBRS_6 + UCBRF_8;            // Modulation UCBRSx=1, UCBRFx=0
  UCA0CTL1 &= ~UCSWRST;                     // **Initialize USCI state machine**
  UCA0IE |= UCRXIE;                         // Enable USCI_A0 RX inter
}



void configure_spi(void)                    //在這邊設定port4(解多工器) P4DIR P4OUT  
{
                                            // P1DIR |= 0x80  P1.7 for RESET_ADS
  P2DIR |= 0XC1;                            // P2.0, 6, 7 for PWDN, RESET_BT, START
  P3SEL |= BIT0 + BIT1 + BIT2;              // P3.0, 1, 2 SPI option select
  P4DIR |= 0X1F;                           
  P4OUT |= ~CS_0 ;                         

  UCB0CTL1 |= UCSWRST;                      // **Put state machine in reset**
  UCB0CTL0 |= UCMST+UCSYNC+UCMSB;           // 3-pin, 8-bit SPI master, MSB
  UCB0CTL1 |= UCSSEL_2;                     // SMCLK
  UCB0BR0 = 0x02;                           // /2  
  UCB0BR1 = 0x00;                           //
  UCB0CTL1 &= ~UCSWRST;                     // **Initialize USCI state machine*
}



void main(void)
{
  char i;
 
  WDTCTL = WDTPW + WDTHOLD;                 // Stop WDT
 


  P5SEL |= BIT2+BIT3;                       // Port select XT2

  UCSCTL6 &= ~XT2OFF;                       // Enable XT2
  UCSCTL3 |= SELREF_2;                      // FLLref = REFO
                                            // Since LFXT1 is not used,
                                            // sourcing FLL with LFXT1 can cause
                                            // XT1OFFG flag to set
  UCSCTL4 |= SELA_2;                        // ACLK=REFO,SMCLK=DCO,MCLK=DCO

  // Loop until XT1,XT2 & DCO stabilizes - in this case loop until XT2 settles
  do
  {
    UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + DCOFFG);
                                            // Clear XT2,XT1,DCO fault flags
    SFRIFG1 &= ~OFIFG;                      // Clear fault flags
  }while (SFRIFG1&OFIFG);                   // Test oscillator fault flag

  UCSCTL6 &= ~XT2DRIVE0;                    // Decrease XT2 Drive according to
                                            // expected frequency
  UCSCTL4 |= SELS_5 + SELM_5;               // SMCLK=MCLK=XT2



  configure_uart();
  configure_spi();                      // Setup SPI
 
  P2OUT &= PWDN;                           //PWDN = 0
  P2OUT &= RESET_BT;                     // P2.6  RESET_BT
  P2OUT &= ~START;                         //START = 0
  P2OUT |= ~PWDN;                          //PWDN = 1
                                          
    
  P4OUT &= CS_0;                        // CS=0 CS Enable
 
  while (!(UCB0IFG&UCTXIFG));            // SDATAC
  UCB0TXBUF = 0x11;
    
  while (!(UCB0IFG&UCTXIFG));             //從01h開始寫
  UCB0TXBUF = 0x41;
 
  while (!(UCB0IFG&UCTXIFG));             //寫3個暫存器
  UCB0TXBUF = 0x02;

  for (i = 0; i < 10; i++);
 
  while (!(UCB0IFG&UCTXIFG));       // WREG CONFIG1 0x03   00000011  continuous mode, Data rate = 1KSPS
  UCB0TXBUF = 0x03;

  for (i = 0; i < 10; i++);
 
  while (!(UCB0IFG&UCTXIFG));             // WREG CONFIG2 0xA0   10100000  internal reference 2.4 V
  UCB0TXBUF = 0xA0;
 
  while (!(UCB0IFG&UCTXIFG));             // WREG Lead-Off Control Register 0x10   00010000
  UCB0TXBUF = 0x10;
 
  while (!(UCB0IFG&UCTXIFG));            //從04h開始寫
  UCB0TXBUF = 0x44;
 
  while (!(UCB0IFG&UCTXIFG));            //寫兩個暫存器
  UCB0TXBUF = 0x01;
   
  while (!(UCB0IFG&UCTXIFG));             // WREG CH1     0x10   00010000    
  UCB0TXBUF = 0x10;

  while (!(UCB0IFG&UCTXIFG));             // WREG CH2     0x81   10000001   power down CH2  
  UCB0TXBUF = 0x81;

  while (!(UCB0IFG&UCTXIFG));             //從08h開始寫
  UCB0TXBUF = 0x48;

  while (!(UCB0IFG&UCTXIFG));            //寫一個暫存器
  UCB0TXBUF = 0x00;

  while (!(UCB0IFG&UCTXIFG));            //    01000000   CLK_DIV = 1 , CLK = 2.048MHZ    
  UCB0TXBUF = 0x40;

  while (!(UCB0IFG & UCTXIFG)); // RREG starting at address 1  00100001  01h 開始讀
UCB0TXBUF = 0x21;
while (!(UCB0IFG & UCTXIFG)); // 讀8個  Registers
UCB0TXBUF = 0x07;
while (!(UCB0IFG & UCTXIFG)); // first dummy data
UCB0TXBUF = 0x00;
while (!(UCB0IFG & UCTXIFG)); // another dummy data
UCB0TXBUF = 0x00;
while (!(UCB0IFG & UCRXIFG));
RES[0] = UCB0RXBUF;
while (!(UCB0IFG & UCTXIFG));
UCB0TXBUF = 0x00;
while (!(UCB0IFG & UCRXIFG));
RES[1] = UCB0RXBUF;
while (!(UCB0IFG & UCTXIFG));
UCB0TXBUF = 0x00;
while (!(UCB0IFG & UCRXIFG));
RES[2] = UCB0RXBUF;
while (!(UCB0IFG & UCTXIFG));
UCB0TXBUF = 0x00;
while (!(UCB0IFG & UCRXIFG));
RES[3] = UCB0RXBUF;
while (!(UCB0IFG & UCTXIFG));
UCB0TXBUF = 0x00;
while (!(UCB0IFG & UCRXIFG));
RES[4] = UCB0RXBUF;
while (!(UCB0IFG & UCTXIFG));
UCB0TXBUF = 0x00;
while (!(UCB0IFG & UCRXIFG));
RES[5] = UCB0RXBUF;
while (!(UCB0IFG & UCTXIFG));
UCB0TXBUF = 0x00;
while (!(UCB0IFG & UCRXIFG));
RES[6] = UCB0RXBUF;
while (!(UCB0IFG & UCTXIFG));
UCB0TXBUF = 0x00;
while (!(UCB0IFG & UCRXIFG));
RES[7] = UCB0RXBUF;

  while(UCB0STAT & UCBUSY);           //SPI 如果UCBUSY=0 閒置  如果UCBUSY=1 USCI 正在接受或傳輸
 
  _EINT();
 
  P2OUT |= ~RESET_BT;
 
  while(1)                              //把 NOSTOP 和 STOP_AD 包含住
  {
   while(rx_on==0);                     //rx_on=0 留在迴圈  rx_on不等於0 離開迴圈
   rx_on = 0;
   if(rx_data==0xff) goto NOSTOP;       //電腦透過RS232 UART 傳開始字元 FF 給UART RX BUFFER
   goto STOP_AD;
     
NOSTOP:
   header = 0;
   P2OUT |= START;                       //START=1 開始做ADC轉換
 
   while (!(UCB0IFG&UCTXIFG));           // RDATAC
   UCB0TXBUF = 0x10;
 
   while(1)                       //進入NOSTOP迴圈後 便一值讀出ADC資料 直到UART 中斷為止(STOP_AD)
   {
    while((P2IN & DRDY_0));       //P2.1 DRDY_0 是否為LOW ?   如果為LOW 則跳出迴圈(ADC資料準備好了)
 
    for (i = 0; i < 3; i++)      // Read Status register  會先傳狀態暫存器  總共三筆 3*8=24BITS
    {
     while (!(UCB0IFG&UCTXIFG));                   
     UCB0TXBUF = 0x00;
 
     if(UCB0STAT & UCOE)
     {
      while (!(UCB0IFG&UCRXIFG));
      STAT0[0] = UCB0RXBUF;
     }
 
     while (!(UCB0IFG&UCRXIFG));
     STAT0[i] = UCB0RXBUF;                //i=0,1,2 三筆狀態資料
    }
 
    for (i = 0; i < 6; i++)       // Read Channel data  再傳CH值 ADS1291 2CH *24BITS=48BITS 一次傳8BITS
    {
     while (!(UCB0IFG&UCTXIFG));            
     UCB0TXBUF = 0x00;
 
     while (!(UCB0IFG&UCRXIFG));         //ADS:MSB  UART:LSB SPI:MSB
     RESU0[i] = UCB0RXBUF;
    }
    
    RESU0[2]=RESU0[2] & 0xFE;                     
    RESU0[2]=RESU0[2] | header;        
    header++;                     
    if ( header == 2 ) header = 0;
    
    for (i = 0; i < 3; i++)              // Send Channel data to BT  傳一個CH的DATA  只有傳CH1 DATA
    {
     while (!(UCA0IFG&UCTXIFG));         // USCI_A0 TX buffer ready?
     UCA0TXBUF = RESU0[i];               // i=0,1,2
     if(rx_on>0 && rx_data==0x00) goto STOP_AD;    //如果發生UART中斷 命令停止ADC取樣 則rx_on大於0 且 rx_data=0x00
    }
    while(UCA0STAT & UCBUSY);
    rx_on = 0;
   }                                              //繼續 NOSTOP While(1) 迴圈
STOP_AD:
   rx_on = 0;                           
  }
}

#pragma vector=USCI_A0_VECTOR
__interrupt void USCI_A0_ISR(void)    //P997 UART 中斷   猜想是電腦透過RS232 UART傳資料給RX Buffer 造成RX中斷
{
   rx_data = UCA0RXBUF;               //UART 使用 FF當作開始字元  00當作結束字元
   rx_on++;
}



can anyone explain why after i add  for (i = 0; i < 10; i++);  this delay when i wrote ADS1291 register then i can write/read ADS1291 register correctly?

and did i have something wrong with ADS1291 register setting?

and at the end. i sent those converted data by Bluetooth using 921600 baudrate. 

and accept those data by Labview.

My Ads1291 IN1P is connetted to the output of analog amp including one INA and OPA  and shift the signal to 1.5V.

my total analog amp gain = 3315

and i have already check my analog part, which is perfect.

 here are the outcome i got from ADS1291.

 

100mVPP 5HZ sin wave

100mVPP 10HZ sin wave

200mVPP 5HZ sin wave



200mVPP 10HZ sin wave

300mVPP 5HZ sin wave

300mVPP 10HZ sin wave

so have anyone know why i got this outcome?

are there any problem about my Firmware or my circuit?

Needs your help.

thanks for all of you.



  • Mr Shen -

    Have you noted the decode times for the Multi-byte commands (see page 10 and 37-38 of the datasheet).   When you run at a faster clock, you may be violating the decode time which is why the delay may work.

  • yes i notice that.

    but even i can write/read the ADS1291 successfully

    i still can't read the correct converted data from ADS1291.

    do you have any idea why ?

    thank you very much

  • Mr Shen - 

    A couple of questions -

    1.  When you read back the data and get "bad" data, what indicates to you that the data is not valid?  The reason for the question is that perhaps the data is valid and the device is not configured the way you are expecting?  You might want to verify the settings, especially if you are reading and writing registers correctly.

    2. when you communicate with the device, are you doing the 24bit transfers all at once or in multiple chunks (ie 3 x 8bits -> see Figure 45/46 in datasheet)?   You might also note the Serial Clock (SCLK) section in the applications section of the data sheet to make sure the SCLK requirements are correct.

  • HI Greg.

    1. i am using function generator to sent a sin wave and then have the singal divided by 1000 .

    and the divided singal go threw an analog amplifer . which totally gain=3310

    and then the amplifed singal connected to ADS1291 IN1P .

    i have already check the analog part . the analog signal is ok.

    should i post my whole circuit include the analog part to you?

    and my ADS1291 registers settings are

    CONFIG1 0x03

    CONFIG2 0xA0

    Lead-Off Control Register 0x10

    CH1     0x10

    CH2     0x81

    LOFF_STAT  0x40

    RESP1 0x02

    i am only using the A/D function.

    did i miss any register setting? or have some registers setting wrong?

    and i already check all the register are writen/read correctly.

     

    2. sorry i really don't know what " doing the 24bit transfers all at once or in multiple chunks " this mean.

    can you explain more detail to me?

    thank you Greg 

  • Mr Shen -

    The settings appear to be correct; so you are probably good there.

    Regarding #2, (referring to Fig 45/46)... in our evaluations, usually divide the write/read back up into 8 bit chunks.  ie Instead of doing a 24bit continuous SCLK, you can do a 8bit SCLK transfer x 3 to get all 24bits.  This helps out with some of the timing requirements.

    One additional question, have you actually probed your input signal to verify that the input to the ADC is OK and not distorted or not what you would expect?  From your statements, a gain of 3315 seem VERY high, so we want to make sure that there isn't a problem there.  Also, since you are running the part at the lower Vref range (2.4V), make sure that you signal is not greater than +/-2.4V.

  • hi Greg. thank you.

    Sorry. i am not good at coding .  Can i post my retrieving data part of Firmware and help me to separate 24bit continuous SCLK into 3x 8 bit continuous SCLK?

    and the second question.

    Yes. i have already probe the output of analog part. 

    and i just come up a question in my mind.

    because my common voltage is 1.5V . so that means  the Maxima amplitude of the sin wave input to ADS1291 = 2.4-1.5=0.9V?

      thanks a lot