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.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; }