串口ok
This commit is contained in:
@@ -0,0 +1,526 @@
|
||||
|
||||
#include "ADC_ADS1256.h"
|
||||
|
||||
/* 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¡êo 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
|
||||
static void cfgADC(ADC_ADS1256_t *adc);
|
||||
static void delayDATA(ADC_ADS1256_t *adc);
|
||||
static void writeReg(ADC_ADS1256_t *adc, uint8_t _RegID, uint8_t _RegValue);
|
||||
static uint8_t readReg(ADC_ADS1256_t *adc, uint8_t _RegID);
|
||||
static void writeCmd(ADC_ADS1256_t *adc, uint8_t _cmd);
|
||||
static uint8_t readChipID(ADC_ADS1256_t *adc);
|
||||
static void setChannel(ADC_ADS1256_t *adc);
|
||||
static void setDiffChannel(ADC_ADS1256_t *adc);
|
||||
static void waitDRDY(ADC_ADS1256_t *adc);
|
||||
static int32_t readData(ADC_ADS1256_t *adc);
|
||||
static uint8_t getGainVal(ADC_ADS1256_t *adc);
|
||||
static void isr(ADC_ADS1256_t *adc);
|
||||
static uint8_t scan(ADC_ADS1256_t *adc);
|
||||
static uint16_t voltageConvert(ADC_ADS1256_t *adc, float Vref, float voltage);
|
||||
static void readDiffChannel(ADC_ADS1256_t *adc, uint8_t);
|
||||
static uint32_t getDataRateVal_us(ADC_ADS1256_t *adc, uint8_t);
|
||||
static void getMaxWaitDelay_us(ADC_ADS1256_t *adc);
|
||||
static void resync(ADC_ADS1256_t *adc);
|
||||
|
||||
bool ADC_ADS1256_init(ADC_ADS1256_t *adc, const char *name, SPI_DEV_t* dev, GPIO_TypeDef* drdy, uint16_t drdy_Pin)
|
||||
{
|
||||
adc->_dev = dev;
|
||||
adc->_drdy = drdy;
|
||||
adc->_drdy_Pin = drdy_Pin;
|
||||
adc->name = name;
|
||||
|
||||
adc->scanMode = 0;
|
||||
adc->gain = 0; /* GAIN */
|
||||
adc->dataRate = 7; /* DATA output speed*/
|
||||
adc->buffer_en = 1;
|
||||
adc->channel=0;
|
||||
|
||||
writeCmd(adc, CMD_WAKEUP);
|
||||
wait_us(25);
|
||||
|
||||
if (readChipID(adc) != 0x03)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
cfgADC(adc);
|
||||
|
||||
uint8_t mux = readReg(adc, REG_MUX);
|
||||
if (mux != 0x08)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
uint8_t getGainVal(ADC_ADS1256_t *adc)
|
||||
{
|
||||
return (1<< adc->gain); //e.g. 1,2,4,8,16,32,64
|
||||
}
|
||||
|
||||
void cfgADC(ADC_ADS1256_t *adc)
|
||||
{
|
||||
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(adc);
|
||||
|
||||
uint8_t buf[6]; /* 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[2] = (0 << 3) | (1 << 2) | ( (adc->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[3] = 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[4] = (0 << 5) | (0 << 3) | ( (adc->gain & 0x07) << 0);
|
||||
//WriteReg(REG_ADCON, (0 << 5) | (0 << 2) | (GAIN_1 << 1)); /*choose 1: gain 1 ;input 5V/
|
||||
buf[5] = s_tabDataRate[adc->dataRate]; // DRATE_100SPS;
|
||||
|
||||
SPI_DEV_select(adc->_dev); /* SPICS? = 0 */
|
||||
buf[0] = (CMD_WREG | 0); /* Write command register, send the register address */
|
||||
buf[1] = (0x03); /* Register number 4,Initialize the number -1*/
|
||||
|
||||
SPI_DEV_transfer(adc->_dev, buf, sizeof(buf), NULL, 0, 1);
|
||||
|
||||
SPI_DEV_unselect(adc->_dev); /* SPI cs = 1 */
|
||||
}
|
||||
|
||||
extern unsigned long getRunTimeCounterValue(void);
|
||||
void wait_us(unsigned long dt)
|
||||
{
|
||||
unsigned long t0 = getRunTimeCounterValue();
|
||||
unsigned long t1 = t0 + dt;
|
||||
while (getRunTimeCounterValue() < t1)
|
||||
{
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
void delayDATA(ADC_ADS1256_t *adc)
|
||||
{
|
||||
/*
|
||||
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 */
|
||||
}
|
||||
|
||||
|
||||
void writeReg(ADC_ADS1256_t *adc, uint8_t _RegID, uint8_t _RegValue)
|
||||
{
|
||||
SPI_DEV_select(adc->_dev); /* SPI cs = 0 */
|
||||
uint8_t buf[3];
|
||||
buf[0] = (CMD_WREG | _RegID); /*Write command register */
|
||||
buf[1] = (0x00); /*Write the register number */
|
||||
|
||||
buf[2] = (_RegValue); /*send register value */
|
||||
SPI_DEV_transfer(adc->_dev, buf, sizeof(buf), NULL, 0, 1);
|
||||
SPI_DEV_unselect(adc->_dev); /* SPI cs = 1 */
|
||||
}
|
||||
|
||||
uint8_t readReg(ADC_ADS1256_t *adc, uint8_t _RegID)
|
||||
{
|
||||
SPI_DEV_select(adc->_dev); /* SPI cs = 0 */
|
||||
uint8_t buf[2];
|
||||
buf[0] = (CMD_RREG | _RegID); /* Write command register */
|
||||
buf[1] = (0x00); /* Write the register number */
|
||||
SPI_DEV_transfer(adc->_dev, buf, 2, NULL, 0, 1);
|
||||
|
||||
delayDATA(adc); /*delay time */
|
||||
|
||||
SPI_DEV_transfer(adc->_dev, NULL, 0, buf, 1, 1);
|
||||
SPI_DEV_unselect(adc->_dev); /* SPI cs = 1 */
|
||||
|
||||
return buf[0];
|
||||
}
|
||||
|
||||
void writeCmd(ADC_ADS1256_t *adc, uint8_t _cmd)
|
||||
{
|
||||
SPI_DEV_select(adc->_dev); /* SPI cs = 0 */
|
||||
uint8_t buf[1];
|
||||
buf[0] = _cmd;
|
||||
SPI_DEV_transfer(adc->_dev, buf, 1, NULL, 0, 1);
|
||||
SPI_DEV_unselect(adc->_dev); /* SPI cs = 1 */
|
||||
}
|
||||
|
||||
uint8_t readChipID(ADC_ADS1256_t *adc)
|
||||
{
|
||||
uint8_t id;
|
||||
|
||||
waitDRDY(adc);
|
||||
id = readReg(adc, REG_STATUS);
|
||||
#ifdef DEBUG
|
||||
printf("ADC id = %02x\r\n", id);
|
||||
#endif
|
||||
return (id >> 4);
|
||||
}
|
||||
|
||||
void setChannel(ADC_ADS1256_t *adc)
|
||||
{
|
||||
/*
|
||||
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( adc->channel > 15 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
writeReg(adc, REG_MUX, (adc->channel << 4) | (1<<3)); /* Bit3 = 1, AINN connection AINCOM */
|
||||
}
|
||||
|
||||
void setDiffChannel(ADC_ADS1256_t *adc)
|
||||
{
|
||||
/*
|
||||
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 (adc->channel == 0)
|
||||
{
|
||||
writeReg(adc, REG_MUX, (0 << 4) | 1); /* Diffchannel AIN0¡ê? AIN1 */
|
||||
}
|
||||
else if (adc->channel == 1)
|
||||
{
|
||||
writeReg(adc, REG_MUX, (2 << 4) | 3); /*Diffchannel AIN2¡ê? AIN3 */
|
||||
}
|
||||
else if (adc->channel == 2)
|
||||
{
|
||||
writeReg(adc, REG_MUX, (4 << 4) | 5); /*Diffchannel AIN4¡ê? AIN5 */
|
||||
}
|
||||
else if (adc->channel == 3)
|
||||
{
|
||||
writeReg(adc, REG_MUX, (6 << 4) | 7); /*Diffchannel AIN6¡ê? AIN7 */
|
||||
}
|
||||
}
|
||||
|
||||
void waitDRDY(ADC_ADS1256_t *adc)
|
||||
{
|
||||
while ( HAL_GPIO_ReadPin(adc->_drdy, adc->_drdy_Pin) );
|
||||
}
|
||||
|
||||
int32_t readData(ADC_ADS1256_t *adc)
|
||||
{
|
||||
uint32_t readVal = 0;
|
||||
static uint8_t buf[3];
|
||||
|
||||
SPI_DEV_select(adc->_dev); /* SPI cs = 0 */
|
||||
|
||||
/* read ADC command */
|
||||
buf[0] = CMD_RDATA;
|
||||
SPI_DEV_transfer(adc->_dev, buf, 1, NULL, 0, 1);
|
||||
|
||||
delayDATA(adc); /*delay time */
|
||||
|
||||
/*Read the sample results 24bit*/
|
||||
SPI_DEV_transfer(adc->_dev, NULL, 0, buf, 3, 1);
|
||||
|
||||
readVal = ((uint32_t)buf[0] << 16) & 0x00FF0000;
|
||||
readVal |= ((uint32_t)buf[1] << 8);
|
||||
readVal |= buf[2];
|
||||
|
||||
SPI_DEV_unselect(adc->_dev); //* CS = 1
|
||||
/* Extend a signed number*/
|
||||
if (readVal & 0x800000)
|
||||
{
|
||||
readVal |= 0xFF000000;
|
||||
}
|
||||
|
||||
return (int32_t)readVal;
|
||||
}
|
||||
|
||||
|
||||
void ADC_ADS1256_update(ADC_ADS1256_t *adc)
|
||||
{
|
||||
if (adc->scanMode == 0) /* 0 Single-ended input 8 channel, 1 Differential input 4 channels */
|
||||
{
|
||||
setChannel(adc); /*Switch channel mode */
|
||||
wait_us(5);
|
||||
|
||||
writeCmd(adc, CMD_SYNC);
|
||||
wait_us(5);
|
||||
|
||||
writeCmd(adc, CMD_WAKEUP);
|
||||
wait_us(25);
|
||||
|
||||
if (adc->channel == 0)
|
||||
{
|
||||
adc->adcNow[7] = readData(adc);
|
||||
}
|
||||
else
|
||||
{
|
||||
adc->adcNow[adc->channel-1] = readData(adc);
|
||||
}
|
||||
|
||||
if (++adc->channel >= 8)
|
||||
{
|
||||
adc->channel = 0;
|
||||
}
|
||||
}
|
||||
else /*Diffchannel*/
|
||||
{
|
||||
|
||||
setDiffChannel(adc); /* change Diffchannel */
|
||||
wait_us(5);
|
||||
|
||||
writeCmd(adc, CMD_SYNC);
|
||||
wait_us(5);
|
||||
|
||||
writeCmd(adc, CMD_WAKEUP);
|
||||
wait_us(25);
|
||||
|
||||
if (adc->channel == 0)
|
||||
{
|
||||
adc->adcNow[3] = readData(adc);
|
||||
}
|
||||
else
|
||||
{
|
||||
adc->adcNow[adc->channel-1] = readData(adc);
|
||||
}
|
||||
|
||||
if (++adc->channel >= 4)
|
||||
{
|
||||
adc->channel = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t voltageConvert(ADC_ADS1256_t *adc, float Vref, float voltage)
|
||||
{
|
||||
uint16_t _D_;
|
||||
_D_ = (uint16_t)(65536 * voltage / Vref);
|
||||
|
||||
return _D_;
|
||||
}
|
||||
|
||||
void readDiffChannel(ADC_ADS1256_t *adc, uint8_t nextChannel)
|
||||
{
|
||||
waitDRDY(adc);
|
||||
adc->prevChannel = adc->channel;
|
||||
adc->channel = nextChannel;
|
||||
if(adc->channel != adc->prevChannel)
|
||||
{
|
||||
setDiffChannel(adc); /*Switch channel mode to next channel to get it started*/
|
||||
wait_us(5);
|
||||
|
||||
writeCmd(adc, CMD_SYNC);
|
||||
wait_us(5);
|
||||
|
||||
writeCmd(adc, CMD_WAKEUP);
|
||||
wait_us(25);
|
||||
}
|
||||
adc->adcNow[adc->prevChannel] = readData(adc); //get data from prev channel while new channel is integrating
|
||||
// pc.printf(" adcNow = %d\r\n", adcNow[prevChannel]);
|
||||
}
|
||||
|
||||
uint32_t getDataRateVal_us(ADC_ADS1256_t *adc, 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 resync(ADC_ADS1256_t *adc)
|
||||
{
|
||||
waitDRDY(adc);
|
||||
wait_us(2);
|
||||
|
||||
writeCmd(adc, CMD_SYNC);
|
||||
wait_us(5);
|
||||
|
||||
writeCmd(adc, CMD_WAKEUP);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user