ADS1256 program
Revision 0:897d3bb0accd, committed 2017-12-01
- Comitter:
- laserdad
- Date:
- Fri Dec 01 21:31:48 2017 +0000
- Commit message:
- last known version;
Changed in this revision
ADS1256.cpp | Show annotated file Show diff for this revision Revisions of this file |
ADS1256.h | Show annotated file Show diff for this revision Revisions of this file |
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ADS1256.cpp Fri Dec 01 21:31:48 2017 +0000 @@ -0,0 +1,582 @@ +#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); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ADS1256.h Fri Dec 01 21:31:48 2017 +0000 @@ -0,0 +1,141 @@ +#ifndef __ADS1256_H__ +#define __ADS1256_H__ + +#include "mbed.h" + +#define ADS1256_SPI_MODE 1 +#define DRATE_MAX 16 +#define DEBUG + +#define ADS1256_GAIN_1 0 /* GAIN 1 */ +#define ADS1256_GAIN_2 1 /*GAIN 2 */ +#define ADS1256_GAIN_4 2 /*GAIN 4 */ +#define ADS1256_GAIN_8 3 /*GAIN 8 */ +#define ADS1256_GAIN_16 4 /* GAIN 16 */ +#define ADS1256_GAIN_32 5 /*GAIN 32 */ +#define ADS1256_GAIN_64 6 /*GAIN 64 */ + + +#define ADS1256_30000SPS 15 +#define ADS1256_15000SPS 14 +#define ADS1256_7500SPS 13 +#define ADS1256_3750SPS 12 +#define ADS1256_2000SPS 11 +#define ADS1256_1000SPS 10 +#define ADS1256_500SPS 9 +#define ADS1256_100SPS 8 +#define ADS1256_60SPS 7 +#define ADS1256_50SPS 6 +#define ADS1256_30SPS 5 +#define ADS1256_25SPS 4 +#define ADS1256_15SPS 3 +#define ADS1256_10SPS 2 +#define ADS1256_5SPS 1 +#define ADS1256_2d5SPS 0 + + +class ADS1256 +{ + SPI *spi; + DigitalOut *cs; + DigitalIn *nrdy; + + public: + ADS1256(SPI *, DigitalIn *, DigitalOut *); + uint8_t gain; + uint8_t dataRate; + int32_t adcNow[8]; /* ADC Conversion value */ + uint8_t channel; /* The current channel*/ + uint8_t prevChannel; /* The previous channel --when muxing */ + uint8_t scanMode; /*Scanning mode, 0 = Single-ended input 8 channel; 1= Differential input 4 channels*/ + uint8_t buffer_en; + uint32_t maxWaitDelay_us; + /* gain channelî */ + + + /* Sampling speed choice*/ + /* + 11110000 = 30,000SPS (default) + 11100000 = 15,000SPS + 11010000 = 7,500SPS + 11000000 = 3,750SPS + 10110000 = 2,000SPS + 10100001 = 1,000SPS + 10010010 = 500SPS + 10000010 = 100SPS + 01110010 = 60SPS + 01100011 = 50SPS + 01010011 = 30SPS + 01000011 = 25SPS + 00110011 = 15SPS + 00100011 = 10SPS + 00010011 = 5SPS + 00000011 = 2.5SPS + */ + + + /*Register definitions Table 23. Register Map --- ADS1256 datasheet Page 30*/ + enum + { + /*Register address, followed by reset the default values */ + REG_STATUS = 0, // x1H + REG_MUX = 1, // 01H + REG_ADCON = 2, // 20H + REG_DRATE = 3, // F0H + REG_IO = 4, // E0H + REG_OFC0 = 5, // xxH + REG_OFC1 = 6, // xxH + REG_OFC2 = 7, // xxH + REG_FSC0 = 8, // xxH + REG_FSC1 = 9, // xxH + REG_FSC2 = 10, // xxH + }; + + /* Command definition£º TTable 24. Command Definitions --- ADS1256 datasheet Page 34 */ + enum + { + CMD_WAKEUP = 0x00, // Completes SYNC and Exits Standby Mode 0000 0000 (00h) + CMD_RDATA = 0x01, // Read Data 0000 0001 (01h) + CMD_RDATAC = 0x03, // Read Data Continuously 0000 0011 (03h) + CMD_SDATAC = 0x0F, // Stop Read Data Continuously 0000 1111 (0Fh) + CMD_RREG = 0x10, // Read from REG rrr 0001 rrrr (1xh) + CMD_WREG = 0x50, // Write to REG rrr 0101 rrrr (5xh) + CMD_SELFCAL = 0xF0, // Offset and Gain Self-Calibration 1111 0000 (F0h) + CMD_SELFOCAL= 0xF1, // Offset Self-Calibration 1111 0001 (F1h) + CMD_SELFGCAL= 0xF2, // Gain Self-Calibration 1111 0010 (F2h) + CMD_SYSOCAL = 0xF3, // System Offset Calibration 1111 0011 (F3h) + CMD_SYSGCAL = 0xF4, // System Gain Calibration 1111 0100 (F4h) + CMD_SYNC = 0xFC, // Synchronize the A/D Conversion 1111 1100 (FCh) + CMD_STANDBY = 0xFD, // Begin Standby Mode 1111 1101 (FDh) + CMD_RESET = 0xFE, // Reset to Power-Up Values 1111 1110 (FEh) + }; + + + + + + //declare functions + void setSpi(void); + void cfgADC(void); + void delayDATA(void); + void writeReg(uint8_t _RegID, uint8_t _RegValue); + uint8_t readReg(uint8_t _RegID); + void writeCmd(uint8_t _cmd); + uint8_t readChipID(void); + void setChannel(); + void setDiffChannel(); + void waitDRDY(void); + void waitNDRDY(void); + int32_t readData(void); + uint8_t getGainVal(void); + void isr(void); + uint8_t scan(void); + uint16_t voltageConvert(float Vref, float voltage); + void readDiffChannel(uint8_t); + uint32_t getDataRateVal_us(uint8_t); + void getMaxWaitDelay_us(void); + void resync(void); + +}; + +#endif \ No newline at end of file