ADS1015.c
/**************************************************************************/
/*!
@file Adafruit_ADS1015.c
@author K.Townsend (Adafruit Industries)
@license BSD (see license.txt)
Driver for the ADS1015/ADS1115 ADC
This is a library for the Adafruit MPL115A2 breakout
----> https://www.adafruit.com/products/???
Adafruit invests time and resources providing this open source code,
please support Adafruit and open-source hardware by purchasing
products from Adafruit!
@section HISTORY
v1.0 - First release
Edit by FangZheng 2014-12-11
*/
#include "global.h"
static Uint16 m_i2cAddress;
static Uint16 m_conversionDelay;
static Uint16 m_bitShift;
static adsGain_t m_gain;
static Uint16 m_chn;
#if 0
/**************************************************************************/
/*!
@brief Writes 16-bits to the specified destination register
*/
/**************************************************************************/
static void writeRegister(Uint16 i2cAddress, Uint16 reg, Uint16 value)
{
Wire.beginTransmission(i2cAddress);
i2cwrite((Uint16)reg);
i2cwrite((Uint16)(value >> 8));
i2cwrite((Uint16)(value & 0xFF));
Wire.endTransmission();
}
/**************************************************************************/
/*!
@brief Writes 16-bits to the specified destination register
*/
/**************************************************************************/
static Uint16 readRegister(Uint16 i2cAddress, Uint16 reg)
{
Wire.beginTransmission(i2cAddress);
i2cwrite(ADS1015_REG_POINTER_CONVERT);
Wire.endTransmission();
Wire.requestFrom(i2cAddress, (Uint16)2);
return ((i2cread() << 8) | i2cread());
}
#endif
/**************************************************************************/
/*!
@brief Instantiates a new ADS1015 class w/appropriate properties
*/
/**************************************************************************/
void ads1015_init(void)
{
m_i2cAddress = ADS1015_ADDRESS;
m_conversionDelay = ADS1015_CONVERSIONDELAY;
m_bitShift = 4;
m_gain = GAIN_ONE; /* +/- 6.144V range (limited to VDD +0.3V max!) */
m_chn = 0;
}
#if 0
/**************************************************************************/
/*!
@brief Sets the gain and input voltage range
*/
/**************************************************************************/
void setGain(adsGain_t gain)
{
m_gain = gain;
}
/**************************************************************************/
/*!
@brief Gets a gain and input voltage range
*/
/**************************************************************************/
adsGain_t getGain()
{
return m_gain;
}
#endif
/**************************************************************************/
/*!
@brief Gets a single-ended ADC reading from the specified channel
*/
/**************************************************************************/
Uint16 readADC_SingleEnded(Uint16 channel)
{
Uint16 config;
if (channel > 3)
{
return 0;
}
// Start with default values
config = ADS1015_REG_CONFIG_CQUE_NONE | // Disable the comparator (default val)
ADS1015_REG_CONFIG_CLAT_NONLAT | // Non-latching (default val)
ADS1015_REG_CONFIG_CPOL_ACTVLOW | // Alert/Rdy active low (default val)
ADS1015_REG_CONFIG_CMODE_TRAD | // Traditional comparator (default val)
ADS1015_REG_CONFIG_DR_1600SPS | // 1600 samples per second (default)
ADS1015_REG_CONFIG_MODE_SINGLE; // Single-shot mode (default)
// Set PGA/voltage range
config |= m_gain;
// Set single-ended input channel
switch (channel)
{
case (0):
config |= ADS1015_REG_CONFIG_MUX_SINGLE_0;
break;
case (1):
config |= ADS1015_REG_CONFIG_MUX_SINGLE_1;
break;
case (2):
config |= ADS1015_REG_CONFIG_MUX_SINGLE_2;
break;
case (3):
config |= ADS1015_REG_CONFIG_MUX_SINGLE_3;
break;
}
// Set 'start single-conversion' bit
config |= ADS1015_REG_CONFIG_OS_SINGLE;
// Write config register to the ADC
writeRegister(m_i2cAddress, ADS1015_REG_POINTER_CONFIG, config);
// Wait for the conversion to complete
//DELAY_US(m_conversionDelay);
DELAY_US(350);
// Read the conversion results
// Shift 12-bit results right 4 bits for the ADS1015
return readRegister(m_i2cAddress, ADS1015_REG_POINTER_CONVERT) >> m_bitShift;
}
void read_adc_config(void)
{
Uint16 config;
// Start with default values
config = ADS1015_REG_CONFIG_CQUE_NONE | // Disable the comparator (default val)
ADS1015_REG_CONFIG_CLAT_NONLAT | // Non-latching (default val)
ADS1015_REG_CONFIG_CPOL_ACTVLOW | // Alert/Rdy active low (default val)
ADS1015_REG_CONFIG_CMODE_TRAD | // Traditional comparator (default val)
ADS1015_REG_CONFIG_DR_1600SPS | // 1600 samples per second (default)
ADS1015_REG_CONFIG_MODE_SINGLE; // Single-shot mode (default)
// Set PGA/voltage range
config |= m_gain;
// Set single-ended input channel
switch (m_chn)
{
case (0):
config |= ADS1015_REG_CONFIG_MUX_SINGLE_0;
break;
case (1):
config |= ADS1015_REG_CONFIG_MUX_SINGLE_1;
break;
case (2):
config |= ADS1015_REG_CONFIG_MUX_SINGLE_2;
break;
case (3):
config |= ADS1015_REG_CONFIG_MUX_SINGLE_3;
break;
}
// Set 'start single-conversion' bit
config |= ADS1015_REG_CONFIG_OS_SINGLE;
// Write config register to the ADC
writeRegister(m_i2cAddress, ADS1015_REG_POINTER_CONFIG, config);
}
void read_adc_reg(volatile Uint16 *res0, volatile Uint16 *res1)
{
if(m_chn)
{
*res1 = readRegister(m_i2cAddress, ADS1015_REG_POINTER_CONVERT) >> m_bitShift;
m_chn = 0;
}
else
{
*res0 = readRegister(m_i2cAddress, ADS1015_REG_POINTER_CONVERT) >> m_bitShift;
m_chn = 1;
}
}
void get_adc(volatile Uint16 *res0, volatile Uint16 *res1)
{
#define PER_CNT 6
static volatile Uint16 i = 0;
if(i == 0)
{
read_adc_config();
}
if(i == PER_CNT)
{
read_adc_reg(res0, res1);
}
if(i++ > PER_CNT) i = 0;
}
#if 0
/**************************************************************************/
/*!
@brief Reads the conversion results, measuring the voltage
difference between the P (AIN0) and N (AIN1) input. Generates
a signed value since the difference can be either
positive or negative.
*/
/**************************************************************************/
int16_t readADC_Differential_0_1(void)
{
Uint16 res, config;
// Start with default values
config = ADS1015_REG_CONFIG_CQUE_NONE | // Disable the comparator (default val)
ADS1015_REG_CONFIG_CLAT_NONLAT | // Non-latching (default val)
ADS1015_REG_CONFIG_CPOL_ACTVLOW | // Alert/Rdy active low (default val)
ADS1015_REG_CONFIG_CMODE_TRAD | // Traditional comparator (default val)
ADS1015_REG_CONFIG_DR_1600SPS | // 1600 samples per second (default)
ADS1015_REG_CONFIG_MODE_SINGLE; // Single-shot mode (default)
// Set PGA/voltage range
config |= m_gain;
// Set channels
config |= ADS1015_REG_CONFIG_MUX_DIFF_0_1; // AIN0 = P, AIN1 = N
// Set 'start single-conversion' bit
config |= ADS1015_REG_CONFIG_OS_SINGLE;
// Write config register to the ADC
writeRegister(m_i2cAddress, ADS1015_REG_POINTER_CONFIG, config);
// Wait for the conversion to complete
DELAY_US(m_conversionDelay);
// Read the conversion results
res = readRegister(m_i2cAddress, ADS1015_REG_POINTER_CONVERT) >> m_bitShift;
if (m_bitShift == 0)
{
return (int16)res;
}
else
{
// Shift 12-bit results right 4 bits for the ADS1015,
// making sure we keep the sign bit intact
if (res > 0x07FF)
{
// negative number - extend the sign to 16th bit
res |= 0xF000;
}
return (int16)res;
}
}
/**************************************************************************/
/*!
@brief Reads the conversion results, measuring the voltage
difference between the P (AIN2) and N (AIN3) input. Generates
a signed value since the difference can be either
positive or negative.
*/
/**************************************************************************/
int16_t readADC_Differential_2_3(void)
{
Uint16 res, config;
// Start with default values
config = ADS1015_REG_CONFIG_CQUE_NONE | // Disable the comparator (default val)
ADS1015_REG_CONFIG_CLAT_NONLAT | // Non-latching (default val)
ADS1015_REG_CONFIG_CPOL_ACTVLOW | // Alert/Rdy active low (default val)
ADS1015_REG_CONFIG_CMODE_TRAD | // Traditional comparator (default val)
ADS1015_REG_CONFIG_DR_1600SPS | // 1600 samples per second (default)
ADS1015_REG_CONFIG_MODE_SINGLE; // Single-shot mode (default)
// Set PGA/voltage range
config |= m_gain;
// Set channels
config |= ADS1015_REG_CONFIG_MUX_DIFF_2_3; // AIN2 = P, AIN3 = N
// Set 'start single-conversion' bit
config |= ADS1015_REG_CONFIG_OS_SINGLE;
// Write config register to the ADC
writeRegister(m_i2cAddress, ADS1015_REG_POINTER_CONFIG, config);
// Wait for the conversion to complete
DELAY_US(m_conversionDelay);
// Read the conversion results
res = readRegister(m_i2cAddress, ADS1015_REG_POINTER_CONVERT) >> m_bitShift;
if (m_bitShift == 0)
{
return (int16)res;
}
else
{
// Shift 12-bit results right 4 bits for the ADS1015,
// making sure we keep the sign bit intact
if (res > 0x07FF)
{
// negative number - extend the sign to 16th bit
res |= 0xF000;
}
return (int16)res;
}
}
/**************************************************************************/
/*!
@brief Sets up the comparator to operate in basic mode, causing the
ALERT/RDY pin to assert (go from high to low) when the ADC
value exceeds the specified threshold.
This will also set the ADC in continuous conversion mode.
*/
/**************************************************************************/
void startComparator_SingleEnded(Uint16 channel, int16_t threshold)
{
// Start with default values
Uint16 config = ADS1015_REG_CONFIG_CQUE_1CONV | // Comparator enabled and asserts on 1 match
ADS1015_REG_CONFIG_CLAT_LATCH | // Latching mode
ADS1015_REG_CONFIG_CPOL_ACTVLOW | // Alert/Rdy active low (default val)
ADS1015_REG_CONFIG_CMODE_TRAD | // Traditional comparator (default val)
ADS1015_REG_CONFIG_DR_1600SPS | // 1600 samples per second (default)
ADS1015_REG_CONFIG_MODE_CONTIN | // Continuous conversion mode
ADS1015_REG_CONFIG_MODE_CONTIN; // Continuous conversion mode
// Set PGA/voltage range
config |= m_gain;
// Set single-ended input channel
switch (channel)
{
case (0):
config |= ADS1015_REG_CONFIG_MUX_SINGLE_0;
break;
case (1):
config |= ADS1015_REG_CONFIG_MUX_SINGLE_1;
break;
case (2):
config |= ADS1015_REG_CONFIG_MUX_SINGLE_2;
break;
case (3):
config |= ADS1015_REG_CONFIG_MUX_SINGLE_3;
break;
}
// Set the high threshold register
// Shift 12-bit results left 4 bits for the ADS1015
writeRegister(m_i2cAddress, ADS1015_REG_POINTER_HITHRESH, threshold << m_bitShift);
// Write config register to the ADC
writeRegister(m_i2cAddress, ADS1015_REG_POINTER_CONFIG, config);
}
/**************************************************************************/
/*!
@brief In order to clear the comparator, we need to read the
conversion results. This function reads the last conversion
results without changing the config value.
*/
/**************************************************************************/
int16_t getLastConversionResults(void)
{
Uint16 res;
// Wait for the conversion to complete
DELAY_US(m_conversionDelay);
// Read the conversion results
res = readRegister(m_i2cAddress, ADS1015_REG_POINTER_CONVERT) >> m_bitShift;
if (m_bitShift == 0)
{
return (int16)res;
}
else
{
// Shift 12-bit results right 4 bits for the ADS1015,
// making sure we keep the sign bit intact
if (res > 0x07FF)
{
// negative number - extend the sign to 16th bit
res |= 0xF000;
}
return (int16)res;
}
}
#endif
ADS1015.h
/**************************************************************************/
/*!
@file Adafruit_ADS1015.h
@author K. Townsend (Adafruit Industries)
@license BSD (see license.txt)
This is a library for the Adafruit ADS1015 breakout board
----> https://www.adafruit.com/products/???
Adafruit invests time and resources providing this open source code,
please support Adafruit and open-source hardware by purchasing
products from Adafruit!
@section HISTORY
v1.0 - First release
v1.1 - Added ADS1115 support - W. Earl
*/
/**************************************************************************/
#ifndef _ADS_1015_H_
#define _ADS_1015_H_
/*=========================================================================
I2C ADDRESS/BITS
-----------------------------------------------------------------------*/
#define ADS1015_ADDRESS (0x90) // 1001 000 (ADDR = GND)
/*=========================================================================*/
/*=========================================================================
CONVERSION DELAY (in uS)
-----------------------------------------------------------------------*/
#define ADS1015_CONVERSIONDELAY (10)
#define ADS1115_CONVERSIONDELAY (8)
/*=========================================================================*/
/*=========================================================================
POINTER REGISTER
-----------------------------------------------------------------------*/
#define ADS1015_REG_POINTER_MASK (0x03)
#define ADS1015_REG_POINTER_CONVERT (0x00)
#define ADS1015_REG_POINTER_CONFIG (0x01)
#define ADS1015_REG_POINTER_LOWTHRESH (0x02)
#define ADS1015_REG_POINTER_HITHRESH (0x03)
/*=========================================================================*/
/*=========================================================================
CONFIG REGISTER
-----------------------------------------------------------------------*/
#define ADS1015_REG_CONFIG_OS_MASK (0x8000)
#define ADS1015_REG_CONFIG_OS_SINGLE (0x8000) // Write: Set to start a single-conversion
#define ADS1015_REG_CONFIG_OS_BUSY (0x0000) // Read: Bit = 0 when conversion is in progress
#define ADS1015_REG_CONFIG_OS_NOTBUSY (0x8000) // Read: Bit = 1 when device is not performing a conversion
#define ADS1015_REG_CONFIG_MUX_MASK (0x7000)
#define ADS1015_REG_CONFIG_MUX_DIFF_0_1 (0x0000) // Differential P = AIN0, N = AIN1 (default)
#define ADS1015_REG_CONFIG_MUX_DIFF_0_3 (0x1000) // Differential P = AIN0, N = AIN3
#define ADS1015_REG_CONFIG_MUX_DIFF_1_3 (0x2000) // Differential P = AIN1, N = AIN3
#define ADS1015_REG_CONFIG_MUX_DIFF_2_3 (0x3000) // Differential P = AIN2, N = AIN3
#define ADS1015_REG_CONFIG_MUX_SINGLE_0 (0x4000) // Single-ended AIN0
#define ADS1015_REG_CONFIG_MUX_SINGLE_1 (0x5000) // Single-ended AIN1
#define ADS1015_REG_CONFIG_MUX_SINGLE_2 (0x6000) // Single-ended AIN2
#define ADS1015_REG_CONFIG_MUX_SINGLE_3 (0x7000) // Single-ended AIN3
#define ADS1015_REG_CONFIG_PGA_MASK (0x0E00)
#define ADS1015_REG_CONFIG_PGA_6_144V (0x0000) // +/-6.144V range = Gain 2/3
#define ADS1015_REG_CONFIG_PGA_4_096V (0x0200) // +/-4.096V range = Gain 1
#define ADS1015_REG_CONFIG_PGA_2_048V (0x0400) // +/-2.048V range = Gain 2 (default)
#define ADS1015_REG_CONFIG_PGA_1_024V (0x0600) // +/-1.024V range = Gain 4
#define ADS1015_REG_CONFIG_PGA_0_512V (0x0800) // +/-0.512V range = Gain 8
#define ADS1015_REG_CONFIG_PGA_0_256V (0x0A00) // +/-0.256V range = Gain 16
#define ADS1015_REG_CONFIG_MODE_MASK (0x0100)
#define ADS1015_REG_CONFIG_MODE_CONTIN (0x0000) // Continuous conversion mode
#define ADS1015_REG_CONFIG_MODE_SINGLE (0x0100) // Power-down single-shot mode (default)
#define ADS1015_REG_CONFIG_DR_MASK (0x00E0)
#define ADS1015_REG_CONFIG_DR_128SPS (0x0000) // 128 samples per second
#define ADS1015_REG_CONFIG_DR_250SPS (0x0020) // 250 samples per second
#define ADS1015_REG_CONFIG_DR_490SPS (0x0040) // 490 samples per second
#define ADS1015_REG_CONFIG_DR_920SPS (0x0060) // 920 samples per second
#define ADS1015_REG_CONFIG_DR_1600SPS (0x0080) // 1600 samples per second (default)
#define ADS1015_REG_CONFIG_DR_2400SPS (0x00A0) // 2400 samples per second
#define ADS1015_REG_CONFIG_DR_3300SPS (0x00C0) // 3300 samples per second
#define ADS1015_REG_CONFIG_CMODE_MASK (0x0010)
#define ADS1015_REG_CONFIG_CMODE_TRAD (0x0000) // Traditional comparator with hysteresis (default)
#define ADS1015_REG_CONFIG_CMODE_WINDOW (0x0010) // Window comparator
#define ADS1015_REG_CONFIG_CPOL_MASK (0x0008)
#define ADS1015_REG_CONFIG_CPOL_ACTVLOW (0x0000) // ALERT/RDY pin is low when active (default)
#define ADS1015_REG_CONFIG_CPOL_ACTVHI (0x0008) // ALERT/RDY pin is high when active
#define ADS1015_REG_CONFIG_CLAT_MASK (0x0004) // Determines if ALERT/RDY pin latches once asserted
#define ADS1015_REG_CONFIG_CLAT_NONLAT (0x0000) // Non-latching comparator (default)
#define ADS1015_REG_CONFIG_CLAT_LATCH (0x0004) // Latching comparator
#define ADS1015_REG_CONFIG_CQUE_MASK (0x0003)
#define ADS1015_REG_CONFIG_CQUE_1CONV (0x0000) // Assert ALERT/RDY after one conversions
#define ADS1015_REG_CONFIG_CQUE_2CONV (0x0001) // Assert ALERT/RDY after two conversions
#define ADS1015_REG_CONFIG_CQUE_4CONV (0x0002) // Assert ALERT/RDY after four conversions
#define ADS1015_REG_CONFIG_CQUE_NONE (0x0003) // Disable the comparator and put ALERT/RDY in high state (default)
/*=========================================================================*/
typedef enum
{
GAIN_TWOTHIRDS = ADS1015_REG_CONFIG_PGA_6_144V,
GAIN_ONE = ADS1015_REG_CONFIG_PGA_4_096V,
GAIN_TWO = ADS1015_REG_CONFIG_PGA_2_048V,
GAIN_FOUR = ADS1015_REG_CONFIG_PGA_1_024V,
GAIN_EIGHT = ADS1015_REG_CONFIG_PGA_0_512V,
GAIN_SIXTEEN = ADS1015_REG_CONFIG_PGA_0_256V
} adsGain_t;
extern void ads1015_init(void);
extern Uint16 readADC_SingleEnded(Uint16 channel);
extern void get_adc(volatile Uint16 *res0, volatile Uint16 *res1);
#endif
i2c
static void IIC_Delay(void)
{
DELAY_US(1);
}
static void IIC_Delay_Half(void)
{
DELAY_US(1);
}
static Uint16 IsCharOne(void)
{
Uint16 retcode = 0;
if (SDA_IN())
{
retcode = 1;
}
return retcode;
}
static void StartRom(void)
{
SET_SDA_OUT();
SET_SCL_OUT();
SetSDA();
IIC_Delay();
SetSCL();
IIC_Delay();
ClrSDA();
IIC_Delay();
ClrSCL();
IIC_Delay();
}
static void StopRom(void)
{
ClrSDA();
IIC_Delay();
SetSCL();
IIC_Delay();
SetSDA();
IIC_Delay();
ClrSCL();
IIC_Delay();
}
static Uint16 SendToRom(Uint16 data)
{
Uint16 count, retcode = 0;
for (count = 0; count < 8; count++)
{
if ((data & BIT7) == BIT7)
{
SetSDA();
}
else
{
ClrSDA();
}
IIC_Delay();
SetSCL();
data = data << 1;
IIC_Delay();
ClrSCL();
//IIC_Delay();
}
SET_SDA_IN();
IIC_Delay();
SetSCL();
//IIC_Delay();
IIC_Delay_Half();
retcode = IsCharOne();
IIC_Delay_Half();
//IIC_Delay();
ClrSCL();
IIC_Delay();
SET_SDA_OUT();
return retcode;
}
static Uint16 ReceiveFromRom(void)
{
Uint16 m = 0, count;
SET_SDA_IN();
IIC_Delay();
for (count = 0; count < 8; count++)
{
m = m << 1;
SetSCL();
//IIC_Delay();
//DELAY_US(3);
IIC_Delay_Half();
if (IsCharOne())
{
m |= BIT0;
}
//IIC_Delay();
//DELAY_US(2);
IIC_Delay_Half();
ClrSCL();
IIC_Delay();
}
SET_SDA_OUT();
return m;
}
static void mack(void)
{
ClrSDA();
IIC_Delay();
SetSCL();
IIC_Delay();
ClrSCL();
IIC_Delay();
}
static void nmack(void)
{
SetSDA();
IIC_Delay();
SetSCL();
IIC_Delay();
ClrSCL();
IIC_Delay();
}
void writeRegister(Uint16 i2cAddress, Uint16 reg, Uint16 value)
{
Uint16 i;
EALLOW;
for(i = 0; i < ADS_RE_COUNT; i++)
{
StopRom();
//IIC_Delay();
IIC_Delay();
StartRom();
if(SendToRom(i2cAddress) == 1)
continue;
if(SendToRom(reg&0xFF) == 1)
continue;
if(SendToRom(value>>8) == 1)
continue;
if(SendToRom(value&0xFF) == 1)
continue;
break;
}
StopRom();
IIC_Delay();
EDIS;
//return i;
}
Uint16 readRegister(Uint16 i2cAddress, Uint16 reg)
{
Uint16 i, ret;
EALLOW;
for(i = 0; i < ADS_RE_COUNT; i++)
{
StopRom();
IIC_Delay();
StartRom();
if(SendToRom(i2cAddress) == 1)
continue;
if(SendToRom(ADS1015_REG_POINTER_CONVERT) == 1)
continue;
StopRom();
IIC_Delay();
StartRom();
if(SendToRom(i2cAddress|BIT0) == 1)
continue;
ret = ReceiveFromRom() << 8;
mack();
ret |= ReceiveFromRom();
mack();
break;
}
StopRom();
IIC_Delay();
EDIS;
return ret;
}
做个备份以后遇到底层的东西就可以省的心了