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.

ADS1248: ADS1248 is not working and receiving garbage ADC value

Part Number: ADS1248

Hi,

I am using ADS1248 in one of our project to convert Analog 4-20mA signal to Digital value, the problem i am facing is I am unable to receive ADC value correct to Pin voltage. I dont think it is working and I am getting garbage value anything unrelated to applied voltage/current. I dont know whether is ADS1248 configuration problem or hardware related but i need support to understand and troubleshoot the issue.

NOTE: i had one mistake in Schematic , we didnt add capaictor at Vrefcom and vrefout earlier but that is now added, but still same result

I here by attach ADS1248 driver files, Schematic Part, and sample code.

AIN% is grounded(not shown in schematic)

// read ADC function
int32_t ADS1248_sample_raw( )
{
	int32_t res = 0;
	unsigned int Temp = 0;

	// test spi
	Temp = ADS1248GetIntRef();

	Temp = ADS1248_DRDY_OFF;
	ADS1248WriteRegister(ADS1248_10_IDAC0, 0x01, &Temp);

	// ref v channels
	Temp =  (ADS1248_INT_VREF_ON ) | (ADS1248_INT_REF0) | (ADS1248_MEAS_NORM);
	//ADS1248SetVoltageReference(Temp);
	ADS1248WriteRegister(ADS1248_2_MUX1, 0x01, &Temp);

	// Setup gain and sample rate
	ADS1248SetGain(ADS1248_GAIN_2 ) ;

	ADS1248SetDataRate(ADS1248_DR_80);
	//Temp = ADS1248_DR_320|ADS1248_GAIN_1;
	//ADS1248WriteRegister(ADS1248_3_SYS0, 0x01, &Temp);

	Temp = ADS1248GetDataRate();

	// read CH 3 wrt CH5
	// Choose channels
	ADS1248SetChannel (0, ( ADS1248_AINN3) );
	ADS1248SetChannel (1, (ADS1248_AINP5) );

	ADS1248_startSingle();

	delayMS(500);
	res = ADS1248ReadData();
	float tempV = res;

	tempV *= 2.048; // internal ref 2.048
	tempV /= 8388608; // 2^23
	tempV *= 1000; // value in mV

	return res;
}

// freertos task to read ADC

static void vLEDTask1(void *pvParameters) {
	bool LedState = false;
	int Temp;
	InitSPI();
	InitDevice();						// Initializes the SPI port pins as well as control
	InitConfig();
	ADS1248SetStart(0);
	tmp_adc = ADS1248GetID();
	tmp_adc = ADS1248GetChannel(0);

	while (1) {
		LedState = (bool) !LedState;

		/* About a 100ms on/off toggle rate */
		vTaskDelay(100/portTICK_RATE_MS );
		//Temp = ADS1248GetDataRate();
		ADS1248_sample_raw();
	}
}
// Toggle START Pin for conversation
void ADS1248_startSingle(){

	int relVal = 1;
	ADS1248SetStart(1);
	delayMS(100);
	ADS1248SetStart(0);

}

ads1248.h

2867.ads1248.c
/*
 * ads1248.c
 *
 * ADS1248 device functions
 *
 * Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/
 *
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *
 *    Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 *    Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the
 *    distribution.
 *
 *    Neither the name of Texas Instruments Incorporated nor the names of
 *    its contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
*///******************************************************************************
//   ADS1248 Function File for Demo Functions
//
//   Description: SPI master talks to SPI slave (ADS1248) using 4-wire mode. LaunchPad
//   is used for this example.
//   ACLK = n/a, MCLK = SMCLK = DCO ~24MHz, BRCLK = SMCLK/7
//
//
//
//                                         MSP430F5529
//                                      -----------------
//                                     |             P1.3|<- Data Interrupt (DRDY)
//                                     |                 |
//                             START <-|P6.0         P6.2|-> Device Select (CS)
//                                     |                 |
//                             RESET <-|P6.1         P3.0|-> Data Out (UCB0SIMO -> DIN)
//                                     |                 |
//                                   <-|P1.6         P3.1|<- Data In (DOUT -> UCB0SOMI)
//                                     |                 |
// Serial Clock Out (UCB0CLK - SCLK) <-|P3.2         P2.7|->
//                                     |                 |
//                 I2C SCL (UCB1SCL) <-|P4.2         P8.1|->
//                                     |                 |
//                 I2C SDA (UCB1SDA)<>-|P4.1         P2.6|->
//                                     |                 |
//                                     |             P3.7|->
//                                     |                 |
//
//
//******************************************************************************

/*
 * ======== Standard board includes ========
 */

#include "board.h"
#include "lpc_utils.h"
#include "ads1248.h"


#define BUFFER_SIZE                         (0x100)

static SPI_CONFIG_FORMAT_T spi_format;
static SPI_DATA_SETUP_T spi_xf;
static uint8_t spi_tx_buf[BUFFER_SIZE];
static uint8_t spi_rx_buf[BUFFER_SIZE];

static uint8_t spi_rx_byte = 0;

void InitSPI(void)
{
#if defined (__MSP430F5529__)
	UCB0CTL1 |= UCSWRST;						// Hold peripheral in reset
	UCB0CTL0 = UCMST + UCSYNC + UCMSB;			// SPI master, synchronous
	UCB0CTL1 = UCSSEL_2 + UCSWRST;				// Use SMCLK for bit rate clock and keep in reset
	UCB0BR0 = 14;								// SMCLK/12 = SCLK (2MHz)
	UCB0CTL1 &= ~UCSWRST; 						// Release peripheral for use
#elif defined (PART_TM4C1294NCPDT)
	extern uint32_t sysfreq;
	uint32_t dataRx;

	SysCtlPeripheralEnable(SYSCTL_SSI);
	#ifdef DIFFERENT_CS_PORT
		GPIOPinTypeGPIOOutput(NCS_PORT, ADS1248_CS);
		//nCS_DIS;
	#endif
	GPIOPinConfigure(ADS1248_SCLK);
	GPIOPinConfigure(ADS1248_DOUT);
	GPIOPinConfigure(ADS1248_DIN);
	GPIOPinTypeSSI(SPI_GPIO_PORT, SPI_GPIO_PINS );
	SSIConfigSetExpClk(SPI_BASE, sysfreq, SPI_MOTO_MODE, SPI_MODE, SPI_SPEED, SPI_WORD_SIZE);
	SSIEnable(SPI_BASE);
	// should happen AFTER SPI init.
	SSIAdvModeSet(SPI_BASE, SSI_ADV_MODE_READ_WRITE);
	SSIAdvFrameHoldEnable(SPI_BASE);
	// clear out any 'junk' that may be in the SPI RX fifo.
	while(SSIDataGetNonBlocking(SPI_BASE, &dataRx));
#endif

#ifdef BOARD_NXP_LPCXPRESSO_1769
	 /* Initialize SSP0 pins connect
		 * P0.15: SCK
		 * P0.16: SSEL
		 * P0.17: MISO
		 * P0.18: MOSI
		 */

		Chip_IOCON_PinMux(LPC_IOCON, 0, 16, IOCON_MODE_PULLUP, IOCON_FUNC0);
			Chip_GPIO_WriteDirBit(LPC_GPIO, 0, 16, true);

		Chip_IOCON_PinMux(LPC_IOCON, 0, 15, IOCON_MODE_PULLDOWN, IOCON_FUNC3);
		Chip_IOCON_PinMux(LPC_IOCON, 0, 17, IOCON_MODE_INACT, IOCON_FUNC3);
		Chip_IOCON_PinMux(LPC_IOCON, 0, 18, IOCON_MODE_INACT, IOCON_FUNC3);

		/* SPI initialization */
		Chip_SPI_Init(LPC_SPI);
		spi_format.bits = SPI_BITS_8;
		spi_format.clockMode = SPI_CLOCK_MODE1;
		spi_format.dataOrder = SPI_DATA_MSB_FIRST;
		Chip_SPI_SetFormat(LPC_SPI, &spi_format);

		Chip_SPI_SetBitRate(LPC_SPI, 2000000);
#if LPC_BUFFERED_SPI
		spi_xf.fnBefFrame =  Board_SPI_AssertSSEL;
		spi_xf.fnAftFrame =  Board_SPI_DeassertSSEL;
		spi_xf.fnBefTransfer = NULL;
		spi_xf.fnAftTransfer = NULL;
		Chip_SPI_SetMode(LPC_SPI, SPI_MODE_MASTER);
#endif
#endif
}

void InitDevice(void)
{
#if defined (__MSP430F5529__)
	P3SEL |= ADS1248_DIN + ADS1248_DOUT + ADS1248_SCLK;
    P1SEL &= ~(ADS1248_DRDY);
    // define initial states
    P6OUT |= ADS1248_START;
    P6OUT |= ADS1248_CS;
    P6OUT |= ADS1248_RESET;
    // define inputs
    P1DIR &= ~(ADS1248_DRDY);                   // DRDY is an input to the micro
    P1IES |= ADS1248_DRDY;                      // and should be used as an interrupt to retrieve data
    // define outputs
    P6DIR |= ADS1248_START;
    P6DIR |= ADS1248_CS;
    P6DIR |= ADS1248_RESET;
#elif defined (PART_TM4C1294NCPDT)
    GPIOPinTypeGPIOOutput(START_PORT, ADS1248_START);  	// start
   	GPIOPinWrite(START_PORT, ADS1248_START, 0);
   	GPIOPinTypeGPIOOutput(RESET_PORT, ADS1248_RESET);  	// reset
   	GPIOPinTypeGPIOInput(DRDY_PORT, ADS1248_DRDY);  	// DRDY
   	GPIOIntTypeSet(DRDY_PORT, ADS1248_DRDY, GPIO_FALLING_EDGE);   // GPIO_HIGH_LEVEL ?
   	GPIOPinWrite(RESET_PORT,ADS1248_RESET, ADS1248_RESET);
#endif

#ifdef BOARD_NXP_LPCXPRESSO_1769

	Chip_GPIO_SetPortDIROutput(LPC_GPIO, START_PORT, ADS1248_START);

#if USE_RESET_PIN
	Chip_GPIO_SetPortDIROutput(LPC_GPIO, RESET_PORT, ADS1248_RESET);
#endif

#endif
}

/*
 * ADS1248 Initial Configuration
 */
void InitConfig(void)
{
	//establish some startup register settings
	unsigned regArray[4];
	// Send SDATAC command
	ADS1248SendSDATAC();
	ADS1248WaitForDataReady(1000);
	ADS1248SendSDATAC();
	//write the desired default register settings for the first 4 registers NOTE: values shown are the POR values as per datasheet
	regArray[0] = 0x01;
	regArray[1] = 0x00;
	regArray[2] = 0x00;
	regArray[3] = 0x00;
	ADS1248WriteSequence(ADS1248_0_MUX0, 4, regArray);
	return;
}

/*
 * DRDY Polling Function
 * Timeout = 0 is wait until DRDY goes low no matter how long it takes, otherwise wait the specified number of cycles
 */
int ADS1248WaitForDataReady(int Timeout)
{
	/* This function shows a method for polling DRDY instead of using as interrupt function
	 * -- Note: this method is not used in the demo, but if we the method was switched to polling from the interrupt method,
	 * the desired port is PORT2 on the MSP430 as this demo is configured.
	 */
#if defined (__MSP430F5529__)
	if (Timeout > 0)
	{
		// wait for /DRDY = 1 to make sure it is high before we look for the transition low
		while (!(P1IN & ADS1248_DRDY) && (Timeout-- >= 0));
		// wait for /DRDY = 0
		while ( (P1IN & ADS1248_DRDY) && (Timeout-- >= 0));
		if (Timeout < 0)
			return ADS1248_ERROR; 					//ADS1248_TIMEOUT_WARNING;
	}
	else
	{
		// wait for /DRDY = 1
		while (!(P1IN & ADS1248_DRDY));
		// wait for /DRDY = 0
		while ( (P1IN & ADS1248_DRDY));
	}
#elif defined (PART_TM4C1294NCPDT)
	/* wait for nDRDY_REG to deassert as a known valid data */
	if (Timeout > 0)
	{
		// wait for /DRDY = 1 to make sure it is high before we look for the transition low
		while (!(nDRDY_REG) && (Timeout-- >= 0));
		// wait for /DRDY = 0
		while ( (nDRDY_REG) && (Timeout-- >= 0));
		if (Timeout < 0)
			return ADS1248_ERROR; 					//ADS1248_TIMEOUT_WARNING;
	}
	else
	{
		// wait for /DRDY = 1
		while (!(nDRDY_REG));
		// wait for /DRDY = 0
		while(nDRDY_REG);
	}
#endif

#ifdef BOARD_NXP_LPCXPRESSO_1769

#define nDRDY_REG Chip_GPIO_GetPinState(LPC_GPIO, 0, 17)

	// set PIN as Input again
	Chip_GPIO_SetPinDIRInput(LPC_GPIO, 0, 17);
	/* wait for nDRDY_REG to deassert as a known valid data */
	if (Timeout > 0)
	{
		// wait for /DRDY = 1 to make sure it is high before we look for the transition low
		while (!(nDRDY_REG) && (Timeout-- >= 0));
		// wait for /DRDY = 0
		while ( (nDRDY_REG) && (Timeout-- >= 0));
		if (Timeout < 0)
			return ADS1248_ERROR; 					//ADS1248_TIMEOUT_WARNING;
	}
	else
	{
		// wait for /DRDY = 1
		while (!(nDRDY_REG));
		// wait for /DRDY = 0
		while(nDRDY_REG);
	}

	// set IO pin as SPI MISO again
	Chip_IOCON_PinMux(LPC_IOCON, 0, 17, IOCON_MODE_INACT, IOCON_FUNC3);
#endif
	return ADS1248_NO_ERROR;
}

/*
 * Primary Low Level Functions
 */
void ADS1248AssertCS( int fAssert)
{
#if defined (__MSP430F5529__)
	// This example is using PORT6 for GPIO CS control, ADS1248_CS is defined in ads1248.h
	if (fAssert){				// fAssert=0 is CS low, fAssert=1 is CS high
		_delay_cycles(50);		// Must delay minimum of 7 tosc periods from last falling SCLK to rising CS
		P6OUT |=  (ADS1248_CS);
	} else
		P6OUT &=  ~(ADS1248_CS);
#elif defined (PART_TM4C1294NCPDT)
	if (fAssert){				// fAssert=0 is CS low, fAssert=1 is CS high
		SysCtrlDelay(100);		// Must delay minimum of 7 tosc periods from last falling SCLK to rising CS
		GPIOPinWrite(NCS_PORT, ADS1248_CS, 0xFF);
	} else
		GPIOPinWrite(NCS_PORT, ADS1248_CS, 0);
#endif

#ifdef BOARD_NXP_LPCXPRESSO_1769
	if (fAssert){
		Board_SPI_AssertSSEL();
	}else{
		Board_SPI_DeassertSSEL();
	}
#endif
}



void ADS1248SendByte(unsigned char Byte)
{
	char dummy;
#if defined (__MSP430F5529__)
	dummy = UCB0RXBUF;
	while(!(UCB0IFG&UCTXIFG));			// Make sure nothing is already in the TX buffer
	UCB0TXBUF = Byte;					// Send the passed Byte out the SPI bus
	while(!(UCB0IFG&UCRXIFG));			// Before returning wait until transmission is complete and clear the RX buffer
	dummy = UCB0RXBUF;
#elif defined (PART_TM4C1294NCPDT)
	HWREG(SPI_BASE + SSI_O_DR) = Byte;        			// set up data for the next xmit
	while(!(HWREG(SPI_BASE + SSI_O_SR) & SSI_SR_RNE));  // wait for data to appear
	dummy = HWREG(SPI_BASE+SSI_O_DR);         			// grab that data
#endif
#if LPC_SPI_BUFFERED

	spi_xf.cnt = 0;
	spi_xf.length = 1;
	spi_xf.pTxData = spi_tx_buf;
	spi_xf.pRxData = spi_rx_buf;

	Chip_SPI_RWFrames_Blocking(LPC_SPI, &spi_xf);
#else

	Chip_SPI_ReceiveFrame(LPC_SPI); // empty RX data register
	//Chip_GPIO_SetPinState(LPC_GPIO,0,16,0); // CS = low
	//TODO:

	Chip_SPI_SendFrame(LPC_SPI, Byte);	// write MSB
	while(!(Chip_SPI_GetStatus(LPC_SPI) & SPI_SR_SPIF));	// wait while tx complete
/*
	dummy = Chip_SPI_ReceiveFrame(LPC_SPI); // read MSB
	//TODO: COMMENT dEBUG

	Chip_SPI_SendFrame(LPC_SPI, inData[1]); // write LSB
	while(!(Chip_SPI_GetStatus(LPC_SPI) & SPI_SR_SPIF));	// wait while tx complete


	//todo:
	Chip_GPIO_SetPinState(LPC_GPIO,0,16,1);
	*/
	spi_rx_byte = Chip_SPI_ReceiveFrame(LPC_SPI); // read lSB
#endif
}

unsigned char ADS1248ReceiveByte(void)
{
	unsigned char Result = 0;
#if defined (__MSP430F5529__)

	while(!(UCB0IFG&UCTXIFG));			// Make sure nothing is currently transmitting
	UCB0TXBUF = ADS1248_CMD_NOP;		// Send out NOP to initiate SCLK
	while(!(UCB0IFG&UCRXIFG));			// Wait until all data is transmitted (received)
	Result = UCB0RXBUF;					// Capture the receive buffer and return the Result
#elif defined (PART_TM4C1294NCPDT)
	// MUST MUST MUST purge junk from fifo!!!!
	while(SSIDataGetNonBlocking(SPI_BASE, &junk));
	HWREG(SPI_BASE + SSI_O_DR) = ADS1248_CMD_NOP;		// Send out NOP to initiate SCLK
	while(!(HWREG(SPI_BASE + SSI_O_SR) & SSI_SR_RNE));  // wait for data to appear
	Result = HWREG(SPI_BASE+SSI_O_DR);         			// grab that data
#endif
	//Result = Chip_SPI_ReceiveFrame(LPC_SPI); // empty RX data register

	Chip_SPI_SendFrame(LPC_SPI, ADS1248_CMD_NOP);	// write MSB
	while(!(Chip_SPI_GetStatus(LPC_SPI) & SPI_SR_SPIF));	// wait while tx complete
	//delayMS(10);

	Result =  Chip_SPI_ReceiveFrame(LPC_SPI); // read MSB

	return Result;
}

/*
 * ADS1248 Higher Level Functions and Commands
 */
void ADS1248SendWakeup(void)
{
	// assert CS to start transfer
	ADS1248AssertCS(0);
	// send the command byte
	ADS1248SendByte(ADS1248_CMD_WAKEUP);
	// de-assert CS
	ADS1248AssertCS(1);
	return;
}

void ADS1248SendSleep(void)
{
	// assert CS to start transfer
	ADS1248AssertCS(0);
	// send the command byte
	ADS1248SendByte(ADS1248_CMD_SLEEP);

	/*
	 * CS must remain low for the device to remain asleep by command...otherwise bring START low by pin control
	 */
	return;
}

void ADS1248SendSync(void)
{
	// assert CS to start transfer
	ADS1248AssertCS(0);
	// send the command byte
	ADS1248SendByte(ADS1248_CMD_SYNC);
	// de-assert CS
	ADS1248AssertCS(1);
	return;
}

void ADS1248SendResetCommand(void)
{
	// assert CS to start transfer
	ADS1248AssertCS(0);
	// send the command byte
	ADS1248SendByte(ADS1248_CMD_RESET);
	// de-assert CS
	ADS1248AssertCS(1);
	return;
}

long ADS1248ReadData(void)
{
	long Data;
	//ADS1248WaitForDataReady(1000);
	// assert CS to start transfer
	ADS1248AssertCS(0);
	// send the command byte
	ADS1248SendByte(ADS1248_CMD_RDATA);
	// get the conversion result
#ifdef ADS1148
	Data = ADS1248ReceiveByte();
	Data = (Data << 8) | ADS1248ReceiveByte();
    // sign extend data if the MSB is high (16 to 32 bit sign extension)
	if (Data & 0x8000)
		Data |= 0xffff0000;
#else
	Data = ADS1248ReceiveByte();
	Data = (Data << 8) | ADS1248ReceiveByte();
	Data = (Data << 8) | ADS1248ReceiveByte();
	// sign extend data if the MSB is high (24 to 32 bit sign extension)
	if (Data & 0x800000)
		Data |= 0xff000000;
#endif
	// de-assert CS
	ADS1248AssertCS(1);
	return Data;
}

void ADS1248ReadRegister(int StartAddress, int NumRegs, unsigned * pData)
{
	int i;
	// assert CS to start transfer
	ADS1248AssertCS(0);
	// send the command byte
	ADS1248SendByte(ADS1248_CMD_RREG | (StartAddress & 0x0f));
	ADS1248SendByte((NumRegs-1) & 0x0f);

	//ADS1248WaitForDataReady(10000);
	// get the register content
	for (i=0; i< NumRegs; i++)
	{
		*pData++ = ADS1248ReceiveByte();
	}
	// de-assert CS
	ADS1248AssertCS(1);
	return;
}

void ADS1248WriteRegister(int StartAddress, int NumRegs, unsigned * pData)
{
	int i;
	// set the CS low
	ADS1248AssertCS(0);
	// send the command byte
	ADS1248SendByte(ADS1248_CMD_WREG | (StartAddress & 0x0f));
	ADS1248SendByte((NumRegs-1) & 0x0f);
	// send the data bytes
	for (i=0; i < NumRegs; i++)
	{
		ADS1248SendByte(*pData++);
	}
	// set the CS back high
	ADS1248AssertCS(1);
}

void ADS1248WriteSequence(int StartAddress, int NumRegs, unsigned * pData)
{
	int i;
	char dummy;
	// set the CS low
	ADS1248AssertCS(0);
#if defined (__MSP430F5529__)
	// send the command byte
	dummy = UCB0RXBUF;
	while(!(UCB0IFG&UCTXIFG));			// Make sure nothing is already in the TX buffer
	UCB0TXBUF = ADS1248_CMD_WREG | (StartAddress & 0x0f);
	while(!(UCB0IFG&UCRXIFG));
	dummy = UCB0RXBUF;
	UCB0TXBUF = (NumRegs-1) & 0x0f;
	while(!(UCB0IFG&UCRXIFG));
	dummy = UCB0RXBUF;
	// send the data bytes
	for (i=0; i < NumRegs; i++)
	{
		UCB0TXBUF = *pData++;
		while(!(UCB0IFG&UCRXIFG));
		dummy = UCB0RXBUF;
	}
#elif defined (PART_TM4C1294NCPDT)
	HWREG(SPI_BASE + SSI_O_DR) = ADS1248_CMD_WREG | (StartAddress & 0x0f);	// set up data for the next xmit
	while(!(HWREG(SPI_BASE + SSI_O_SR) & SSI_SR_RNE));  // wait for data to appear
	dummy = HWREG(SPI_BASE+SSI_O_DR);         			// grab that data
	HWREG(SPI_BASE + SSI_O_DR) = (NumRegs-1) & 0x0f;	// set up data for the next xmit
	while(!(HWREG(SPI_BASE + SSI_O_SR) & SSI_SR_RNE));  // wait for data to appear
	dummy = HWREG(SPI_BASE+SSI_O_DR);         			// grab that data
	// send the data bytes
	for (i=0; i < NumRegs; i++)
	{
		HWREG(SPI_BASE + SSI_O_DR) = *pData++;
		while(!(HWREG(SPI_BASE + SSI_O_SR) & SSI_SR_RNE));  // wait for data to appear
		dummy = HWREG(SPI_BASE+SSI_O_DR);         			// grab that data
	}

#endif

#ifdef BOARD_NXP_LPCXPRESSO_1769
#if BUFFERED_SPI
	for (i=0; i < NumRegs; i++)
	{
		spi_tx_buf[i] = pData[i];
	}

	spi_xf.cnt = 0;
	spi_xf.length = NumRegs;
	spi_xf.pTxData = spi_tx_buf;
	spi_xf.pRxData = spi_rx_buf;

	Chip_SPI_RWFrames_Blocking(LPC_SPI, &spi_xf);
#else
	Chip_SPI_SendFrame(LPC_SPI, ADS1248_CMD_WREG | (StartAddress & 0x0f));	// set up data for the next xmit
	while(!(Chip_SPI_GetStatus(LPC_SPI) & SPI_SR_SPIF));// wait for data to appear
	dummy = Chip_SPI_ReceiveFrame(LPC_SPI);// grab that data
	Chip_SPI_SendFrame(LPC_SPI, (NumRegs-1) & 0x0f);	// set up data for the next xmit
	while(!(Chip_SPI_GetStatus(LPC_SPI) & SPI_SR_SPIF));// wait for data to appear
	dummy = Chip_SPI_ReceiveFrame(LPC_SPI);// grab that data
	// send the data bytes
	for (i=0; i < NumRegs; i++)
	{
		Chip_SPI_SendFrame(LPC_SPI, *pData++);
		while(!(Chip_SPI_GetStatus(LPC_SPI) & SPI_SR_SPIF));  // wait for data to appear
		dummy = Chip_SPI_ReceiveFrame(LPC_SPI);      			// grab that data
	}
#endif
#endif
	// set the CS back high
	ADS1248AssertCS(1);
}

void ADS1248SendRDATAC(void)
{
	// assert CS to start transfer
	ADS1248AssertCS(0);
	// send the command byte
	ADS1248SendByte(ADS1248_CMD_RDATAC);
	// de-assert CS
	ADS1248AssertCS(1);
	return;
}

void ADS1248SendSDATAC(void)
{
	// assert CS to start transfer
	ADS1248AssertCS(0);
	// send the command byte
	ADS1248SendByte(ADS1248_CMD_SDATAC);
	// de-assert CS
	ADS1248AssertCS(1);
	return;
}

void ADS1248SendSYSOCAL(void)
{
	// assert CS to start transfer
	ADS1248AssertCS(0);
	// send the command byte
	ADS1248SendByte(ADS1248_CMD_SYSOCAL);
	// de-assert CS
	ADS1248AssertCS(1);
	return;
}

void ADS1248SendSYSGCAL(void)
{
	// assert CS to start transfer
	ADS1248AssertCS(0);
	// send the command byte
	ADS1248SendByte(ADS1248_CMD_SYSGCAL);
	// de-assert CS
	ADS1248AssertCS(1);
	return;
}

void ADS1248SendSELFOCAL(void)
{
	// assert CS to start transfer
	ADS1248AssertCS(0);
	// send the command byte
	ADS1248SendByte(ADS1248_CMD_SELFOCAL);
	// de-assert CS
	ADS1248AssertCS(1);
	return;
}

/*
 * Register Set Value Commands
 *
 * These commands need to strip out old settings (AND) and add (OR) the new contents to the register
 */
int ADS1248SetBurnOutSource(int BurnOut)
{
	unsigned Temp;
	int dError = ADS1248_NO_ERROR;
	ADS1248ReadRegister(ADS1248_0_MUX0, 0x01, &Temp);
	Temp &= 0x3f;
	switch(BurnOut) {
		case 0:
			Temp |= ADS1248_BCS_OFF;
			break;
		case 1:
			Temp |= ADS1248_BCS_500nA;
			break;
		case 2:
			Temp |= ADS1248_BCS_2uA;
			break;
		case 3:
			Temp |= ADS1248_BCS_10uA;
			break;
		default:
			dError = ADS1248_ERROR;
			Temp |= ADS1248_BCS_OFF;
	}
	// write the register value containing the new value back to the ADS
	ADS1248WriteRegister(ADS1248_0_MUX0, 0x01, &Temp);
	return dError;
}

int ADS1248SetChannel(int vMux, int pMux)
{
	unsigned Temp;
	int dError = ADS1248_NO_ERROR;
	ADS1248ReadRegister(ADS1248_0_MUX0, 0x01, &Temp);
	if (pMux==1) {
		Temp &= 0xf8;
		switch(vMux) {
			case 0:
				Temp |= ADS1248_AINN0;
				break;
			case 1:
				Temp |= ADS1248_AINN1;
				break;
			case 2:
				Temp |= ADS1248_AINN2;
				break;
			case 3:
				Temp |= ADS1248_AINN3;
				break;
			case 4:
				Temp |= ADS1248_AINN4;
				break;
			case 5:
				Temp |= ADS1248_AINN5;
				break;
			case 6:
				Temp |= ADS1248_AINN6;
				break;
			case 7:
				Temp |= ADS1248_AINN7;
				break;
			default:
				Temp |= ADS1248_AINN0;
				dError = ADS1248_ERROR;
		}

	} else {
		Temp &= 0xc7;
		switch(vMux) {
			case 0:
				Temp |= ADS1248_AINP0;
				break;
			case 1:
				Temp |= ADS1248_AINP1;
				break;
			case 2:
				Temp |= ADS1248_AINP2;
				break;
			case 3:
				Temp |= ADS1248_AINP3;
				break;
			case 4:
				Temp |= ADS1248_AINP4;
				break;
			case 5:
				Temp |= ADS1248_AINP5;
				break;
			case 6:
				Temp |= ADS1248_AINP6;
				break;
			case 7:
				Temp |= ADS1248_AINP7;
				break;
			default:
				Temp |= ADS1248_AINP0;
				dError = ADS1248_ERROR;
		}
	}
	// write the register value containing the new value back to the ADS
	ADS1248WriteRegister(ADS1248_0_MUX0, 0x01, &Temp);
	return dError;
}

int ADS1248SetBias(unsigned char vBias)
{
	unsigned Temp;
	Temp = ADS1248_VBIAS_OFF;
	if (vBias & 0x80)
		Temp |=  ADS1248_VBIAS7;
	if (vBias & 0x40)
		Temp |=  ADS1248_VBIAS6;
	if (vBias & 0x20)
		Temp |=  ADS1248_VBIAS5;
	if (vBias & 0x10)
		Temp |=  ADS1248_VBIAS4;
	if (vBias & 0x08)
		Temp |=  ADS1248_VBIAS3;
	if (vBias & 0x04)
		Temp |=  ADS1248_VBIAS2;
	if (vBias & 0x02)
		Temp |=  ADS1248_VBIAS1;
	if (vBias & 0x01)
		Temp |=  ADS1248_VBIAS0;
	// write the register value containing the new value back to the ADS
	ADS1248WriteRegister(ADS1248_1_VBIAS, 0x01, &Temp);
	return ADS1248_NO_ERROR;
}

// Relate to Mux1
int ADS1248SetIntRef(int sRef)
{
	unsigned Temp;
	int dError = ADS1248_NO_ERROR;
	ADS1248ReadRegister(ADS1248_2_MUX1, 0x01, &Temp);
	Temp &= 0x1f;
	switch(sRef) {
		case 0:
			Temp |= ADS1248_INT_VREF_OFF;
			break;
		case 1:
			Temp |= ADS1248_INT_VREF_ON;
			break;
		case 2:
		case 3:
			Temp |= ADS1248_INT_VREF_CONV;
			break;
		default:
			Temp |= ADS1248_INT_VREF_OFF;
			dError = ADS1248_ERROR;

	}
	// write the register value containing the new value back to the ADS
	ADS1248WriteRegister(ADS1248_2_MUX1, 0x01, &Temp);
	return dError;
}

int ADS1248SetVoltageReference(int VoltageRef)
{
	unsigned Temp;
	int dError = ADS1248_NO_ERROR;
	ADS1248ReadRegister(ADS1248_2_MUX1, 0x01, &Temp);
	Temp &= 0xe7;
	switch(VoltageRef) {
		case 0:
			Temp |= ADS1248_REF0;
			break;
		case 1:
			Temp |= ADS1248_REF1;
			break;
		case 2:
			Temp |= ADS1248_INT;
			break;
		case 3:
			Temp |= ADS1248_INT_REF0;
			break;
		default:
			Temp |= ADS1248_REF0;
			dError = ADS1248_ERROR;
	}
	// write the register value containing the new value back to the ADS
	ADS1248WriteRegister(ADS1248_2_MUX1, 0x01, &Temp);
	return dError;
}

int ADS1248SetSystemMonitor(int Monitor)
{
	unsigned Temp;
	int dError = ADS1248_NO_ERROR;
	ADS1248ReadRegister(ADS1248_2_MUX1, 0x01, &Temp);
	Temp &= 0x78;
	switch(Monitor) {
		case 0:
			Temp |= ADS1248_MEAS_NORM;
			break;
		case 1:
			Temp |= ADS1248_MEAS_OFFSET;
			break;
		case 2:
			Temp |= ADS1248_MEAS_GAIN;
			break;
		case 3:
			Temp |= ADS1248_MEAS_TEMP;
			break;
		case 4:
			Temp |= ADS1248_MEAS_REF1;
			break;
		case 5:
			Temp |= ADS1248_MEAS_REF0;
			break;
		case 6:
			Temp |= ADS1248_MEAS_AVDD;
			break;
		case 7:
			Temp |= ADS1248_MEAS_DVDD;
			break;
		default:
			Temp |= ADS1248_MEAS_NORM;
			dError = ADS1248_ERROR;
	}
	// write the register value containing the new value back to the ADS
	ADS1248WriteRegister(ADS1248_2_MUX1, 0x01, &Temp);
	return dError;
}

// Relate to SYS0
int ADS1248SetGain(int Gain)
{
	unsigned Temp;
	int dError = ADS1248_NO_ERROR;
	ADS1248ReadRegister(ADS1248_3_SYS0, 0x01, &Temp);
	Temp &= 0x0f;
	switch(Gain) {
		case 0:
			Temp |= ADS1248_GAIN_1;
			break;
		case 1:
			Temp |= ADS1248_GAIN_2;
			break;
		case 2:
			Temp |= ADS1248_GAIN_4;
			break;
		case 3:
			Temp |= ADS1248_GAIN_8;
			break;
		case 4:
			Temp |= ADS1248_GAIN_16;
			break;
		case 5:
			Temp |= ADS1248_GAIN_32;
			break;
		case 6:
			Temp |= ADS1248_GAIN_64;
			break;
		case 7:
			Temp |= ADS1248_GAIN_128;
			break;
		default:
			Temp |= ADS1248_GAIN_1;
			dError = ADS1248_ERROR;
		}
		// write the register value containing the new value back to the ADS
		ADS1248WriteRegister(ADS1248_3_SYS0, 0x01, &Temp);
		return dError;
}

int ADS1248SetDataRate(int DataRate)
{
	unsigned Temp;
	int dError = ADS1248_NO_ERROR;
	ADS1248ReadRegister(ADS1248_3_SYS0, 0x01, &Temp);
	Temp &= 0x70;
	switch(DataRate) {
		case 0:
			Temp |= ADS1248_DR_5;
			break;
		case 1:
			Temp |= ADS1248_DR_10;
			break;
		case 2:
			Temp |= ADS1248_DR_20;
			break;
		case 3:
			Temp |= ADS1248_DR_40;
			break;
		case 4:
			Temp |= ADS1248_DR_80;
			break;
		case 5:
			Temp |= ADS1248_DR_160;
			break;
		case 6:
			Temp |= ADS1248_DR_320;
			break;
		case 7:
			Temp |= ADS1248_DR_640;
			break;
		case 8:
			Temp |= ADS1248_DR_1000;
			break;
		case 9:
		case 10:
		case 11:
		case 12:
		case 13:
		case 14:
		case 15:
			Temp |= ADS1248_DR_2000;
			break;
		default:
			Temp |= ADS1248_DR_5;
			dError = ADS1248_ERROR;
	}
	// write the register value containing the new value back to the ADS
	ADS1248WriteRegister(ADS1248_3_SYS0, 0x01, &Temp);
	return dError;
}

// Relate to OFC (3 registers)
int ADS1248SetOFC(long RegOffset)
{
	// find the pointer to the variable so we can write the value as bytes
	unsigned *cptr=(unsigned *)(&RegOffset);
	int i;

	for (i=0; i<3; i++)
	{
		// write the register value containing the new value back to the ADS
		ADS1248WriteRegister((ADS1248_4_OFC0 + i), 0x01, &cptr[i]);
	}
	return ADS1248_NO_ERROR;
}

// Relate to FSC (3 registers)
int ADS1248SetFSC(long RegGain)
{
	// find the pointer to the variable so we can write the value as bytes
	unsigned *cptr=(unsigned *)(&RegGain);
	int i;
	for (i=0; i<3; i++)
	{
		// write the register value containing the new value back to the ADS
		ADS1248WriteRegister((ADS1248_7_FSC0 + i), 0x01, &cptr[i]);
	}
	return ADS1248_NO_ERROR;
}

// Relate to IDAC0
int ADS1248SetDRDYMode(int DRDYMode)
{
	unsigned Temp;
	int dError = ADS1248_NO_ERROR;
	ADS1248ReadRegister(ADS1248_10_IDAC0, 0x01, &Temp);
	Temp &= 0xf7;
	switch(DRDYMode) {
		case 0:
			Temp |= ADS1248_DRDY_OFF;
			break;
		case 1:
			Temp |= ADS1248_DRDY_ON;
			break;
		default:
			Temp |= ADS1248_DRDY_OFF;
			dError = ADS1248_ERROR;
	}
	// write the register value containing the new value back to the ADS
	ADS1248WriteRegister(ADS1248_10_IDAC0, 0x01, &Temp);
	return dError;
}

int ADS1248SetCurrentDACOutput(int CurrentOutput)
{
	unsigned Temp;
	int dError = ADS1248_NO_ERROR;
	ADS1248ReadRegister(ADS1248_10_IDAC0, 0x01, &Temp);
	Temp &= 0xf8;
	switch(CurrentOutput) {
		case 0:
			Temp |= ADS1248_IDAC_OFF;
			break;
		case 1:
			Temp |= ADS1248_IDAC_50;
			break;
		case 2:
			Temp |= ADS1248_IDAC_100;
			break;
		case 3:
			Temp |= ADS1248_IDAC_250;
			break;
		case 4:
			Temp |= ADS1248_IDAC_500;
			break;
		case 5:
			Temp |= ADS1248_IDAC_750;
			break;
		case 6:
			Temp |= ADS1248_IDAC_1000;
			break;
		case 7:
			Temp |= ADS1248_IDAC_1500;
			break;
		default:
			Temp |= ADS1248_IDAC_OFF;
			dError = ADS1248_ERROR;
	}
	// write the register value containing the new value back to the ADS
	ADS1248WriteRegister(ADS1248_10_IDAC0, 0x01, &Temp);
	return dError;
}

// Relate to IDAC1
int ADS1248SetIDACRouting(int IDACroute, int IDACdir)		// IDACdir (0 = I1DIR, 1 = I2DIR)
{
	unsigned Temp;
	int dError = ADS1248_NO_ERROR;
	ADS1248ReadRegister(ADS1248_11_IDAC1, 0x01, &Temp);
	if (IDACdir>0){
		Temp &= 0xf0;
		switch(IDACroute) {
			case 0:
				Temp |= ADS1248_IDAC2_A0;
				break;
			case 1:
				Temp |= ADS1248_IDAC2_A1;
				break;
			case 2:
				Temp |= ADS1248_IDAC2_A2;
				break;
			case 3:
				Temp |= ADS1248_IDAC2_A3;
				break;
			case 4:
				Temp |= ADS1248_IDAC2_A4;
				break;
			case 5:
				Temp |= ADS1248_IDAC2_A5;
				break;
			case 6:
				Temp |= ADS1248_IDAC2_A6;
				break;
			case 7:
				Temp |= ADS1248_IDAC2_A7;
				break;
			case 8:
				Temp |= ADS1248_IDAC2_EXT1;
				break;
			case 9:
				Temp |= ADS1248_IDAC2_EXT2;
				break;
			case 10:
				Temp |= ADS1248_IDAC2_EXT1;
				break;
			case 11:
				Temp |= ADS1248_IDAC2_EXT2;
				break;
			case 12:
			case 13:
			case 14:
			case 15:
				Temp |= ADS1248_IDAC2_OFF;
				break;
			default:
				Temp |= ADS1248_IDAC2_OFF;
				dError = ADS1248_ERROR;
		}

	} else {
		Temp &= 0x0f;
		switch(IDACroute) {
			case 0:
				Temp |= ADS1248_IDAC1_A0;
				break;
			case 1:
				Temp |= ADS1248_IDAC1_A1;
				break;
			case 2:
				Temp |= ADS1248_IDAC1_A2;
				break;
			case 3:
				Temp |= ADS1248_IDAC1_A3;
				break;
			case 4:
				Temp |= ADS1248_IDAC1_A4;
				break;
			case 5:
				Temp |= ADS1248_IDAC1_A5;
				break;
			case 6:
				Temp |= ADS1248_IDAC1_A6;
				break;
			case 7:
				Temp |= ADS1248_IDAC1_A7;
				break;
			case 8:
				Temp |= ADS1248_IDAC1_EXT1;
				break;
			case 9:
				Temp |= ADS1248_IDAC1_EXT2;
				break;
			case 10:
				Temp |= ADS1248_IDAC1_EXT1;
				break;
			case 11:
				Temp |= ADS1248_IDAC1_EXT2;
				break;
			case 12:
			case 13:
			case 14:
			case 15:
				Temp |= ADS1248_IDAC1_OFF;
				break;
			default:
				Temp |= ADS1248_IDAC1_OFF;
				dError = ADS1248_ERROR;
		}
	}
	// write the register value containing the new value back to the ADS
	ADS1248WriteRegister(ADS1248_11_IDAC1, 0x01, &Temp);
	return dError;
}

// Relate to GPIOCFG
int ADS1248SetGPIOConfig(unsigned char cdata)
{
	unsigned Temp;
	Temp = 0x00;
	if (cdata & 0x80)
		Temp |=  ADS1248_GPIO_7;
	if (cdata & 0x40)
		Temp |=  ADS1248_GPIO_6;
	if (cdata & 0x20)
		Temp |=  ADS1248_GPIO_5;
	if (cdata & 0x10)
		Temp |=  ADS1248_GPIO_4;
	if (cdata & 0x08)
		Temp |=  ADS1248_GPIO_3;
	if (cdata & 0x04)
		Temp |=  ADS1248_GPIO_2;
	if (cdata & 0x02)
		Temp |=  ADS1248_GPIO_1;
	if (cdata & 0x01)
		Temp |=  ADS1248_GPIO_0;
	// write the register value containing the new value back to the ADS
	ADS1248WriteRegister(ADS1248_12_GPIOCFG, 0x01, &Temp);
	return ADS1248_NO_ERROR;
}

// Relate to GPIODIR
int ADS1248SetGPIODir(unsigned char cdata)
{
	unsigned Temp;
	Temp = 0x00;
	if (cdata & 0x80)
		Temp |=  ADS1248_IO_7;
	if (cdata & 0x40)
		Temp |=  ADS1248_IO_6;
	if (cdata & 0x20)
		Temp |=  ADS1248_IO_5;
	if (cdata & 0x10)
		Temp |=  ADS1248_IO_4;
	if (cdata & 0x08)
		Temp |=  ADS1248_IO_3;
	if (cdata & 0x04)
		Temp |=  ADS1248_IO_2;
	if (cdata & 0x02)
		Temp |=  ADS1248_IO_1;
	if (cdata & 0x01)
		Temp |=  ADS1248_IO_0;
	// write the register value containing the new value back to the ADS
	ADS1248WriteRegister(ADS1248_13_GPIODIR, 0x01, &Temp);
	return ADS1248_NO_ERROR;
}

// Relate to GPIODAT
int ADS1248SetGPIO(unsigned char cdata)
{
	unsigned Temp;
	Temp = 0x00;
	if (cdata & 0x80)
		Temp |=  ADS1248_OUT_7;
	if (cdata & 0x40)
		Temp |=  ADS1248_OUT_6;
	if (cdata & 0x20)
		Temp |=  ADS1248_OUT_5;
	if (cdata & 0x10)
		Temp |=  ADS1248_OUT_4;
	if (cdata & 0x08)
		Temp |=  ADS1248_OUT_3;
	if (cdata & 0x04)
		Temp |=  ADS1248_OUT_2;
	if (cdata & 0x02)
		Temp |=  ADS1248_OUT_1;
	if (cdata & 0x01)
		Temp |=  ADS1248_OUT_0;
	// write the register value containing the new value back to the ADS
	ADS1248WriteRegister(ADS1248_14_GPIODAT, 0x01, &Temp);
	return ADS1248_NO_ERROR;
}

/* Register Get Value Commands */
// Relate to MUX0
int ADS1248GetBurnOutSource(void)
{
	unsigned Temp;
	ADS1248ReadRegister(ADS1248_0_MUX0, 0x01, &Temp);
	return ((Temp >> 6) & 0x03);
}

int ADS1248GetChannel(int cMux)			// cMux = 0, AINP; cMux = 1, AINN
{
	unsigned Temp;
	ADS1248ReadRegister(ADS1248_0_MUX0, 0x01, &Temp);
	if (cMux==0)
		return ((Temp >> 3) & 0x07);
	else
		return (Temp  & 0x07);
}

// Relate to VBIAS
unsigned char ADS1248GetBias(void)
{
	unsigned Temp;
	ADS1248ReadRegister(ADS1248_1_VBIAS, 0x01, &Temp);
	return (Temp & 0xff);
}

//Relate to MUX1
int ADS1248GetCLKSTAT(void)
{
	unsigned Temp;
	ADS1248ReadRegister(ADS1248_2_MUX1, 0x01, &Temp);
	return ((Temp >> 7) & 0x01);
}

int ADS1248GetIntRef(void)
{
	unsigned Temp;
	ADS1248ReadRegister(ADS1248_2_MUX1, 0x01, &Temp);
	return ((Temp >> 5) & 0x03);
}

int ADS1248GetVoltageReference(void)
{
	unsigned Temp;
	ADS1248ReadRegister(ADS1248_2_MUX1, 0x01, &Temp);
	return ((Temp >> 3) & 0x03);
}

int ADS1248GetSystemMonitor(void)
{
	unsigned Temp;
	ADS1248ReadRegister(ADS1248_2_MUX1, 0x01, &Temp);
	return (Temp & 0x07);
}

// Relate to SYS0
int ADS1248GetGain(void)
{
	unsigned Temp;
	ADS1248ReadRegister(ADS1248_3_SYS0, 0x01, &Temp);
	return ((Temp >> 4) & 0x07);
}

int ADS1248GetDataRate(void)
{
	unsigned Temp;
	ADS1248ReadRegister(ADS1248_3_SYS0, 0x01, &Temp);
	return (Temp & 0x0f);
}

// Relate to OFC (3 registers)
long ADS1248GetOFC(void)
{
	long rData=0;
	unsigned rValue=0;
	unsigned regArray[3];
	int i;
	//write the desired default register settings for the first 4 registers NOTE: values shown are the POR values as per datasheet
	regArray[0] = 0x00;
	regArray[1] = 0x00;
	regArray[2] = 0x00;
	for (i=0; i<3; i++)
	{
		// read the register value for the OFC
		ADS1248ReadRegister((ADS1248_4_OFC0 + i), 0x01, &rValue);
		regArray[i] = rValue;
	}
	rData = regArray[2];
	rData = (rData<<8) | regArray[1];
	rData = (rData<<8) | regArray[0];
	return rData;
}

// Relate to FSC (3 registers)
long ADS1248GetFSC(void)
{
	long rData=0;
	unsigned rValue=0;
	unsigned regArray[3];
	int i;
	//write the desired default register settings for the first 4 registers NOTE: values shown are the POR values as per datasheet
	regArray[0] = 0x00;
	regArray[1] = 0x00;
	regArray[2] = 0x00;
	for (i=0; i<3; i++)
	{
		// read the register value for the OFC
		ADS1248ReadRegister((ADS1248_7_FSC0 + i), 0x01, &rValue);
		regArray[i] = rValue;
	}
	rData = regArray[2];
	rData = (rData<<8) | regArray[1];
	rData = (rData<<8) | regArray[0];
	return rData;
}

// Relate to IDAC0
int ADS1248GetID(void)
{
	unsigned Temp;
	ADS1248ReadRegister(ADS1248_10_IDAC0, 0x01, &Temp);
	return ((Temp>>4) & 0x0f);
}

int ADS1248GetDRDYMode(void)
{
	unsigned Temp;
	ADS1248ReadRegister(ADS1248_10_IDAC0, 0x01, &Temp);
	return ((Temp>>3) & 0x01);
}

int ADS1248GetCurrentDACOutput(void)
{
	unsigned Temp;
	ADS1248ReadRegister(ADS1248_10_IDAC0, 0x01, &Temp);
	return (Temp & 0x07);
}

// Relate to IDAC1
int ADS1248GetIDACRouting(int WhichOne) 		// IDACRoute (0 = I1DIR, 1 = I2DIR)
{
	unsigned Temp;
	ADS1248ReadRegister(ADS1248_11_IDAC1, 0x01, &Temp);
	if (WhichOne==0)
		return ((Temp>>4) & 0x0f);
	else
		return (Temp & 0x0f);
}

// Relate to GPIOCFG
unsigned char ADS1248GetGPIOConfig(void)
{
	unsigned Temp;
	ADS1248ReadRegister(ADS1248_12_GPIOCFG, 0x01, &Temp);
	return (Temp & 0xff);
}

// Relate to GPIODIR
unsigned char ADS1248GetGPIODir(void)
{
	unsigned Temp;
	ADS1248ReadRegister(ADS1248_13_GPIODIR, 0x01, &Temp);
	return (Temp & 0xff);
}

// Relate to GPIODAT
unsigned char ADS1248GetGPIO(void)
{
	unsigned Temp;
	ADS1248ReadRegister(ADS1248_14_GPIODAT, 0x01, &Temp);
	return (Temp & 0xff);
}

/* Miscellaneous Commands */
long ADS1248RDATACRead(void)		// reads data directly based on RDATAC mode (writes NOP) and 32 SCLKs
{
	long Data;
	// assert CS to start transfer
	ADS1248AssertCS(0);
	// get the conversion result
#ifdef ADS1148
	Data = ADS1248ReceiveByte();
	Data = (Data << 8) | ADS1248ReceiveByte();
    // sign extend data if the MSB is high (16 to 32 bit sign extension)
	if (Data & 0x8000)
		Data |= 0xffff0000;
#else
	Data = ADS1248ReceiveByte();
	Data = (Data << 8) | ADS1248ReceiveByte();
	Data = (Data << 8) | ADS1248ReceiveByte();
	// sign extend data if the MSB is high (24 to 32 bit sign extension)
	if (Data & 0x800000)
		Data |= 0xff000000;
#endif
	// de-assert CS
	ADS1248AssertCS(1);
	return Data;
}

/* Hardware Control Functions for Device Pin Control */
// Possible Need for Reset, Start (power down) (0-low, 1-high, 2-pulse)
int ADS1248SetStart(int nStart)
{
	/*
	 * Code can be added here to set high or low the state of the pin for controlling the START pin
	 * which will differ depending on controller used and port pin assigned
	 */

#if defined (__MSP430F5529__)
	// This example is using PORT6 for GPIO Start control, ADS1248_START is defined in ads1248.h
	if (nStart)				// nStart=0 is START low, nStart=1 is START high
		P6OUT |=  (ADS1248_START);
	else
		P6OUT &=  ~(ADS1248_START);
#elif defined (PART_TM4C1294NCPDT)
	if (nStart)				// nStart=0 is START low, nStart=1 is START high
		GPIOPinWrite(START_PORT, ADS1248_START, 0xFF);
	else
		GPIOPinWrite(START_PORT, ADS1248_START, 0);
#endif

#ifdef BOARD_NXP_LPCXPRESSO_1769
		// nStart=0 is START low, nStart=1 is START high

		Chip_GPIO_SetPinState(LPC_GPIO, START_PORT, ADS1248_START, nStart);
#endif
	return ADS1248_NO_ERROR;
}

int ADS1248SetReset(int nReset)
{
	/*
	 * Code can be added here to set high or low the state of the pin for controlling the RESET pin
	 * which will differ depending on controller used and port pin assigned
	 */
#if defined (__MSP430F5529__)
	// This example is using PORT6 for GPIO Reset Control, ADS1248_RESET is defined in ads1248.h
	if (nReset)				// nReset=0 is RESET low, nReset=1 is RESET high
		P6OUT |=  (ADS1248_RESET);
	else
		P6OUT &=  ~(ADS1248_RESET);
#elif defined (PART_TM4C1294NCPDT)
	if (nReset)				// nReset=0 is RESET low, nReset=1 is RESET high
		GPIOPinWrite(RESET_PORT, ADS1248_RESET, 0xFF);
	else
		GPIOPinWrite(RESET_PORT, ADS1248_RESET, 0);
#endif
	return ADS1248_NO_ERROR;
}

  • Hi Admin,

    Thanks for posting this piece of code and the schematic. Can you also help explain what's going on in more detail?

    What signals are you applying to your inputs, what is the expected voltage you want to measure, and what is the data you are seeing from the device?

    It was also not clear to me from your schematic how you are measuring the inputs? If you want to measure across the shunt you will need to measure between 1TW1 and 1TW2 for example, but I don't see any connection points from these nodes back to the ADC. The code also says that you are reading AIN3 with respect to AIN5. But AIN5 is not connected to anything in the schematic you sent. And AIN3 is connected to net A4, but I don't see A4 anywhere else in the picture you sent other than connected to AIN3. Where does this net go?

    Please help provide more details. Thanks!

    -Bryan

  • Hi Admin,

    Also, please note that you need to hold the START pin high when writing registers. This is mentioned in the footnote underneath Table 19 (SPI Commands) on pg. 45 in the ADS1248 datasheet. Looks like you are only toggling the START pin to perform a conversion, so none of your registers are actually being written.

    -Bryan

  • Hi Bryan Thanks for reply and your time,

    - What signals are you applying to your inputs, what is the expected voltage you want to measure, and what is the data you are seeing from the device?

    As whole it was not working , so what i did is appliead 1 Volt at c40 Capacitor , A5 is connected at AIN4 and i connecetd GND to PIN AIN5(pin 14 of IC is GND), and i am measuring AIN4 wrt to AIN5 or AIN3 wrt AIN5.

    it was a mistake and not reflected in the original schematic.

  • Hi Bryan

    In changed the Start Single Pulse code as below, but still not getting reading

    void ADS1248_startSingle(){
    
    	int relVal = 1;
    	ADS1248SetStart(0);// low
    	delayMS(100);    // wait for 100 ms
    	ADS1248SetStart(1); // high
    
    }

  • The below image shows the reading taken in an array, as you can see reading keeps on fluctuating and it is nowhere near to 1V.

    the internal reference is 2.048V, 

  • Hi Admin,

    Are you holding the START pin high when writing all of your registers? Note that the ADS1248 requires you to hold the START pin high for the duration of the register writes and reads. At least in the original code you sent, you do not call the ADS1248_startSingle()function until after all of your register writes.

    Can you make sure this occurs correctly by writing all of your registers and then reading them back to make sure they all updated? Once we know that you are able to read and write registers, we can then focus on the conversion results.

    -Bryan

  • Hi Bryan Thanks for reply,

    sorry for late delay as we had holiday period.

    Now i have updated my code for change as you have mentioned, as you can see i had added Datarate verification if i read datarate register and if it is not same i have used while loop for error.

    my code run fines and doesnt go in while loop, so data register are updated correct that can be concluded.


    int32_t ADS1248_sample_raw( ) { int32_t res = 0; unsigned int Temp = 0; //keep START HIGH ADS1248SetStart(1); Temp = ADS1248_DRDY_OFF; ADS1248WriteRegister(ADS1248_10_IDAC0, 0x01, &Temp); // ref v channels Temp = (ADS1248_INT_VREF_ON ) | (ADS1248_INT_REF0) | (ADS1248_MEAS_NORM); //ADS1248SetVoltageReference(Temp); ADS1248WriteRegister(ADS1248_2_MUX1, 0x01, &Temp); // Setup gain and sample rate ADS1248SetGain(ADS1248_GAIN_1 ) ; ADS1248SetDataRate(ADS1248_DR_1000); //Temp = ADS1248_DR_320|ADS1248_GAIN_1; //ADS1248WriteRegister(ADS1248_3_SYS0, 0x01, &Temp); Temp = ADS1248GetDataRate(); // verify if data register is updated if(Temp != ADS1248_DR_1000){ while(1); // error } // read CH 3 wrt CH5 // Choose channels ADS1248SetChannel (0, ( ADS1248_AINN4) ); ADS1248SetChannel (1, (ADS1248_AINP5) ); ADS1248_startSingle(); delayMS(500); res = ADS1248ReadData(); rawADC[adcCounterSample++] = res; if(adcCounterSample > 31) { adcCounterSample = 0; } float tempV = res; tempV *= 2.048; // internal ref 2.048 tempV /= 8388608; // 2^23 tempV *= 1000; // value in mV return res; }
    
    

    i have also updated start pulse code for conversion

    void ADS1248_startSingle(){
    
    	ADS1248SetStart(0);
    	delayMS(100);
    	ADS1248SetStart(1);
    	delayMS(100);
    	ADS1248SetStart(0);
    	ADS1248SetStart(1);
    }

    Still there is no result

  • Hi Admin,

    Can you try reading back some of the system monitors on the ADS1248 and see if you get valid data? For example, the power supply monitor and/or the VREF monitor. This will give you an idea if you can read valid data from the device or not, and maybe there is an issue with the inputs.

    -Bryan

  • Hi Bryan,

    As You suggested i have added 2 lines to read ref and system monitor, you can see in below code

    /**
    * @brief This function will return raw reading of channels by passing +ve channe, --ve channel, gain setting, samplerate and reference voltage
    * @author Mohammed Asim Merchant
    * @date 27/02/2019
    * @param void.
    * @return int32_t.
    */
    int32_t ADS1248_sample_raw( )
    {
    	int32_t res = 0;
    	unsigned int Temp = 0;
    
    	//keep START HIGH
    	ADS1248SetStart(1);
    
    	Temp = ADS1248_DRDY_OFF;
    	ADS1248WriteRegister(ADS1248_10_IDAC0, 0x01, &Temp);
    
    	// ref v channels
    	Temp =  (ADS1248_INT_VREF_ON ) | (ADS1248_INT_REF0) | (ADS1248_MEAS_NORM);
    	//ADS1248SetVoltageReference(Temp);
    	ADS1248WriteRegister(ADS1248_2_MUX1, 0x01, &Temp);
    
    	// Setup gain and sample rate
    	ADS1248SetGain(ADS1248_GAIN_1 ) ;
    
    	ADS1248SetDataRate(ADS1248_DR_1000);
    	//Temp = ADS1248_DR_320|ADS1248_GAIN_1;
    	//ADS1248WriteRegister(ADS1248_3_SYS0, 0x01, &Temp);
    
    	/*
    	 * Read back the ref and sys monitor variable for verification
    	 * */
    	Temp = ADS1248GetVoltageReference();
    
    	Temp =  ADS1248GetSystemMonitor();
    
    	Temp = ADS1248GetDataRate();
    
    	// verify if data register is updated
    	if(Temp != ADS1248_DR_1000){
    		while(1);	// error
    	}
    
    	// read CH 3 wrt CH5
    	// Choose channels
    	ADS1248SetChannel (0, ( ADS1248_AINN0) );
    	ADS1248SetChannel (1, (ADS1248_AINP5) );
    
    	ADS1248_startSingle();
    
    	delayMS(500);
    	res = ADS1248ReadData();
    	rawADC[adcCounterSample++] = res;
    	if(adcCounterSample > 31)
    	{
    		adcCounterSample = 0;
    	}
    	float tempV = res;
    
    	tempV *= 2.048; // internal ref 2.048
    	tempV /= 8388608; // 2^23
    	tempV *= 1000; // value in mV
    
    	return res;
    }

    The following code return value as 

    	Temp = ADS1248GetVoltageReference(); // Temp is read back as 3 
    
    	Temp =  ADS1248GetSystemMonitor();// Temp is read back as 0
  • Hi Bryan,

    I started reading back all register that i was writing, it turns out the Register for Positive ch and the negative channel was not getting updated,

    The following line of code was not working

    ADS1248SetChannel (0, ( ADS1248_AINN4) );
    ADS1248SetChannel (1, (ADS1248_AINP5) );

    after this, i have updated the code and now it works,

    actual code is 

    ADS1248SetChannel ( 4 , 0);
    ADS1248SetChannel ( 5 , 1);

    This ADS12548 library is from TI source but there is no documentation for the same, so i happen to have passed 

    ADS1248_AINN4 as argument

    Thanks for guiding me, it was nice getting a response from you, Have a nice year ahead.

    Thanks for Your time and words

  • Hi Admin,

    I am glad your problem was resolved, and that it was something relatively simple to fix.

    Can you let me know where you got the ADS1248 code since it is from a TI source? I can take a look at it and see if it needs to be documented better.

    -Bryan

  • Hi Byan ,

    Here is the LINK: 

    ADS1248.c and .h can be easily migrated to suit any microcntroller

  • Hi Admin,

    Thanks for sending the link. We will review and update if necessary.

    I will close this thread for now. If you have any other questions please start a new thread and we will support you.

    -Bryan