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.

ADS1271 Interface

Other Parts Discussed in Thread: ADS1271

Dear Sir,

               I am interfacing  ADS1271 for one of my Automation project using PIC IC. I am Getting very unstable Counts which fluctuates in 10 lakhs and its not getting saturated with Vref also.

I have been working for long time. I am using High Resolution Mode, SPI interface. But the DRDY is coming inverse with ref to datasheet. I could not find the problem.

Since its time bound project pl guide me at the earliest. Here with I attach my shematic and Signal images and code.

4572.ads1271.pdf

2425.ADC.c
/*

	Project Name 	: Square Wave Function Gen
	Hardware Dev.	: Vinayagam/Radha
	Software Dev.	: Radha

	Description :
	--------------
    This Program Get the user input for frequncey OP and Gen op in RB3

*/

#include<htc.h>
#include<stdio.h>
#include<stdlib.h>


#define LD4  RB5
#define LD3	 RB4
#define LD2	 RB3
#define LD1	 RB2


#define LCD_RW RC0
#define LCD_RS RB1
#define LCD_CS RB0

#define AD_SCLK RA0
#define AD_SYN	RA1
#define AD_DRDY RA4
#define AD_SDATA RA5

__CONFIG(0x0FE4);			//07e4
//  _CONFIG2(0x08FF);

// Variables  // 
signed long ADCSampleVal;
unsigned char TMPSTR[30];
/*
union {
 	struct {
		 unsigned  BIT0             : 1;
         unsigned  BIT1             : 1;
         unsigned  BIT2             : 1;
         unsigned  BIT3             : 1;
         unsigned  BIT4			    : 1;	
         unsigned  BIT5             : 1;
         unsigned  BIT6             : 1;
         unsigned  BIT7             : 1;
    	  };
		   unsigned char DISPDATA;

}DOT_DATA;
*/

union {
	struct {
		unsigned char LcdBit0 : 1 ;
		unsigned char LcdBit1 : 1 ;
		unsigned char LcdBit2 : 1 ;
		unsigned char LcdBit3 : 1 ;
		unsigned char LcdBit4 : 1 ;
		unsigned char LcdBit5 : 1 ;
		unsigned char LcdBit6 : 1 ;
		unsigned char LcdBit7 : 1 ;
	} LCDbit ;
	unsigned char all ;
}LCDDATA ;

unsigned char T_DATA;
unsigned char CHARBUF[5];
unsigned char TMPCHBUF[6];
unsigned char DelayOver =0;
unsigned char RXDATA= 0;
unsigned char Count = 0;
unsigned long Com_DlyCount=0;


bit TMPD_DATA;
bit TXBUFEMPTY;
bit RXPRESENT;
bit STARTBYTE = 0;
bit ENDBYTE = 0;
bit NO_COMDATA = 0;
bit UPDATE = 0;
bit STARPRV_FLAG = 0;


void interrupt ISR()
{
  // Serial Int Function
  if(TXIF)
	{
	    TXIF = 0;
		TXIE=0;
		TXBUFEMPTY = 1;		
	}

  if(RCIF)
  {		
	if(RCREG== '%')Count=0;

	TMPCHBUF[Count++] =RCREG;
	if(Count>4)
	{
      if((TMPCHBUF[0]=='%') && (TMPCHBUF[4]=='$'))
	  {
        ENDBYTE=1; 
		Com_DlyCount = 0;
	  }

	  Count=0;
	}
  }


  if(TMR1IF)
  {

   DelayOver = 1;
   if(++Com_DlyCount > (62000 * 2)) // 5 Sec
   {
	 NO_COMDATA=1;
	 
   }   
 
 /*  if(UPDATE)
   {
     if(DISPSCAN >= 4)DISPSCAN = 0;BYTE_NO =0;BIT_DATA=0;

	 if(BYTE_NO >= 16)
	 {
	   BYTE_NO = 0;
	   BIT_DATA = 0;

	   DISPSCAN++;
	   
	   ENABLE = 1;
	   NOP();

	   LATCH = 1;
	   NOP();
	   LATCH = 1;
	   NOP();
	 }

	 if(DISPSCAN==0){ LOW_ADD=0; LOWST_ADD =0;}
	 else if(DISPSCAN==1){LOW_ADD=1; LOWST_ADD =1;}
	 else if(DISPSCAN==2){LOW_ADD=0; LOWST_ADD =1;}
	 else if(DISPSCAN==3){LOW_ADD=1; LOWST_ADD =0;}
	
	 ENABLE = 0;
	 NOP();
	 
	 if(BIT_DATA >=8) BIT_DATA=0; BYTE_NO++;
	  
	 DOT_DATA.DISPDATA = DISPBUFFER[((DISPSCAN * 16 ) + BYTE_NO)]; // Locate the data
     DOT_DATA.DISPDATA = ~DOT_DATA.DISPDATA;
	 
	 // Have to edit in fut

	 if(BIT_DATA==0)TMPD_DATA = DOT_DATA.BIT0;
 	 else if(BIT_DATA == 1) TMPD_DATA = DOT_DATA.BIT1;
	 else if(BIT_DATA == 2) TMPD_DATA = DOT_DATA.BIT2;
	 else if(BIT_DATA == 3) TMPD_DATA = DOT_DATA.BIT3;
	 else if(BIT_DATA == 4) TMPD_DATA = DOT_DATA.BIT4;
	 else if(BIT_DATA == 5) TMPD_DATA = DOT_DATA.BIT5;
	 else if(BIT_DATA == 6) TMPD_DATA = DOT_DATA.BIT6;
	 else if(BIT_DATA == 7) TMPD_DATA = DOT_DATA.BIT7;

	 CLK = 0;
	 NOP();	 

  	 D_DATA = TMPD_DATA;
	 NOP();	
	 
	 CLK = 1;
     NOP();
    
     BIT_DATA++;	  
	
   }

*/
   TMR1IF = 0;
   TMR1H = 0xFF;
   TMR1L = 0x60;
   T1CON = 0x41;

   }

}

void Delay100Micro(unsigned long value)
{
  
  for(;value>0;value--)
  {

	DelayOver = 0;
	while(!DelayOver);
    
  }
}

void Delay_ms(unsigned char dval)
{
   for(;dval>0;dval--)
   {	
     Delay100Micro(100);//10
   }
}

void Delay1Sec(unsigned char dval)
{
   for(;dval>0;dval--)
   {	
     Delay100Micro(10000);
   }		
}


 void XmitData(unsigned char Txdata)
{
 // while(!TXBUFEMPTY);					//Check Buffer is empty B4 sending the data
  TXREG = Txdata ;
  while(TXBUFEMPTY);					// Wait till data sent
}


void txn()
{
  unsigned char k;

	for(k=0;k<5;k++)
	{
		if(TXBUFEMPTY)
		{
			TXBUFEMPTY=0;
			TXIE=1;
		//	TXREG=DISPBUFFER[k];
		}
	}
	TXIE=1;
	TXREG=' ';
}


unsigned char getch() {
	/* retrieve one byte */
	while(!RCIF)	/* set when register is not empty */
		continue;
	return RCREG;	
}

void putch(unsigned char byte) 
{
	/* output one byte */
	while(!TXIF)	/* set when register is empty */
		continue;
	TXREG = byte;
}



void InitLCDPortIO(void)
{
 
  TRISB	 &= 0;		
}



void LCD_Strobe(void)
{   
  	LCD_CS=1;
	Delay_ms(1);
	LCD_CS=0;
}
void Write2Lcd(unsigned char LData2Write)
{
  
	Delay_ms(1);
	
	LCDDATA.all = LData2Write;

	LD1 = LCDDATA.LCDbit.LcdBit4;NOP();
	LD2 = LCDDATA.LCDbit.LcdBit5;NOP();
	LD3 = LCDDATA.LCDbit.LcdBit6;NOP();
	LD4 = LCDDATA.LCDbit.LcdBit7;NOP();
	
	
	LCD_Strobe();

	LD1 = LCDDATA.LCDbit.LcdBit0;NOP();
	LD2 = LCDDATA.LCDbit.LcdBit1;NOP();
	LD3 = LCDDATA.LCDbit.LcdBit2;NOP();
	LD4 = LCDDATA.LCDbit.LcdBit3;NOP();


	LCD_Strobe();


}


void ClearLcd(void)
{
	LCD_RS = 0;
	Write2Lcd(0x1);
	Delay_ms(2);
}


void InitLCDDisplay(void)
{

//initialises the display

	InitLCDPortIO();

	LCD_RW	=0;	NOP();
	
	LCD_RS	=0;	NOP();
    LCD_CS 	=0;	NOP();

	Delay_ms(15);	// wait 15mSec after power applied,


    LCDDATA.all = 0x30;
	LD1 = LCDDATA.LCDbit.LcdBit4; 	NOP();
	LD2 = LCDDATA.LCDbit.LcdBit5;	NOP();
	LD3 = LCDDATA.LCDbit.LcdBit6;	NOP();
	LD4 = LCDDATA.LCDbit.LcdBit7;	NOP();


	LCD_Strobe();
	
    Delay_ms(5);

	LCD_Strobe();
	Delay_ms(1);	

	LCD_Strobe();	
	Delay_ms(1);	

	

	LCDDATA.all = 0x20;
	LD1 = LCDDATA.LCDbit.LcdBit4; NOP();
	LD2 = LCDDATA.LCDbit.LcdBit5; NOP();
	LD3 = LCDDATA.LCDbit.LcdBit6; NOP();
	LD4 = LCDDATA.LCDbit.LcdBit7; NOP();	// Four bit mode


	LCD_Strobe();

    Write2Lcd(0x28);
	Write2Lcd(0x14);
	Write2Lcd(0x0C);
   // Write2Lcd(0xF);
	ClearLcd();			// Clear screen
	Write2Lcd(0x6); 	// Set entry Mode
	
}


void lcd_puts(const char * s)
{
	LCD_RS = 1;			// write characters
	NOP();
	LCD_RW = 0;
	NOP();
	while(*s)
	Write2Lcd(*s++);
}


/* write one character to the LCD */

void lcd_putch(char c)
{

	LCD_RS = 1;	NOP();		// write characters
	LCD_RW = 0; NOP();

	Write2Lcd( c );
}


/*
 * Go to the specified position
 */

void lcd_goto(unsigned char pos)
{
	LCD_RS = 0;NOP();
	if(pos < 16) Write2Lcd(0x80 |pos);
	else Write2Lcd(0xc0 |(pos - 16));
}



void ReadADCCounts(void)
{
  unsigned char ADI;
  signed long ADCOUNTSDATA;
  
  	ADCOUNTSDATA = 0;
  	ADCSampleVal = 0;

    AD_SCLK = 1;
  	AD_SYN = 1;
    AD_DRDY == 1;
    Delay_ms(1);

 //	AD_SYN = 0;
 //   Delay_ms(1);
  //  AD_SYN = 1;				//START Conversion
	
    AD_SDATA = 1;

  	while(AD_DRDY == 1);
	Delay100Micro(10);
	
  
  	for(ADI = 0; ADI < 24;ADI++)
  	{  
   		AD_SCLK = 1;
    	NOP();
		NOP();
		NOP();
		NOP();
		NOP();
		NOP();

    	AD_SCLK = 0;
		NOP();
		NOP();
		NOP();
		NOP();
		NOP();					// Falling Edge

    	if(AD_SDATA)ADCOUNTSDATA |= 1;
		else		ADCOUNTSDATA |= 0; 
            
   		if(ADI < 23) ADCOUNTSDATA <<= 1; 		// Dont shift 24th Bit
           
  	}
    
    ADCSampleVal = ADCOUNTSDATA;

}


void FillBuf (unsigned char *bufptr, unsigned int noofchars, unsigned char bufdata)
{
  for (; noofchars > 0; noofchars--)
  {
    *bufptr = bufdata;
	bufptr++;
  }
}


void Long2String (long intval, unsigned char decimals)
{
  long divisor;
  unsigned char xx;
  unsigned char *tmpptr;

  FillBuf (&TMPSTR[0], 8, ' ');
  tmpptr = &TMPSTR[0];
  if (intval < 0) *tmpptr = '-'; else *tmpptr = ' ';	//First digit -/+
  tmpptr++;

  intval = labs (intval);
  intval %= 10000000;									//Make 7 digits
  divisor = 1000000;

  for (xx=0; xx<(6-decimals); xx++)
  {
    if ((intval / divisor) > 0) break;					//Make Leading Spaces insted of Zeros
	*tmpptr = ' ';
	tmpptr++;
	intval %= divisor;
	divisor /= 10;
  }

  for (; xx<7; xx++)
  {
    if ((decimals > 0) && ((7-xx) == decimals))
	{
	  *tmpptr = '.';									//Place Decimal Point
	  tmpptr++;
	}

    *tmpptr = (intval / divisor) | 0x30;
	tmpptr++;
	intval %= divisor;
	divisor /= 10;
  }
  if (decimals == 0) TMPSTR [8] = '\x0'; else TMPSTR [9] = '\x0';	//*tmpptr = '\x0';

//  return (&TMPSTR [0]);
}

void ADC_Init(void)
{
  
	TRISA0 = 0; //OP  SCK
	TRISA1 = 0; //OP  SYN

	TRISA4 = 1;	//IP DRDY
	TRISA5 = 1; //IP DOUT

}

void main()
{
	unsigned char i;
	unsigned char Avgcnt;
    signed long ADC_AVGCNTS;
   	
	GIE = 1;
	PEIE = 1;
	TXIE = 1;
	RCIE = 1;

	INTE = 0;
	
	OSCCON =0xFB; 				//0xFB;

//	OSCCON = 0xF2;
	OSCTUNE = 0x7F;				//0x1F;
	for(i =0; i<250;i++);	//warm up delay
	
	TRISA = 0x00;			//configuers as op	
	ANSELA = 0x00;
	TRISB = 0x00;			//configuers as op	
	ANSELB = 0x00;
	TRISC |= 0x00;			// SET Key as Input

 //   LCD_Init();
 

// Timer1 over flow Init

    TMR1IE = 0x01;
	TMR1H = 0xFF;			// F9
	TMR1L = 0x60;	 		// C0	
	T1CON = 0x41;			// 41
	T1GCON = 0;
	
	TRISC6 = 1;
	TRISC7 = 1;

	BAUDCON = 0x00;
	SPBRGH = 0x00;
	SPBRG = 103;				// 16 mhz 25 for 4 mhz
	TXSTA = 0x24;
	RCSTA = 0x90;

	TRISB = 0;
	ANSELB = 0;
	WPUB =0x00;

    InitLCDDisplay();
	ADC_Init();
	
	ClearLcd();
	lcd_goto(0);
	
    AD_SYN = 1;

	lcd_puts("Adc Test..");
//	Delay_1s(1);
    ClearLcd();
	lcd_goto(0);    
	lcd_puts("C:");
  
 do{
   
    ADC_AVGCNTS = 0;
    ADCSampleVal=0;

    for(Avgcnt = 0;Avgcnt < 100;Avgcnt++)
    {
      	ReadADCCounts();
      	ADC_AVGCNTS+= ADCSampleVal;
    }    
	
      
    ADCSampleVal = ADC_AVGCNTS /100;

 	ADCSampleVal = ADCSampleVal/6;

    Long2String(ADCSampleVal,0);
    lcd_goto(2);       	
	lcd_putch(TMPSTR[0]);
	lcd_putch(TMPSTR[1]);
	lcd_putch(TMPSTR[2]);
	lcd_putch(TMPSTR[3]);
    lcd_putch(TMPSTR[4]);
    lcd_putch(TMPSTR[5]);
    lcd_putch(TMPSTR[6]);
	lcd_putch(TMPSTR[7]);

	Delay_ms(10);
 //   Delay_ms(10);
//	Delay_ms(10);
//	Delay_ms(10);
//	Delay_ms(10);  
     
    }    
   
	while(1);


 
	

}

  • Radha,

    Can you tell us more about your scope shots?  Where do you have your scope probes connected for each picture?

    Best regards,

    Bob B

  • Dear Bob,

                      Thanks for your interest. In attached Pictures. The First one is DRDY signal probe kept at pin DRDY of ADS1271.

    The second on SCLK of ADS1271 ,the Third one is SDATA kept at DOUT pin of ADS1271. Pl give me the valuable suggestion at the earliest.

    Regards

    Radha

  • Radha,

    It is a little hard to tell for sure, but it appears from the second picture and from the code that SCLK is dwelling high before DRDY goes low.  SCLK must dwell low as data will shift at falling edge of SCLK.  In this case you will miss the most significant bit.  With bit-bang code you should read the input after SCLK transitions from low to high ( or SCLK at high state.)

    Best regards,

    Bob B

  • Dear Bob,

                      I have tried SCLK as per your reply but still the fluctuations are there. Can u look into my code or ado you any sample code to try at earliest.

    Regards

    Radha

  • Radha,

    I'm sorry I don't have any example code for PIC microcontrollers.  Please send me a scope picture of the communication with SCLK and DOUT on the same scope plot so that I can verify communications.

    Best regards,

    Bob B

  • Bob,

              Its OK u don't have code for PIC Controller.I just need procedure of CLK and DATA reading and other signal condition. Send me if u have for any other controller.

      Here with I attach my Screen shot took on same shot for CLK and DATA . The Top one is data and Bottom one is CLK

    start of DATA

    END of DATA.

    Kindly check and reply at the earliest

    Regards

    Radha

  • Can U check out my code and conclude?

  • Radha,

    Notice how erratic the clock pulses are? These pulses should be very clean and uniform.  In the clocks that appear slightly darker, I suspect that there is an issue with stability in the clock signal itself.  These are probably two quick clock transitions, and they must conform to the timing constraints of the timing diagram in the datasheet.

    You need to analyze why some clock pulses are very long as compared to others.  Do you have interrupts that are taking place that are inferring with consistency?  You also need to zoom in and verify that each clock pulse is valid.

    Best regards,

    Bob B

  • Bob,

             Ya. I have disable the interrupts wen clocking which makes the pulse clean and uniform.

    Still the issue is same.

    1. Counts fluctuates in lakhs.

    2. Its not saturated with Vref. still oscilatting more than vref. means reading is invalid?

    3. DRDY is inverse wrf to datasheet.

    In data sheet SPI Interface ,SCLK data shfits in falling edge. User should read at rasing edge is given. make clock zero wen data read.

    which mean for each bit?

    can u procedure me the reading / interfacing?

    Regards

    Radha.P

  • Radha,

    Now that you have a clean scope picture, you need to verify that the count is really moving as much as you are saying.  What you have said is that there is instability with about 12 to 13 bits.  Do you really see that much movement on the scope?

    If your reference is noisy or unstable, then you will see fluctuations in your result.  You may want to place a capacitor at the ADS1271 (or very close to it) across the VrefP and VrefN pins. 

    I suspect you have an issue with number conversion.  You say you cannot reach saturation.  Does the scope picture show this?  It is not possible to get a number above VREF unless you are misinterpreting the number.  The output code is binary two's complement. If the most significant bit is high, then the number is actually a negative number.  Are you properly interpreting and signing your number appropriately?  You are using a 32 bit signed value (long) in your program and reading in data that is 24 bit.  If the MSB is high in the data result captured, then the value is negative and this means that the most significant byte of the long (ADCOUNTSDATA) must also be high for the value to be considered a negative value.

    DRDY will appear differently depending on whether you are reading the data or not reading the data.  When you are reading the data, the DRDY will appear as shown in the datasheet.  If you are not reading data, you will see DRDY dwelling low most of the time with a short pulse from low to high to low which means that new results are being posted when DRDY goes high and are available with DRDY goes low.  The big thing to remember is the transition from high to low which signals new data is available.

    As far as procedure for communication this will depend a lot on the controller.  Generally I prefer to use a hardware peripheral instead of manually controlling the port pins for communication (bit-banging.)  Hardware peripherals will work independently of your control loop and will make clocking problems less of an issue.  If your PIC controller has a SPI hardware peripheral I would suggest using that over bit-banging.

    Best regards,

    Bob B

  • Dear Sir,

                     Thanks for your input so far.Pl clear this also. I have checked the number conversion there is no issue in that. i Have found if i wait for DRDY to Low and then to High

    while(DRDY);

    while(!DRDY) loop counts is stable for 22 bit also. but change in mv miss 2 or 3 readings.

    If i wait only to low while(DRDY) then counts fluctuates in high range. Can u guide me what to do?

    Regards

    Radha.P

  • Sir,

            The Last two digits are same in reading for data .What would be the reason?

  • Radha,

    The best way to know when data is available is by using an interrupt driven system to capture data as soon as DRDY transitions from high to low.  The problem with polling, especially when it involves a processing loop, is that the data can be missed or only partially read.  On page 25 of the datasheet under the description for DRDY/FSYNC and just above Figure 63 it says "The new data is loaded within the ADS1271 one CLK cycle before DRDY goes low.  All data must be shifted out before this time to avoid being overwritten."

    At higher data rates you have a very small window to capture the data as you must do so within the specified constraints.  A certain amount of machine cycles are spent just to poll for a change in DRDY.  Also, while polling you can do nothing else or you risk having corrupted data.  In an interrupt driven system you can always generate the call for reading as soon as the interrupt flag is set.  In this way the data read is very consistent, and will be read out within the correct time frame.  It also allows you to process other code instead of locking up your process in a 'while' loop.  You will have much better success using an interrupt driven system.

    Best regards,

    Bob B

  • Sir,

            My interface working with low speed, SPI currently not available in my chip.Let me try for future design but still. Basically it should work right?

    Any how If i use MCLK 2 mhz overall my conversion time is 80ms. which is 5samples per second very low. If change mclkto 20MHZ the same code not working and no improvement in cnv time also. what is the max speed i can achieve?  How to improve the speed?

    Regards

    Radha

  • Radha,

    That is exactly the problem I'm talking about. Even if your controller does not have a hardware SPI peripheral it should have interrupt capability. Even then you may have problems as the micro must take a specific amount of machine cycles to complete the read of the data. If while you are polling DRDY and if you start your read cycle too late you may start to read the conversion results from the next conversion. The two results get mixed together and the data is invalid.

    Best regards,

    Bob B