ADS1256 program
ADS1256.cpp
- Committer:
- laserdad
- Date:
- 2017-12-01
- Revision:
- 0:897d3bb0accd
File content as of revision 0:897d3bb0accd:
#include "ADS1256.h" extern Serial pc; ADS1256::ADS1256(SPI *spi_itf, DigitalIn *nrdy_pin, DigitalOut *cs_pin) { spi = spi_itf; cs = cs_pin; nrdy = nrdy_pin; *cs = 1; // Assert CS high setSpi(); scanMode = 1; gain = 0; /* GAIN */ dataRate = 15; /* DATA output speed*/ buffer_en = 1; channel=0; getMaxWaitDelay_us(); }; uint8_t ADS1256::getGainVal(void) { return (1<<gain); //e.g. 1,2,4,8,16,32,64 } void ADS1256::setSpi(void) { spi->format(8, ADS1256_SPI_MODE); spi->frequency(1800000); } /* ********************************************************************************************************* * name: CfgADC * function: The configuration parameters of ADC gain, data rate and internal buffer; * parameter: gain: 0-5 (1-64) * dataRate: 0-16 (2.5-30000 sps) * The return value: NULL ********************************************************************************************************* */ void ADS1256::cfgADC(void) { static const uint8_t s_tabDataRate[16] = { 0x03, 0x13, 0x20, 0x33, 0x43, 0x53, 0x63, 0x72, 0x82, 0x92, 0xA1, 0xB0, 0xC0, 0xD0, 0xE0, 0xF0 /*reset value */ }; waitDRDY(); uint8_t buf[4]; /* Storage ads1256 register configuration parameters */ /*Status register define Bits 7-4 ID3, ID2, ID1, ID0 Factory Programmed Identification Bits (Read Only) Bit 3 ORDER: Data Output Bit Order 0 = Most Significant Bit First (default) 1 = Least Significant Bit First Input data is always shifted in most significant byte and bit first. Output data is always shifted out most significant byte first. The ORDER bit only controls the bit order of the output data within the byte. Bit 2 ACAL : Auto-Calibration 0 = Auto-Calibration Disabled (default) 1 = Auto-Calibration Enabled When Auto-Calibration is enabled, self-calibration begins at the completion of the WREG command that changes the PGA (bits 0-2 of ADCON register), DR (bits 7-0 in the DRATE register) or BUFEN (bit 1 in the STATUS register) values. Bit 1 BUFEN: Analog Input Buffer Enable 0 = Buffer Disabled (default) 1 = Buffer Enabled Bit 0 DRDY : Data Ready (Read Only) This bit duplicates the state of the DRDY pin. ACAL=1 enable calibration */ buf[0] = (0 << 3) | (1 << 2) | ( (buffer_en & 0x01) << 1);//enable the internal buffer // buf[0] = (0 << 3) | (1 << 2) | (0 << 1); // The internal buffer is prohibited //WriteReg(REG_STATUS, (0 << 3) | (1 << 2) | (1 << 1)); buf[1] = 0x08; /* ADCON: A/D Control Register (Address 02h) Bit 7 Reserved, always 0 (Read Only) Bits 6-5 CLK1, CLK0 : D0/CLKOUT Clock Out Rate Setting 00 = Clock Out OFF 01 = Clock Out Frequency = fCLKIN (default) 10 = Clock Out Frequency = fCLKIN/2 11 = Clock Out Frequency = fCLKIN/4 When not using CLKOUT, it is recommended that it be turned off. These bits can only be reset using the RESET pin. Bits 4-3 SDCS1, SCDS0: Sensor Detect Current Sources 00 = Sensor Detect OFF (default) 01 = Sensor Detect Current = 0.5 ¦Ì A 10 = Sensor Detect Current = 2 ¦Ì A 11 = Sensor Detect Current = 10¦Ì A The Sensor Detect Current Sources can be activated to verify the integrity of an external sensor supplying a signal to the ADS1255/6. A shorted sensor produces a very small signal while an open-circuit sensor produces a very large signal. Bits 2-0 PGA2, PGA1, PGA0: Programmable Gain Amplifier Setting 000 = 1 (default) 001 = 2 010 = 4 011 = 8 100 = 16 101 = 32 110 = 64 111 = 64 */ buf[2] = (0 << 5) | (0 << 3) | ( (gain & 0x07) << 0); //WriteReg(REG_ADCON, (0 << 5) | (0 << 2) | (GAIN_1 << 1)); /*choose 1: gain 1 ;input 5V/ buf[3] = s_tabDataRate[dataRate]; // DRATE_10SPS; *cs = 0; /* SPICS¡ = 0 */ spi->write(CMD_WREG | 0); /* Write command register, send the register address */ spi->write(0x03); /* Register number 4,Initialize the number -1*/ spi->write(buf[0]); /* Set the status register */ spi->write(buf[1]); /* Set the input channel parameters */ spi->write(buf[2]); /* Set the ADCON control register,gain */ spi->write(buf[3]); /* Set the output rate */ *cs =1; /* SPI cs = 1 */ wait_us(50); getMaxWaitDelay_us(); } /* ********************************************************************************************************* * name: DelayDATA * function: delay * parameter: NULL * The return value: NULL ********************************************************************************************************* */ void ADS1256::delayDATA(void) { /* Delay from last SCLK edge for DIN to first SCLK rising edge for DOUT: RDATA, RDATAC,RREG Commands min 50 CLK = 50 * 0.13uS = 6.5uS */ wait_us(10); /* The minimum time delay 6.5us */ } /* ********************************************************************************************************* * name: WriteReg * function: Write the corresponding register * parameter: _RegID: register ID * _RegValue: register Value * The return value: NULL ********************************************************************************************************* */ void ADS1256::writeReg(uint8_t _RegID, uint8_t _RegValue) { *cs = 0; /* SPI cs = 0 */ spi->write(CMD_WREG | _RegID); /*Write command register */ spi->write(0x00); /*Write the register number */ spi->write(_RegValue); /*send register value */ *cs =1; /* SPI cs = 1 */ } /* ********************************************************************************************************* * name: ReadReg * function: readVal the corresponding register * parameter: _RegID: register ID * The return value: read register value ********************************************************************************************************* */ uint8_t ADS1256::readReg(uint8_t _RegID) { uint8_t readVal; *cs = 0; /* SPI cs = 0 */ spi->write(CMD_RREG | _RegID); /* Write command register */ spi->write(0x00); /* Write the register number */ delayDATA(); /*delay time */ readVal = spi->write(0); /* Read the register values */ *cs =1; /* SPI cs = 1 */ return readVal; } /* ********************************************************************************************************* * name: WriteCmd * function: Sending a single byte order * parameter: _cmd : command * The return value: NULL ********************************************************************************************************* */ void ADS1256::writeCmd(uint8_t _cmd) { *cs = 0; /* SPI cs = 0 */ spi->write(_cmd); *cs =1; /* SPI cs = 1 */ } /* ********************************************************************************************************* * name: ReadChipID * function: Read the chip ID * parameter: _cmd : NULL * The return value: four high status register ********************************************************************************************************* */ uint8_t ADS1256::readChipID(void) { uint8_t id; //waitDRDY(); id = readReg(REG_STATUS); #ifdef DEBUG pc.printf("id = %02x\r\n", id); #endif return (id >> 4); } /* ********************************************************************************************************* * name: Setchannel * function: Configuration channel number * parameter: channel: channel number 0--7 * The return value: NULL ********************************************************************************************************* */ void ADS1256::setChannel() { /* Bits 7-4 PSEL3, PSEL2, PSEL1, PSEL0: Positive Input channel (AINP) Select 0000 = AIN0 (default) 0001 = AIN1 0010 = AIN2 (ADS1256 only) 0011 = AIN3 (ADS1256 only) 0100 = AIN4 (ADS1256 only) 0101 = AIN5 (ADS1256 only) 0110 = AIN6 (ADS1256 only) 0111 = AIN7 (ADS1256 only) 1xxx = AINCOM (when PSEL3 = 1, PSEL2, PSEL1, PSEL0 are ¡°don¡¯t care¡±) NOTE: When using an ADS1255 make sure to only select the available inputs. Bits 3-0 NSEL3, NSEL2, NSEL1, NSEL0: Negative Input channel (AINN)Select 0000 = AIN0 0001 = AIN1 (default) 0010 = AIN2 (ADS1256 only) 0011 = AIN3 (ADS1256 only) 0100 = AIN4 (ADS1256 only) 0101 = AIN5 (ADS1256 only) 0110 = AIN6 (ADS1256 only) 0111 = AIN7 (ADS1256 only) 1xxx = AINCOM (when NSEL3 = 1, NSEL2, NSEL1, NSEL0 are ¡°don¡¯t care¡±) */ if( channel > 15 ) { return; } writeReg(REG_MUX, (channel << 4) | (1<<3)); /* Bit3 = 1, AINN connection AINCOM */ } /* ********************************************************************************************************* * name: SetDiffchannel * function: The configuration difference channel * parameter: channel: channel number 0--3 * The return value: four high status register ********************************************************************************************************* */ void ADS1256::setDiffChannel() { /* Bits 7-4 PSEL3, PSEL2, PSEL1, PSEL0: Positive Input channel (AINP) Select 0000 = AIN0 (default) 0001 = AIN1 0010 = AIN2 (ADS1256 only) 0011 = AIN3 (ADS1256 only) 0100 = AIN4 (ADS1256 only) 0101 = AIN5 (ADS1256 only) 0110 = AIN6 (ADS1256 only) 0111 = AIN7 (ADS1256 only) 1xxx = AINCOM (when PSEL3 = 1, PSEL2, PSEL1, PSEL0 are ¡°don¡¯t care¡±) NOTE: When using an ADS1255 make sure to only select the available inputs. Bits 3-0 NSEL3, NSEL2, NSEL1, NSEL0: Negative Input channel (AINN)Select 0000 = AIN0 0001 = AIN1 (default) 0010 = AIN2 (ADS1256 only) 0011 = AIN3 (ADS1256 only) 0100 = AIN4 (ADS1256 only) 0101 = AIN5 (ADS1256 only) 0110 = AIN6 (ADS1256 only) 0111 = AIN7 (ADS1256 only) 1xxx = AINCOM (when NSEL3 = 1, NSEL2, NSEL1, NSEL0 are ¡°don¡¯t care¡±) */ //use channel = 3 for strain gauge bridge //use channel = 0 for Vout2 //use channel = 1 for Vout1 if (channel == 0) { writeReg(REG_MUX, (0 << 4) | 1); /* Diffchannel AIN0£¬ AIN1 */ } else if (channel == 1) { writeReg(REG_MUX, (2 << 4) | 3); /*Diffchannel AIN2£¬ AIN3 */ } else if (channel == 2) { writeReg(REG_MUX, (4 << 4) | 5); /*Diffchannel AIN4£¬ AIN5 */ } else if (channel == 3) { writeReg(REG_MUX, (6 << 4) | 7); /*Diffchannel AIN6£¬ AIN7 */ } } /* ********************************************************************************************************* * name: WaitDRDY * function: delay time wait for automatic calibration * parameter: NULL * The return value: NULL ********************************************************************************************************* */ void ADS1256::waitDRDY(void) { while ( nrdy->read() ); } void ADS1256::getMaxWaitDelay_us(void) { if(dataRate == 0x00) { maxWaitDelay_us = getDataRateVal_us(dataRate) + 8000; } else { maxWaitDelay_us = getDataRateVal_us(dataRate-1); } } /* ***********************`********************************************************************************** * name: ReadData * function: read ADC value * parameter: NULL * The return value: NULL ********************************************************************************************************* */ int32_t ADS1256::readData(void) { uint32_t readVal = 0; static uint8_t buf[3]; *cs = 0; /* SPI cs = 0 */ spi->write(CMD_RDATA); /* read ADC command */ delayDATA(); /*delay time */ /*Read the sample results 24bit*/ buf[0] = spi->write(0); buf[1] = spi->write(0); buf[2] = spi->write(0); readVal = ((uint32_t)buf[0] << 16) & 0x00FF0000; readVal |= ((uint32_t)buf[1] << 8); readVal |= buf[2]; *cs =1; //* CS = 1 /* Extend a signed number*/ if (readVal & 0x800000) { readVal |= 0xFF000000; } return (int32_t)readVal; } /* ********************************************************************************************************* * name: ADS1256::GetAdc * function: read ADC value * parameter: channel number 0--7 * The return value: ADC vaule (signed number) ********************************************************************************************************* */ /* ********************************************************************************************************* * name: ADS1256::ISR * function: Collection procedures * parameter: NULL * The return value: NULL ********************************************************************************************************* */ void ADS1256::isr(void) { if (scanMode == 0) /* 0 Single-ended input 8 channel, 1 Differential input 4 channels */ { setChannel(); /*Switch channel mode */ wait_us(5); writeCmd(CMD_SYNC); wait_us(5); writeCmd(CMD_WAKEUP); wait_us(25); if (channel == 0) { adcNow[7] = readData(); } else { adcNow[channel-1] = readData(); } if (++channel >= 8) { channel = 0; } } else /*Diffchannel*/ { setDiffChannel(); /* change Diffchannel */ wait_us(5); writeCmd(CMD_SYNC); wait_us(5); writeCmd(CMD_WAKEUP); wait_us(25); if (channel == 0) { adcNow[3] = readData(); } else { adcNow[channel-1] = readData(); } if (++channel >= 4) { channel = 0; } } } /* ********************************************************************************************************* * name: ADS1256::Scan * function: * parameter:NULL * The return value: 1 ********************************************************************************************************* */ uint8_t ADS1256::scan(void) { if (!(cs->read())) { isr(); return 1; } return 0; } /* ********************************************************************************************************* * name: Voltage_Convert * function: Voltage value conversion function * parameter: Vref : The reference voltage 3.3V or 5V * voltage : output DAC value * The return value: NULL ********************************************************************************************************* */ uint16_t ADS1256::voltageConvert(float Vref, float voltage) { uint16_t _D_; _D_ = (uint16_t)(65536 * voltage / Vref); return _D_; } void ADS1256::readDiffChannel(uint8_t nextChannel) { waitDRDY(); prevChannel = channel; channel = nextChannel; if(channel != prevChannel) { setDiffChannel(); /*Switch channel mode to next channel to get it started*/ wait_us(5); writeCmd(CMD_SYNC); wait_us(5); writeCmd(CMD_WAKEUP); wait_us(25); } adcNow[prevChannel] = readData(); //get data from prev channel while new channel is integrating // pc.printf(" adcNow = %d\r\n", adcNow[prevChannel]); } uint32_t ADS1256::getDataRateVal_us(uint8_t dataRateIndex) { static const uint32_t tabDataRateVal_us[16] = { 400000, 200000, 100000, 66667, 40000, 33334, 16667, 16667, 10000, 2000, 1000, 500, 267, 134, 34, 7 /*reset the default values */ }; return tabDataRateVal_us[dataRateIndex]; } void ADS1256::waitNDRDY(void) { while(!nrdy->read()); } void ADS1256::resync(void) { waitDRDY(); wait_us(2); writeCmd(CMD_SYNC); wait_us(5); writeCmd(CMD_WAKEUP); }