LTC2449 - 24-Bit High Speed 8-/16-Channel Delta Sigma ADCs with Selectable Speed/Resolution

Features

  • Up to 8 Differential or 16 Single-Ended Input Channels
  • Up to 8kHz Output Rate
  • Up to 4kHz Multiplexing Rate
  • Selectable Speed/Resolution
  • 2µVRMS Noise at 1.76kHz Output Rate
  • 200nVRMS Noise at 13.8Hz Output Rate with Simultaneous 50/60Hz Rejection
  • Guaranteed Modulator Stability and Lock-Up Immunity for any Input and Reference Conditions
  • 0.0005% INL, No Missing Codes
  • Autosleep Enables 20µA Operation at 6.9Hz
  • <5µV Offset (4.5V < VCC < 5.5V, –40°C to 85°C)
  • Differential Input and Differential Reference with GND to VCC Common Mode Range
  • No Latency Mode, Each Conversion is Accurate Even After a New Channel is Selected
  • Internal Oscillator-No External Components
  • LTC2445/LTC2449 Include MUXOUT/ADCIN for External Buffering or Gain
  • Tiny QFN 5mm x 7mm Package
Designed for Automotive and Transportation Applications
AEC-Q100 generic family data available for specific packages


Typical Application

LTC2449 Typical Application
LTC2449 Typical Application

Description

The LTC2444/LTC2445/LTC2448/LTC2449 are 8-/16- channel (4-/8-differential) high speed 24-bit No Latency Delta Sigma ADCs. They use a proprietary delta-sigma architecture enabling variable speed/resolution. Through a simple 4-wire serial interface, ten speed/resolution combinations 6.9Hz/280nVRMS to 3.5kHz/25µVRMS (4kHz with external oscillator) can be selected with no latency between conversion results or shift in DC accuracy (offset, full-scale, linearity, drift). Additionally, a 2X speed mode can be selected enabling output rates up to 7kHz (8kHz if an external oscillator is used) with one cycle latency.

Any combination of single-ended or differential inputs can be selected with a common mode input range from ground to VCC, independent of VREF. While operating in the 1X speed mode the first conversion following a new speed, resolution, or channel selection is valid. Since there is no settling time between conversions, all 8 differential channels can be scanned at a rate of 500Hz. At the conclusion of each conversion, the converter is internally reset eliminating any memory effects between successive conversions and assuring stability of the high order delta-sigma modulator.

Packaging

CAD Symbols and Footprints: The downloadable Zip file below contains the schematic symbol and PCB footprints.

For complete and up to date package information and drawings, please refer to our packaging page

Part Number Package Code Temp Package
Drawing
RoHS
LTC2449CUHF#PBF 5x7 QFN-38 UHF C 05-08-1701 Yes
LTC2449CUHF#TRPBF 5x7 QFN-38 UHF C 05-08-1701 Yes
LTC2449IUHF#PBF 5x7 QFN-38 UHF I 05-08-1701 Yes
LTC2449IUHF#TRPBF 5x7 QFN-38 UHF I 05-08-1701 Yes


LTC2449 Package Drawing
LTC2449 Package Drawing
LTC2449 Package Drawing
LTC2449 Package Drawing

Order Info

  • Part numbers ending in PBF are lead free. Solder plated terminal finish (SnPb) versions are non-standard and special terms and conditions and pricing applies if available. Please contact LTC marketing for information.
  • Part numbers containing TR or TRM are shipped in tape and reel or 500 unit mini tape and reel, respectively
  • Please refer to our general ordering information or the product datasheet for more details

Package Variations and Pricing

Part Number Package Temp Price
(1-99)
Price
(1k)*
RoHS
LTC2449CUHF#PBF 5x7 QFN-38 C $8.75 $7.15 Yes
LTC2449CUHF#TRPBF 5x7 QFN-38 C $7.25 Yes
LTC2449IUHF#PBF 5x7 QFN-38 I $10.15 $8.25 Yes
LTC2449IUHF#TRPBF 5x7 QFN-38 I $8.35 Yes
Buy NowRequest Samples
* The USA list pricing shown is for BUDGETARY USE ONLY, shown in United States dollars (FOB USA per unit for the stated volume), and is subject to change. International prices may differ due to local duties, taxes, fees and exchange rates. For volume-specific price or delivery quotes, please contact your local Linear Technology sales office or authorized distributor.

Demo Boards

Linear Technology offers many demo boards free of charge to qualified customers. Contact your local sales office or distributor to inquire about a demo board. Certain demo boards are also available for sale via credit card on this website. Demo boards are for evaluation purposes only. It remains the customer’s responsibility to verify proper and reliable operation in the actual end application.

Part Number Description Price Documentation
DC1410A-B LTC2449 Demo Board | Load Cell Digitizer Application, req DC2026C $50.00
DC742B LTC2449UHF Demo Board | 24-Bit High-Speed 8/16-Channel Delta Sigma ADC (req DC2026) $50.00
Buy Now

Companion Boards

Part Number Description Price Documentation
DC2026C Linduino One Isolated USB Demo Board: An Arduino- and QuikEval-Compatible Code Development Platform $75.00
DC590B Isolated USB Serial Controller for Linear Technology QuikEval-Compatible Demo Boards $50.00
Buy Now
Click here to view our complete list of demo boards

Designed for Automotive and Transportation Applications

Please contact your local sales representative for more information regarding reliability reports and AEC-Q100 data or to inquire about parts that are not included. For more information, view our Automotive and Transportation page

Part Number Package Temp Price
(1-99)
Price
(1k)*
RoHS
LTC2449IUHF#PBF 5x7 QFN-38 I $10.15 $8.25 Yes
LTC2449IUHF#TRPBF 5x7 QFN-38 I $8.35 Yes
Buy NowRequest Samples
* The USA list pricing shown is for BUDGETARY USE ONLY, shown in United States dollars (FOB USA per unit for the stated volume), and is subject to change. International prices may differ due to local duties, taxes, fees and exchange rates. For volume-specific price or delivery quotes, please contact your local Linear Technology sales office or authorized distributor.

Applications

  • High Speed Multiplexing
  • Weight Scales
  • Auto Ranging 6-Digit DVMs
  • Direct Temperature Measurement
  • High Speed Data Acquisition

Product Notifications

Please login to your MyLinear account for notifications of datasheet updates, new document releases and LTspice model announcements for your favorite products. If you do not have a MyLinear account you may Sign Up Now.

Forgot your password? Click here.
Need help? Email mylinear@linear.com with questions and comments.

Design Tools

Linduino

Linduino is an Arduino compatible platform for developing and distributing firmware libraries and code for SPI and I²C-compatible integrated circuits. The Linduino One board interfaces to more than 300 QuikEval demonstration cards, supporting a variety of product types including analog-to-digital converters (ADCs)digital-to-analog converters (DACs)power monitors, and more. Firmware libraries for individual devices are written in C and designed to be portable to a wide variety of processors and microcontrollers. Each library has a demonstration program that can be uploaded to the Linduino One platform to allow the circuit and software to be quickly and easily verified.

Click here for more information on Linduino

Code

Linduino is Linear Technology's Arduino compatible system for developing and distributing firmware libraries and example code for Linear Technology’s integrated circuits. The code below can be downloaded or copied and pasted into your project. Please visit the Linduino Home Page for demo board, manual and setup information.

This part is Code Supported: There is example code available for this part. The code below may rely on other drivers available in the full library.

Download LTC2449 - DC1410AB.ino File

/*!
Linear Technology DC1410A-B Demonstration Board.
LTC2449: 24-Bit, 16-Channel Delta Sigma ADC with SPI interface

@verbatim

NOTES
  Setup:
   Set the terminal baud rate to 115200 and select the newline terminator. Equipment
   required is a precision voltage source and a precision voltmeter. Additionally,
   an external power supply is required to provide a negative voltage for Amp V-.
   Set it to anywhere from -1V to -5V. Set Amp V+ to Vcc. Ensure the COM and REF-
   pins are connected to ground. The REF+ pin should be connected to +5V.

  How Measure a Load Cell:
   The LTC2449 allowas a wide common mode range of 0V to Vcc. The LT1678 OPAMP common
   mode range is V- + 1.5 to V+ - 0.8V. Ensure the load cell sensor meets the requirments
   of the ADC and amplifier. Lastly, set the desired gain and read in differential mode.

USER INPUT DATA FORMAT:
 decimal : 1024
 hex     : 0x400
 octal   : 02000  (leading 0 "zero")
 binary  : B10000000000
 float   : 1024.0

@endverbatim

http://www.linear.com/product/LTC2449

http://www.linear.com/product/LTC2449#demoboards

REVISION HISTORY
$Revision: 6562 $
$Date: 2017-02-17 15:31:46 -0800 (Fri, 17 Feb 2017) $

Copyright (c) 2013, Linear Technology Corp.(LTC)
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this
   list of conditions and the following disclaimer.
2. 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.

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.

The views and conclusions contained in the software and documentation are those
of the authors and should not be interpreted as representing official policies,
either expressed or implied, of Linear Technology Corp.

The Linear Technology Linduino is not affiliated with the official Arduino team.
However, the Linduino is only possible because of the Arduino team's commitment
to the open-source community.  Please, visit http://www.arduino.cc and
http://store.arduino.cc , and consider a purchase that will help fund their
ongoing work.

*/

/*! @file
    @ingroup LTC2449
*/

#include <Arduino.h>
#include <stdint.h>
#include "Linduino.h"
#include "LT_SPI.h"
#include <SPI.h>
#include "UserInterface.h"
#include "LT_I2C.h"
#include "QuikEval_EEPROM.h"
#include "LTC24XX_general.h"
#include "LTC2449.h"
#include "LTC24XX_general.h"

// Function Declaration
void print_title();                             // Print the title block
void print_prompt();                            // Prompt the user for an input command
void print_user_command(uint8_t menu);          // Display selected differential channels

uint8_t menu_1_read_differential();             // Read the ADC in differential mode
void set_gain(uint8_t a_pin, uint8_t b_pin, uint8_t gain);  // Drive the select pins to get desired gain
void init_gain_pins(uint8_t a_pin, uint8_t b_pin);          // Initialize the MUX select pins
void menu_2_set_osr();                          // Set the OSR for the ADC
void menu_3_set_channel_gain();                 // Sets gains for indvidual channels
void print_gain(uint8_t gain);                  // Displays the current channel gain setting

enum Av {unity, g8, g16, g32};                  // Gain options

// Global variables
static uint8_t demo_board_connected;                      //!< Set to 1 if the board is connected
static uint16_t osr = LTC2449_OSR_32768;                  //!< Default OSR is 32768
static float LTC2449_lsb = 5.0 / 536870911;               //!< The LTC2449 ideal reference voltage
static uint16_t eoc_timeout = 250;                        //!< Timeout in ms
uint8_t filt_flag = 1;                                    //!< Keeps track when filters need to be reset
uint8_t channel_gain[6] = {g32, g32, g32, g32, g32, g32}; //!< default is gain 32

// Constants
//! Lookup table for reads
const uint16_t read_command_seq[] = {LTC2449_P12_N13,
                                     LTC2449_P14_N15, LTC2449_P14_N15, LTC2449_P14_N15, LTC2449_P14_N15,
                                     LTC2449_P0_N1, LTC2449_P2_N3, LTC2449_P4_N5, LTC2449_P6_N7, LTC2449_P8_N9,
                                     LTC2449_P10_N11, LTC2449_P10_N11
                                    };  //!< Channel read sequence for the demo board

//! Lookup table for gain setting reads
uint8_t read_gain_seq[] = {unity, unity, unity, g8, g16, g32, channel_gain[0], channel_gain[1], channel_gain[2], channel_gain[3],
                           channel_gain[4], channel_gain[5]
                          }; //!< The gain sequence for the auto calibration
//! Lookup table for OSR
const uint16_t OSR_COMMAND[] = {LTC2449_OSR_64, LTC2449_OSR_128, LTC2449_OSR_256, LTC2449_OSR_512, LTC2449_OSR_1024,
                                LTC2449_OSR_2048, LTC2449_OSR_4096, LTC2449_OSR_8192, LTC2449_OSR_16384, LTC2449_OSR_32768
                               }; //!< Build the command for OSR

//! Gain MUX pins
const uint8_t A_PIN = 4;
const uint8_t B_PIN = 7;

//! Exponential filter smothing constant for the offset
const float smoothing_const = 0.7;

//! Initialize Linduino
void setup()
{
  init_gain_pins(A_PIN, B_PIN);   // Initialize the gain pins as outputs

  char demo_name[] = "DC1410";    // Demo Board Name stored in QuikEval EEPROM
  quikeval_SPI_init();            // Configure the spi port for 4MHz SCK
  quikeval_SPI_connect();         // Connect SPI to main data port
  quikeval_I2C_init();            // Configure the EEPROM I2C port for 100kHz
  Serial.begin(115200);           // Initialize the serial port to the PC
  print_title();

  demo_board_connected = discover_demo_board(demo_name);
  if (demo_board_connected)
  {
    print_prompt();
  }
  else
  {
    Serial.println(F("EEPROM not detected, will attempt to proceed"));
    print_prompt();
  }
  quikeval_SPI_connect();         // Initialize for SPI
}

//! Repeats Linduino loop
void loop()
{
  int16_t user_command;             // The user input command
  uint8_t ack_EOC = 0;              // Keeps track of the EOC timeout
  if (Serial.available())           // Check for user input
  {
    user_command = read_int();      // Read the user command
    if (user_command != 'm')
      Serial.println(user_command); // Prints the user command to com port
    Serial.flush();
    switch (user_command)
    {
      case 1:
        ack_EOC |= menu_1_read_differential();
        break;
      case 2:
        menu_2_set_osr();
        break;
      case 3:
        menu_3_set_channel_gain();
        break;
      default:
        Serial.println(F("Incorrect Option"));
    }
    if (ack_EOC)
      Serial.println(F("\n******SPI ERROR******\n"));
    Serial.print(F("\n*************************\n"));
    print_prompt();
  }
}

// Function Definitions

//! Prints the title block when program first starts.
void print_title()
{
  Serial.print(F("\n*****************************************************************\n"));
  Serial.print(F("* DC1410A-B Demonstration Program                               *\n"));
  Serial.print(F("*                                                               *\n"));
  Serial.print(F("* This program demonstrates how to measure strain gauge or      *\n"));
  Serial.print(F("* other form of a Wheatstone bridge sensors with the LTC2449    *\n"));
  Serial.print(F("*                                                               *\n"));
  Serial.print(F("*                                                               *\n"));
  Serial.print(F("* Set the baud rate to 115200 and select the newline terminator.*\n"));
  Serial.print(F("*                                                               *\n"));
  Serial.print(F("*****************************************************************\n"));
}

//! Prints main menu.
void print_prompt()
{
  Serial.print(F("\n1-Read Differential\n"));
  Serial.print(F("2-OSR Settings\n"));
  Serial.print(F("3-Set Channel Gain\n"));
  Serial.print(F("Enter a Command: "));
}

//! Read channels in differential mode
//! @return Returns 0=successful, 1=unsuccessful (exceeded timeout)
uint8_t menu_1_read_differential()
{
  int8_t y;               // Offset into differential channel array to select polarity
  uint16_t adc_command;   // The LTC2449 command word
  int16_t user_command;   // The user input command
  uint32_t adc_code[12];   // The LTC2449 code
  float adc_voltage;      // The LTC2449 voltage
  float offset = 0.0;     // The ADC channel offset
  float gain_unity = 0.0; // The code for unity gain
  float gain_8 = 0.0;     // The calculated gain of 8
  float gain_16 = 0.0;    // The calculated gain of 16
  float gain_32 = 0.0;    // The calculated gain of 32
  float gain_value[4];    // The calculated gain

  do
  {
    // Read the calibration channels first then the rest of the channels
    for (int8_t i = 0; i <= 11; i++)
    {
      set_gain(A_PIN, B_PIN, read_gain_seq[i]); // Set the MUX to the desired gain
      adc_command = read_command_seq[i] | osr;
      // Ensure a conversions are complete
      if (LTC2449_EOC_timeout(LTC2449_CS, eoc_timeout))
        return 1;
      // Read the LTC2449
      LTC2449_read(LTC2449_CS, adc_command, adc_code + i);
    }

    if (filt_flag)
    {
      filt_flag = 0;
      offset = adc_code[1] - 536870912;
      gain_unity = ((float)adc_code[2]) - 536870912;
      gain_8 = ((float)adc_code[3] - 536870912) / gain_unity;
      gain_16 = ((float)adc_code[4] - 536870912) / gain_unity;
      gain_32 = ((float)adc_code[5] - 536870912) / gain_unity;
    }
    else
    {
      // IIR exponential filter
      offset = (1.0 - smoothing_const ) * ((float)adc_code[1] - 536870912) + smoothing_const * offset;
      gain_unity = ((float)adc_code[2]) - 536870912;
      gain_8 = (1.0 - smoothing_const) * (((float)adc_code[3] - 536870912) / gain_unity) + smoothing_const * gain_8;
      gain_16 = (1.0 - smoothing_const) * (((float)adc_code[4] - 536870912) / gain_unity) + smoothing_const * gain_16;
      gain_32 = (1.0 - smoothing_const) * (((float)adc_code[5] - 536870912) / gain_unity) + smoothing_const * gain_32;
    }

    gain_value[0] = 1; // Assume ideal unity gain
    gain_value[1] = gain_8;
    gain_value[2] = gain_16;
    gain_value[3] = gain_32;

    // Display the readings and data
    Serial.println(F("\n**********"));
    Serial.print(F("  Offset: "));
    Serial.print(offset, 6);
    Serial.print(F("  "));
    Serial.print(LTC24XX_diff_code_to_calibrated_voltage(((int32_t)offset) + 536870912, LTC2449_lsb, 0.0) * 1000, 4);
    Serial.println(F(" mV"));
    Serial.print(F("  G8: "));
    Serial.println(gain_8, 6);
    Serial.print(F("  G16: "));
    Serial.println(gain_16, 6);
    Serial.print(F("  G32: "));
    Serial.println(gain_32, 6);
    Serial.println();

    Serial.println(F("CH       ADC Code    Gain       Comp Voltage (mV)"));
    Serial.print(F("P0-N1:   0x"));
    Serial.print(adc_code[5], HEX);
    Serial.print("  ");
    Serial.print(gain_value[channel_gain[0]], 6);
    Serial.print(F("  "));
    Serial.println(1000 * LTC24XX_diff_code_to_calibrated_voltage(adc_code[6], LTC2449_lsb, offset) / gain_value[channel_gain[0]], 6);

    Serial.print(F("P2-N3:   0x"));
    Serial.print(adc_code[6], HEX);
    Serial.print(F("  "));
    Serial.print(gain_value[channel_gain[1]], 6);
    Serial.print("  ");
    Serial.println(1000 * LTC24XX_diff_code_to_calibrated_voltage(adc_code[7], LTC2449_lsb, offset) / gain_value[channel_gain[1]], 6);

    Serial.print(F("P4-N5:   0x"));
    Serial.print(adc_code[7], HEX);
    Serial.print(F("  "));
    Serial.print(gain_value[channel_gain[2]], 6);
    Serial.print("  ");
    Serial.println(1000 * LTC24XX_diff_code_to_calibrated_voltage(adc_code[8], LTC2449_lsb, offset) / gain_value[channel_gain[2]], 6);

    Serial.print(F("P6-N7:   0x"));
    Serial.print(adc_code[8], HEX);
    Serial.print(F("  "));
    Serial.print(gain_value[channel_gain[3]], 6);
    Serial.print("  ");
    Serial.println(1000 * LTC24XX_diff_code_to_calibrated_voltage(adc_code[9], LTC2449_lsb, offset) / gain_value[channel_gain[3]], 6);

    Serial.print(F("P8-N9:   0x"));
    Serial.print(adc_code[9], HEX);
    Serial.print(F("  "));
    Serial.print(gain_value[channel_gain[4]], 6);
    Serial.print("  ");
    Serial.println(1000 * LTC24XX_diff_code_to_calibrated_voltage(adc_code[10], LTC2449_lsb, offset) / gain_value[channel_gain[4]], 6);

    Serial.print(F("P10-N11: 0x"));
    Serial.print(adc_code[10], HEX);
    Serial.print(F("  "));
    Serial.print(gain_value[channel_gain[5]], 6);
    Serial.print("  ");
    Serial.println(1000 * LTC24XX_diff_code_to_calibrated_voltage(adc_code[11], LTC2449_lsb, offset) / gain_value[channel_gain[5]], 6);

    Serial.println();
    Serial.println(F("Enter any character to exit"));

  }
  while (Serial.available() == 0);
  while (Serial.available())
    Serial.read();
  Serial.flush();
  return 0;
}

//! Set the Mux select pins to the desired gain
void set_gain(uint8_t a_pin, uint8_t b_pin, uint8_t gain)
{
  digitalWrite(a_pin, gain & 0b01);
  digitalWrite(b_pin, gain & 0b10);
}

//! initialize the MUX select pins
void init_gain_pins(uint8_t a_pin, uint8_t b_pin)
{
  pinMode(a_pin, OUTPUT);
  pinMode(b_pin, OUTPUT);
  digitalWrite(a_pin, LOW);
  digitalWrite(b_pin, LOW);
}

//! Allows the user to sets the desired gain
void menu_3_set_channel_gain()
{
  int16_t user_command; // The user input cammand

  while (1)
  {
    // Display gain settings
    Serial.print(F("\nCurrent Gain Settings:\n"));
    Serial.print(F("  CH 0P-1N   gain: "));
    print_gain(channel_gain[0]);
    Serial.print(F("  CH 2P-3N   gain: "));
    print_gain(channel_gain[1]);
    Serial.print(F("  CH 4P-5N   gain: "));
    print_gain(channel_gain[2]);
    Serial.print(F("  CH 6P-7N   gain: "));
    print_gain(channel_gain[3]);
    Serial.print(F("  CH 8P-9N   gain: "));
    print_gain(channel_gain[4]);
    Serial.print(F("  CH 10P-11N gain: "));
    print_gain(channel_gain[5]);

    Serial.print(F("\n\n"));
    Serial.print(F("Channel Select\n"));
    Serial.print(F("  0-0P-1N     3-6P-7N\n"));
    Serial.print(F("  1-2P-3N     4-8P-9N\n"));
    Serial.print(F("  2-4P-5N     5-10P-11N\n"));
    Serial.print(F("  6-ALL\n"));
    Serial.print(F("m-Main Menu\n"));
    Serial.print(F("Enter a Command: "));

    user_command = read_int();          // Read the single command
    uint8_t channel = user_command;
    if (user_command == 'm')
    {
      Serial.println(F("m"));
      break;
    }
    Serial.println(user_command);
    if (user_command > 6)
      Serial.println(F("Incorrect Option"));
    else
    {
      if (user_command == 6)
      {
        Serial.print(F("\nGain Options\n"));
        Serial.print(F("  0-Unity Gain\n"));
        Serial.print(F("  1-Gain of 8\n"));
        Serial.print(F("  2-Gain of 16\n"));
        Serial.print(F("  3-Gain of 32\n"));
        Serial.print(F("Enter a Command: "));
        user_command = read_int();        // Read the single command
        Serial.println(user_command);
        if (user_command < 0 || user_command > 3)
          Serial.print(F("Incorrect Gain Option"));
        else
        {
          for (uint8_t i = 0; i <= 5; i++)
          {
            channel_gain[i] = user_command;
          }
        }
      }
      else
      {
        Serial.print(F("\nGain Options\n"));
        Serial.print(F("  0-Unity Gain\n"));
        Serial.print(F("  1-Gain of 8\n"));
        Serial.print(F("  2-Gain of 16\n"));
        Serial.print(F("  3-Gain of 32\n"));
        Serial.print(F("Enter a Command: "));
        user_command = read_int();        // Read the single command
        Serial.println(user_command);
        if (user_command < 0 || user_command > 3)
          Serial.print(F("Incorrect Gain Option"));
        else
          channel_gain[channel] = user_command;
      }
    }
  }
  for (int8_t i = 0; i <= 5; i++)
    read_gain_seq[i + 6] = channel_gain[i];
  filt_flag = 1;
}

//! Utility function to display the gain
void print_gain(uint8_t gain)
{
  switch (gain)
  {
    case unity:
      Serial.print(F("Unity\n"));
      break;
    case g8:
      Serial.print(F("8\n"));
      break;
    case g16:
      Serial.print(F("16\n"));
      break;
    case g32:
      Serial.print(F("32\n"));
      break;
  }
}

//! Allows the user to sets the desired OSR
void menu_2_set_osr()
{
  int16_t user_command; // The user input command

  // OSR settings
  Serial.print(F("OSR Settings\n\n"));
  Serial.print(F("0-64\n"));
  Serial.print(F("1-128\n"));
  Serial.print(F("2-256\n"));
  Serial.print(F("3-512\n"));
  Serial.print(F("4-1024\n"));
  Serial.print(F("5-2048\n"));
  Serial.print(F("6-4096\n"));
  Serial.print(F("7-8192\n"));
  Serial.print(F("8-16384\n"));
  Serial.print(F("9-32768\n"));
  Serial.print(F("Enter a Command: "));

  user_command = read_int();
  if (user_command <= 0)
  {
    user_command = 0;
  }
  else if (user_command > 9)
  {
    user_command = 9;
  }
  Serial.println(user_command);

  osr = OSR_COMMAND[user_command];
  filt_flag = 1;
}

Download LTC2449 - DC742A Linduino .INO File

/*!
Linear Technology DC742A Demonstration Board.
LTC2449: 24-Bit, 16-Channel Delta Sigma ADC with Selectable Speed/Resolution.

Linear Technology DC979A Demonstration Board.
LTC2442: 24-Bit, 4-Channel Delta Sigma ADC with Integrated Amplifier

Linear Technology DC845A Demonstration Board.
LTC2448: 24-Bit, 8-/16-Channel Delta Sigma ADCs with Selectable Speed/Resolution

@verbatim

NOTES
  Setup:
   Set the terminal baud rate to 115200 and select the newline terminator. Equipment
   required is a precision voltage source and a precision voltmeter. Additionally,
   an external power supply is required to provide a negative voltage for Amp V-.
   Set it to anywhere from -1V to -5V. Set Amp V+ to Vcc. Ensure the COM and REF-
   pins are connected to ground. The REF+ pin should be connected to +5V.

  How to test Single-Ended mode:
   The voltage source should be connected to the ADC such that the negative lead is
   connected to the COM(common) pin. The positive lead may be connected to any
   channel input. Ensure voltage is within analog input voltage range -0.3 to 2.5V.

  How to test Differential Mode:
   The voltage source should be connected with positive and negative leads to paired
   channels. The voltage source negative output must also be connected to the COM
   pin in order to provide a ground-referenced voltage. Ensure voltage is within
   analog input voltage range -0.3V to +2.5V. Swapping input voltages results in a
   reversed polarity reading.

  How to calibrate:
   Apply 100mV CH0 with respect to COM. Next, measure this voltage with a precise
   voltmeter and enter this value. (This takes the reading.) Now apply approximately
   2.40 volts to CH0. Measure this voltage with a precise voltmeter and enter this
   value. Calibration is now stored in EEPROM. Upon start-up the calibration values
   will be restored.

USER INPUT DATA FORMAT:
 decimal : 1024
 hex     : 0x400
 octal   : 02000  (leading 0 "zero")
 binary  : B10000000000
 float   : 1024.0

@endverbatim

http://www.linear.com/product/LTC2449
http://www.linear.com/product/LTC2442
http://www.linear.com/product/LTC2448

http://www.linear.com/product/LTC2449#demoboards
http://www.linear.com/product/LTC2442#demoboards
http://www.linear.com/product/LTC2448#demoboards

REVISION HISTORY
$Revision: 4776 $
$Date: 2016-03-14 11:18:29 -0700 (Mon, 14 Mar 2016) $

Copyright (c) 2013, Linear Technology Corp.(LTC)
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this
   list of conditions and the following disclaimer.
2. 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.

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.

The views and conclusions contained in the software and documentation are those
of the authors and should not be interpreted as representing official policies,
either expressed or implied, of Linear Technology Corp.

The Linear Technology Linduino is not affiliated with the official Arduino team.
However, the Linduino is only possible because of the Arduino team's commitment
to the open-source community.  Please, visit http://www.arduino.cc and
http://store.arduino.cc , and consider a purchase that will help fund their
ongoing work.

 */

/*! @file
    @ingroup LTC2449
*/

#include <Arduino.h>
#include <stdint.h>
#include "Linduino.h"
#include "LT_SPI.h"
#include "UserInterface.h"
#include "LT_I2C.h"
#include "QuikEval_EEPROM.h"
#include "LTC2449.h"
#include <SPI.h>
#include <Wire.h>

// Function Declaration
void print_title();                             // Print the title block
void print_prompt();                            // Prompt the user for an input command
void print_user_command(uint8_t menu);          // Display selected differential channels
void store_calibration();                       // Store the ADC calibration to the EEPROM
int8_t restore_calibration();                   // Read the calibration from EEPROM, return 1 if successful, 0 if not

int8_t menu_1_read_single_ended();
int8_t menu_2_read_differential();
int8_t menu_3_calibrate();
void menu_4_set_OSR();
void menu_5_set_1X2X();
void menu_6_en_dis_cal();

// Global variables
static uint8_t demo_board_connected;            //!< Set to 1 if the board is connected
static int16_t OSR_mode = LTC2449_OSR_32768;    //!< The LTC2449 OSR setting
static int16_t two_x_mode = LTC2449_SPEED_1X;   //!< The LTC2449 2X Mode settings
static float LTC2449_lsb = 9.3132258E-9;        //!< Ideal LSB voltage for a perfect part
static int32_t LTC2449_offset_code = 0;         //!< Ideal offset for a perfect part

// Constants

//! Lookup table to build the command for single-ended mode
const uint16_t BUILD_COMMAND_SINGLE_ENDED[16] = {LTC2449_CH0, LTC2449_CH1, LTC2449_CH2, LTC2449_CH3,
    LTC2449_CH4, LTC2449_CH5, LTC2449_CH6, LTC2449_CH7,
    LTC2449_CH8, LTC2449_CH9, LTC2449_CH10, LTC2449_CH11,
    LTC2449_CH12, LTC2449_CH13, LTC2449_CH14, LTC2449_CH15
                                                };    //!< Builds the command for single-ended mode

//! Lookup table to build the command for differential mode
const uint16_t BUILD_COMMAND_DIFF[16] = {LTC2449_P0_N1, LTC2449_P2_N3, LTC2449_P4_N5, LTC2449_P6_N7,
                                        LTC2449_P8_N9, LTC2449_P10_N11, LTC2449_P12_N13, LTC2449_P14_N15,
                                        LTC2449_P1_N0, LTC2449_P3_N2, LTC2449_P5_N4, LTC2449_P7_N6,
                                        LTC2449_P9_N8, LTC2449_P11_N10, LTC2449_P13_N12, LTC2449_P15_N14
                                        };      //!< Build the command for differential mode

//! Lookup table to build the command for OSR
const uint16_t BUILD_OSR_COMMAND[10] = {LTC2449_OSR_32768, LTC2449_OSR_64, LTC2449_OSR_128, LTC2449_OSR_256, LTC2449_OSR_512,
                                        LTC2449_OSR_1024, LTC2449_OSR_2048, LTC2449_OSR_4096, LTC2449_OSR_8192, LTC2449_OSR_16384
                                       };       //!< Build the command for OSR

//! Lookup table to build 1X / 2X bits
const uint16_t BUILD_1X_2X_COMMAND[2] = {LTC2449_SPEED_1X, LTC2449_SPEED_2X};   //!< Build the command for 1x or 2x mode

//! MISO timeout constant
const uint16_t MISO_TIMEOUT = 1000;

//! Initialize Linduino
void setup()
{
  char demo_name[]="DC742";     // Demo Board Name stored in QuikEval EEPROM

  quikeval_SPI_init();          // Configure the spi port for 4MHz SCK
  quikeval_SPI_connect();       // Connect SPI to main data port
  quikeval_I2C_init();          // Configure the EEPROM I2C port for 100kHz
  Serial.begin(115200);         // Initialize the serial port to the PC
  print_title();
  demo_board_connected = discover_demo_board(demo_name);
  if (demo_board_connected)
  {
    restore_calibration();
    print_prompt();
  }
}

//! Repeats Linduino loop
void loop()
{
  int16_t user_command;                 // The user input command
  uint8_t acknowledge = 0;
  if (demo_board_connected)
  {
    if (Serial.available())             // Check for user input
    {
      user_command = read_int();        // Read the user command
      if (user_command != 'm')
        Serial.println(user_command);   // Prints the user command to com port
      Serial.flush();
      switch (user_command)
      {
        case 1:
          acknowledge |= menu_1_read_single_ended();
          break;
        case 2:
          acknowledge |= menu_2_read_differential();
          break;
        case 3:
          acknowledge |= menu_3_calibrate();
          break;
        case 4:
          menu_4_set_OSR();
          break;
        case 5:
          menu_5_set_1X2X();
          break;
        case 6:
          menu_6_en_dis_cal();
          break;
        default:
          Serial.println("Incorrect Option");
      }
      if (acknowledge)
        Serial.println("***** SPI ERROR *****");
      Serial.print(F("\n*************************\n"));
      print_prompt();
    }
  }
}

// Function Definitions

//! Prints the title block when program first starts.
void print_title()
{
  Serial.print(F("\n*****************************************************************\n"));
  Serial.print(F("* DC742A Demonstration Program                                  *\n"));
  Serial.print(F("*                                                               *\n"));
  Serial.print(F("* This program demonstrates how to send data and receive data   *\n"));
  Serial.print(F("* from the 24-bit ADC.                                          *\n"));
  Serial.print(F("*                                                               *\n"));
  Serial.print(F("*                                                               *\n"));
  Serial.print(F("* Set the baud rate to 115200 and select the newline terminator.*\n"));
  Serial.print(F("*                                                               *\n"));
  Serial.print(F("*****************************************************************\n"));
}

//! Prints main menu.
void print_prompt()
{
  Serial.print(F("\n1-Read Single-Ended\n"));
  Serial.print(F("2-Read Differential\n"));
  Serial.print(F("3-Calibration\n"));
  Serial.print(F("4-Oversample Ratio Settings\n"));
  Serial.print(F("5-2X Mode Settings\n"));
  Serial.print(F("6-Enable / Disable Calibration Key\n\n"));
  Serial.print(F("Enter a Command: "));
}

//! Display selected differential channels. Displaying single-ended channels is
//! straightforward; not so with differential because the inputs can take either polarity.
void print_user_command(uint8_t menu)
{
  switch (menu)
  {
    case 0:
      Serial.print("0P-1N");
      break;
    case 1:
      Serial.print("2P-3N");
      break;
    case 2:
      Serial.print("4P-5N");
      break;
    case 3:
      Serial.print("6P-7N");
      break;
    case 4:
      Serial.print("8P-9N");
      break;
    case 5:
      Serial.print("10P-11N");
      break;
    case 6:
      Serial.print("12P-13N");
      break;
    case 7:
      Serial.print("14P-15N");
      break;
    case 8:
      Serial.print("1P-0N");
      break;
    case 9:
      Serial.print("3P-2N");
      break;
    case 10:
      Serial.print("5P-4N");
      break;
    case 11:
      Serial.print("7P-6N");
      break;
    case 12:
      Serial.print("9P-8N");
      break;
    case 13:
      Serial.print("11P-10N");
      break;
    case 14:
      Serial.print("13P-12N");
      break;
    case 15:
      Serial.print("15P-14N");
      break;
  }
  Serial.print(": ");
}

//! Read channels in single-ended mode
//! @return 0 if successful, 1 is failure
int8_t menu_1_read_single_ended()
{
  uint16_t adc_command;     // The LTC2449 command word
  int16_t user_command;     // The user input command
  uint32_t adc_code = 0;    // The LTC2449 code
  float adc_voltage;        // The LTC2449 voltage

  while (1)
  {
    Serial.print(F("*************************\n\n"));
    Serial.print(F("0-CH0  8-CH8\n"));
    Serial.print(F("1-CH1  9-CH9\n"));
    Serial.print(F("2-CH2  10-CH10\n"));
    Serial.print(F("3-CH3  11-CH11\n"));
    Serial.print(F("4-CH4  12-CH12\n"));
    Serial.print(F("5-CH5  13-CH13\n"));
    Serial.print(F("6-CH6  14-CH14\n"));
    Serial.print(F("7-CH7  15-CH15\n"));
    Serial.print(F("16-ALL\n"));
    Serial.print(F("m-Main Menu\n"));
    Serial.print("Enter a Command: ");

    user_command = read_int();                          // Read the single command
    if (user_command == 'm')
      return(0);
    Serial.println(user_command);

    if (user_command == 16)
    {
      Serial.print(F("ALL\n"));
      adc_command = BUILD_COMMAND_SINGLE_ENDED[0] | OSR_mode | two_x_mode;  // Build ADC command for channel 0
      if (LTC2449_EOC_timeout(LTC2449_CS, MISO_TIMEOUT)) // Checks for EOC with a timeout
        return(1);
      LTC2449_read(LTC2449_CS, adc_command, &adc_code); // Throws out last reading

      for (int8_t x = 0; x <= 15; x++)                  // Read all channels in single-ended mode
      {
        if (two_x_mode)
        {
          LTC2449_read(LTC2449_CS, adc_command, &adc_code); // Throws out an extra reading in 2x mode
          if (LTC2449_EOC_timeout(LTC2449_CS, MISO_TIMEOUT)) // Checks for EOC with a timeout
            return(1);
        }
        adc_command = BUILD_COMMAND_SINGLE_ENDED[(x + 1) % 16] | OSR_mode | two_x_mode;
        if (LTC2449_EOC_timeout(LTC2449_CS, MISO_TIMEOUT))  // Checks for EOC with a timeout
          return(1);
        LTC2449_read(LTC2449_CS, adc_command, &adc_code);
        adc_voltage = LTC2449_code_to_voltage(adc_code, LTC2449_lsb, LTC2449_offset_code);
        Serial.print("  ****");
        Serial.print("CH");
        Serial.print(x);
        Serial.print(": ");
        Serial.print(adc_voltage, 4);
        Serial.print(F("V\n\n"));
      }
    }
    else
    {
      adc_command = BUILD_COMMAND_SINGLE_ENDED[user_command] | OSR_mode | two_x_mode;
      Serial.print("\nADC Command: B");
      Serial.println(adc_command, BIN);
      if (LTC2449_EOC_timeout(LTC2449_CS, MISO_TIMEOUT))    // Checks for EOC with a timeout
        return(1);
      LTC2449_read(LTC2449_CS, adc_command, &adc_code);     // Throws out last reading
      if (two_x_mode)
      {
        LTC2449_read(LTC2449_CS, adc_command, &adc_code);   // Throws out an extra reading in 2x mode
        if (LTC2449_EOC_timeout(LTC2449_CS, MISO_TIMEOUT))  // Checks for EOC with a timeout
          return(1);
      }
      if (LTC2449_EOC_timeout(LTC2449_CS, MISO_TIMEOUT))    // Checks for EOC with a timeout
        return(1);
      LTC2449_read(LTC2449_CS, adc_command, &adc_code);     // Now we're ready to read the desired data
      Serial.print("Received Code: 0x");
      Serial.println(adc_code, HEX);
      adc_voltage = LTC2449_code_to_voltage(adc_code, LTC2449_lsb, LTC2449_offset_code);
      Serial.print("  ****");
      Serial.print("CH");
      Serial.print(user_command);
      Serial.print(": ");
      Serial.print(adc_voltage, 4);
      Serial.print(F("V\n\n"));
    }
  }
  return(0);
}

//! Read channels in differential mode
//! @return 0 if successful, 1 is failure
int8_t menu_2_read_differential()
{
  int8_t y;                 // Offset into differential channel array to select polarity
  uint16_t adc_command;     // The LTC2449 command word
  int16_t user_command;     // The user input command
  uint32_t adc_code = 0;    // The LTC2449 code
  float adc_voltage;        // The LTC2449 voltage

  while (1)
  {
    Serial.print(F("\n*************************\n\n")); // Display  differential menu
    Serial.print(F("0-0P-1N     8-1P-0N\n"));
    Serial.print(F("1-2P-3N     9-3P-2N\n"));
    Serial.print(F("2-4P-5N     10-5P-4N\n"));
    Serial.print(F("3-6P-7N     11-7P-6N\n"));
    Serial.print(F("4-8P-9N     12-9P-8N\n"));
    Serial.print(F("5-10P-11N   13-11P-10N\n"));
    Serial.print(F("6-12P_13N   14-13P-12N\n"));
    Serial.print(F("7-14P-15N   15-15P-14N\n"));
    Serial.print(F("16-ALL Even_P-Odd_N\n"));
    Serial.print(F("17-ALL Odd_P-Even_N\n"));
    Serial.print(F("m-Main Menu\n"));

    user_command = read_int();                        // Read the single command
    if (user_command == 'm')
      return(0);
    Serial.println(user_command);
    if ((user_command == 16) || (user_command == 17))
    {
      if (user_command == 16)
      {
        Serial.print(F("ALL Even_P-Odd_N\n"));        // Cycles through options 0-7
        y = 0;
      }
      if (user_command == 17)
      {
        Serial.print(F("ALL Odd_P-Even_N\n"));        // Cycles through options 8-15
        y = 8;
      }

      adc_command = BUILD_COMMAND_DIFF[y] | OSR_mode | two_x_mode;  // Build the channel 0 and 1 for differential mode
      if (LTC2449_EOC_timeout(LTC2449_CS, MISO_TIMEOUT))            // Checks for EOC with a timeout
        return(1);
      LTC2449_read(LTC2449_CS, adc_command, &adc_code);             // Throws out reading
      for (int8_t x = 0; x < 7; x++)                                // Read all channels in differential mode. All even channels are positive and odd channels are negative
      {
        if (two_x_mode)
        {
          LTC2449_read(LTC2449_CS, adc_command, &adc_code);         // Throws out an extra reading in 2x mode
          if (LTC2449_EOC_timeout(LTC2449_CS, MISO_TIMEOUT))        // Checks for EOC with a timeout
            return(1);
        }
        adc_command = BUILD_COMMAND_DIFF[((x + 1) % 8) + y] | OSR_mode | two_x_mode;
        if (LTC2449_EOC_timeout(LTC2449_CS, MISO_TIMEOUT))          // Checks for EOC with a timeout
          return(1);
        LTC2449_read(LTC2449_CS, adc_command, &adc_code);
        Serial.print("Received Code: 0x");
        Serial.println(adc_code, HEX);
        adc_voltage = LTC2449_code_to_voltage(adc_code, LTC2449_lsb, LTC2449_offset_code);
        Serial.print("\n  ****");
        print_user_command(x + y);
        Serial.print(": ");
        Serial.print(adc_voltage, 4);
        Serial.print(F("V\n"));
      }
    }
    else
    {
      // Reads and displays a selected channel
      adc_command = BUILD_COMMAND_DIFF[user_command] | OSR_mode | two_x_mode;
      Serial.print("ADC Command: B");
      Serial.println(adc_command, BIN);
      if (LTC2449_EOC_timeout(LTC2449_CS, MISO_TIMEOUT))            // Checks for EOC with a timeout
        return(1);
      LTC2449_read(LTC2449_CS, adc_command, &adc_code);             // Throws out last reading
      if (two_x_mode)
      {
        if (LTC2449_EOC_timeout(LTC2449_CS, MISO_TIMEOUT))          // Checks for EOC with a timeout
          return(1);
        LTC2449_read(LTC2449_CS, adc_command, &adc_code);           // Throws out an extra reading in 2x mode
      }
      if (LTC2449_EOC_timeout(LTC2449_CS, MISO_TIMEOUT))            // Checks for EOC with a timeout
        return(1);
      LTC2449_read(LTC2449_CS, adc_command, &adc_code);
      Serial.print("Received Code: 0x");
      Serial.println(adc_code, HEX);
      adc_voltage = LTC2449_code_to_voltage(adc_code, LTC2449_lsb, LTC2449_offset_code);
      Serial.print("\n  ****");
      print_user_command(user_command);
      Serial.print(adc_voltage, 4);
      Serial.print(F("V\n"));
    }
  }
  return(0);
}

//! Calibrate ADC given two known inputs
//! @return 0 if successful, 1 is failure
int8_t menu_3_calibrate()
{
  uint16_t adc_command;     // The LTC2449 command word
  int16_t user_command;     // The user input command
  uint32_t adc_code = 0;    // The LTC2449 code
  float zero_voltage;       // Measured cal voltage
  float fs_voltage;         // Measured cal voltage
  uint32_t zero_code;       // Cal zero code
  uint32_t fs_code;         // Cal full scale code

  // Calibration
  Serial.println("Apply 100mV to CH0 with respect to COM");
  Serial.println("or apply a voltage for the lower point in two point calibration");
  Serial.print("Enter the measured input voltage:");
  zero_voltage = read_float();
  Serial.println(zero_voltage, 6);

  // Set OSR to 32768
  adc_command = BUILD_OSR_COMMAND[9];                  // Build OSR command
  if (LTC2449_EOC_timeout(LTC2449_CS, MISO_TIMEOUT))    // Checks for EOC with a timeout
    return(1);
  LTC2449_read(LTC2449_CS, adc_command, &adc_code);     // Send OSR command

  adc_command = BUILD_COMMAND_SINGLE_ENDED[0] | LTC2449_OSR_32768 | LTC2449_SPEED_1X;   // Build ADC command byte for voltage input
  if (LTC2449_EOC_timeout(LTC2449_CS, MISO_TIMEOUT))    // Checks for EOC with a timeout
    return(1);
  LTC2449_read(LTC2449_CS, adc_command, &adc_code);     // Throw away previous reading
  delay(100);
  if (LTC2449_EOC_timeout(LTC2449_CS, MISO_TIMEOUT))    // Checks for EOC with a timeout
    return(1);
  LTC2449_read(LTC2449_CS, adc_command, &zero_code);    // Measure zero

  Serial.println("Apply ~2.40V input voltage to CH0.");
  Serial.println("Enter the measured input voltage:");

  fs_voltage = read_float();
  if (LTC2449_EOC_timeout(LTC2449_CS, MISO_TIMEOUT))    // Checks for EOC with a timeout
    return(1);
  LTC2449_read(LTC2449_CS, adc_command, &adc_code);     // Throw away previous reading
  delay(100);
  if (LTC2449_EOC_timeout(LTC2449_CS, MISO_TIMEOUT))    // Checks for EOC with a timeout
    return(1);
  LTC2449_read(LTC2449_CS, adc_command, &fs_code);      // Measure full scale
  LTC2449_cal_voltage(zero_code, fs_code, zero_voltage, fs_voltage, &LTC2449_lsb, &LTC2449_offset_code);

  Serial.print("ADC offset : ");
  Serial.println(LTC2449_offset_code);
  Serial.print(" ADC lsb : ");
  Serial.print(LTC2449_lsb*1.0e9, 4);
  Serial.println("nV (32-bits)");
  store_calibration();
  return(0);
}

//! Set Oversample Ratio (OSR)
//! @return void
void menu_4_set_OSR()
{
  int16_t user_command; // The user input command

  // Oversample Ratio Settings
  Serial.print(F("Oversample Ratio Settings\n"));   // Display  OSR menu
  Serial.print(F("1-64\n"));
  Serial.print(F("2-128\n"));
  Serial.print(F("3-256\n"));
  Serial.print(F("4-512\n"));
  Serial.print(F("5-1024\n"));
  Serial.print(F("6-2048\n"));
  Serial.print(F("7-4096\n"));
  Serial.print(F("8-8192\n"));
  Serial.print(F("9-16384\n"));
  Serial.print(F("10-32768\n"));
  Serial.print("\nEnter a Command: ");

  user_command = read_int();
  Serial.println(user_command);

  OSR_mode = BUILD_OSR_COMMAND[user_command];       // Build OSR command

  Serial.print("\nADC OSR Command: B");
  Serial.println(OSR_mode, BIN);
}

//! Set 1X or 2X mode
//! @return void
void menu_5_set_1X2X()
{
  int16_t user_command; // The user input command

  // 2X Mode
  Serial.print(F("2X Mode Settings\n\n"));
  Serial.print(F("0-Disable\n"));
  Serial.print(F("1-Enable\n"));
  Serial.print(F("Enter a Command: "));
  user_command = read_int();
  Serial.println(user_command);

  if (user_command == 0)
  {
    two_x_mode = LTC2449_SPEED_1X;
    Serial.print(F("2X Mode Disabled\n"));
  }
  else
  {
    two_x_mode = LTC2449_SPEED_2X;
    Serial.print(F("2X Mode Enabled\n"));
  }
}

//! Store measured calibration parameters to nonvolatile EEPROM on demo board
//! @return void
void store_calibration()
// store the ADC calibration to the EEPROM
{
  eeprom_write_int16(EEPROM_I2C_ADDRESS, EEPROM_CAL_KEY, EEPROM_CAL_STATUS_ADDRESS);           // Cal key
  eeprom_write_int32(EEPROM_I2C_ADDRESS, LTC2449_offset_code, EEPROM_CAL_STATUS_ADDRESS+2);    // Offset
  eeprom_write_float(EEPROM_I2C_ADDRESS, LTC2449_lsb, EEPROM_CAL_STATUS_ADDRESS+6);            // LSB
  Serial.println("Calibration Stored to EEPROM");
}

//! Enable / Disable calibration without actually touching stored calibration values
//! @return void
void menu_6_en_dis_cal()
{
  int16_t user_command; // The user input command

  Serial.println(F("Enable / Disable calibration key"));
  Serial.println(F("0-Disable\n"));
  Serial.println(F("1-Enable - use ONLY if you know a calibration has been performed previously\n"));
  Serial.println(F("Enter a Command: "));
  user_command = read_int();

  if (user_command == 0)
  {
    eeprom_write_int16(EEPROM_I2C_ADDRESS, 0xFFFF, EEPROM_CAL_STATUS_ADDRESS);           // Reset cal key
    Serial.print(F("Calibration Disabled\n"));
  }
  else
  {
    eeprom_write_int16(EEPROM_I2C_ADDRESS, EEPROM_CAL_KEY, EEPROM_CAL_STATUS_ADDRESS);   // Set cal key
    Serial.print(F("Calibration Enabled\n"));
  }
  restore_calibration();
}

//! Read stored calibration parameters from nonvolatile EEPROM on demo board
//! @return return 1 if successful, 0 if not
int8_t restore_calibration()
// read the calibration from EEPROM
{
  int16_t cal_key;
  // read the cal key from the EEPROM
  eeprom_read_int16(EEPROM_I2C_ADDRESS, &cal_key, EEPROM_CAL_STATUS_ADDRESS);
  if (cal_key == EEPROM_CAL_KEY)
  {
    // calibration has been stored, read offset and lsb
    eeprom_read_int32(EEPROM_I2C_ADDRESS, &LTC2449_offset_code, EEPROM_CAL_STATUS_ADDRESS+2);  // offset
    eeprom_read_float(EEPROM_I2C_ADDRESS, &LTC2449_lsb, EEPROM_CAL_STATUS_ADDRESS+6);          // lsb
    Serial.println("Calibration Restored");
    return(1);
  }
  else
  {
    Serial.println("Calibration not found");
    return(0);
  }
}

Download LTC2449 Linduino .CPP File

/*!
LTC2449: 24-Bit, 16-Channel Delta Sigma ADCs with Selectable Speed/Resolution.
LTC2442: 24-Bit, 4-Channel Delta Sigma ADC with Integrated Amplifier
LTC2448: 24-Bit, 8-/16-Channel Delta Sigma ADCs with Selectable Speed/Resolution

@verbatim

The LTC2444/LTC2445/LTC2448/LTC2449 are 8-/16-channel (4-/8-differential)
high speed 24-bit No Latency Delta Sigma ADCs. They use a proprietary
delta-sigma architecture enabling variable speed/resolution. Through a
simple 4-wire serial interface, ten speed/resolution combinations
6.9Hz/280nVRMS to 3.5kHz/25uVRMS (4kHz with external oscillator) can be
selected with no latency between conversion results or shift in DC accuracy
(offset, full-scale, linearity, drift). Additionally, a 2X speed mode can
be selected enabling output rates up to 7kHz (8kHz if an external
oscillator is used) with one cycle latency.

@endverbatim

http://www.linear.com/product/LTC2449
http://www.linear.com/product/LTC2442
http://www.linear.com/product/LTC2448

http://www.linear.com/product/LTC2449#demoboards
http://www.linear.com/product/LTC2442#demoboards
http://www.linear.com/product/LTC2448#demoboards

REVISION HISTORY
$Revision: 4776 $
$Date: 2016-03-14 11:18:29 -0700 (Mon, 14 Mar 2016) $

Copyright (c) 2013, Linear Technology Corp.(LTC)
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this
   list of conditions and the following disclaimer.
2. 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.

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.

The views and conclusions contained in the software and documentation are those
of the authors and should not be interpreted as representing official policies,
either expressed or implied, of Linear Technology Corp.

The Linear Technology Linduino is not affiliated with the official Arduino team.
However, the Linduino is only possible because of the Arduino team's commitment
to the open-source community.  Please, visit http://www.arduino.cc and
http://store.arduino.cc , and consider a purchase that will help fund their
ongoing work.
*/

//! @defgroup LTC2449 LTC2449: 24-Bit, 16-Channel Delta Sigma ADCs with Selectable Speed/Resolution

/*! @file
    @ingroup LTC2449
    Library for LTC2449: 24-Bit, 16-Channel Delta Sigma ADCs with Selectable Speed/Resolution
*/

#include <stdint.h>
#include <Arduino.h>
#include "Linduino.h"
#include "LT_SPI.h"
#include "LTC2449.h"
#include <SPI.h>

//! Define the SPI CS pin
#ifndef LTC2449_CS
#define LTC2449_CS QUIKEVAL_CS
#endif

int8_t LTC2449_EOC_timeout(uint8_t cs, uint16_t miso_timeout)
// Checks for EOC with a specified timeout (ms)
{
  uint16_t timer_count = 0;             // Timer count for MISO
  output_low(cs);                       //! 1) Pull CS low
  while (1)                             //! 2) Wait for SDO (MISO) to go low
  {
    if (input(MISO) == 0) break;        //! 3) If SDO is low, break loop
    if (timer_count++>miso_timeout)     // If timeout, return 1 (failure)
    {
      output_high(cs);                  // Pull CS high
      return(1);
    }
    else
      delay(1);
  }
  output_high(cs);                  // Pull CS high
  return(0);
}

// Reads from LTC2449.
void LTC2449_read(uint8_t cs, uint16_t adc_command, uint32_t *adc_code)
{
  LT_union_int32_4bytes data, command;  // LTC2449 data and command
  LT_union_int16_2bytes temp_comm;
  temp_comm.LT_int16 = adc_command;
  command.LT_byte[3] = temp_comm.LT_byte[1];
  command.LT_byte[2] = temp_comm.LT_byte[0];
  command.LT_byte[1] = 0;
  command.LT_byte[0] = 0;

  output_low(cs);                                                       //! 1) Pull CS low

  spi_transfer_block(cs, command.LT_byte, data.LT_byte, (uint8_t)4);    //! 2) Transfer arrays

  output_high(cs);                                                      //! 3) Pull CS high
  *adc_code = data.LT_int32;
}

// Calculates the voltage corresponding to an adc code, given lsb weight (in volts) and the calibrated
// adc offset code (zero code that is subtracted from adc_code).
float LTC2449_code_to_voltage(int32_t adc_code, float LTC2449_lsb, int32_t LTC2449_offset_code)
{
  float adc_voltage;
  adc_code -= 536870912;                                            //! 1) Converts offset binary to binary
  adc_voltage=(float)(adc_code+LTC2449_offset_code)*LTC2449_lsb;    //! 2) Calculate voltage from ADC code, lsb, offset.
  return(adc_voltage);
}

// Calculate the lsb weight and offset code given a full-scale code and a measured zero-code.
void LTC2449_cal_voltage(int32_t zero_code, int32_t fs_code, float zero_voltage, float fs_voltage, float *LTC2449_lsb, int32_t *LTC2449_offset_code)
{
  zero_code -= 536870912;   //! 1) Converts zero code from offset binary to binary
  fs_code -= 536870912;     //! 2) Converts full scale code from offset binary to binary

  float temp_offset;
  *LTC2449_lsb = (fs_voltage-zero_voltage)/((float)(fs_code - zero_code));                              //! 3) Calculate the LSB

  temp_offset = (zero_voltage/ *LTC2449_lsb) - zero_code;                                               //! 4) Calculate Unipolar offset
  temp_offset = (temp_offset > (floor(temp_offset) + 0.5)) ? ceil(temp_offset) : floor(temp_offset);    //! 5) Round
  *LTC2449_offset_code = (int32_t)temp_offset;                                                          //! 6) Cast as int32_t
}

Download LTC2449 Linduino Header File

/*!
LTC2449: 24-Bit, 16-Channel Delta Sigma ADCs with Selectable Speed/Resolution.
LTC2442: 24-Bit, 4-Channel Delta Sigma ADC with Integrated Amplifier
LTC2448: 24-Bit, 8-/16-Channel Delta Sigma ADCs with Selectable Speed/Resolution

@verbatim

The LTC2444/LTC2445/LTC2448/LTC2449 are 8-/16-channel (4-/8-differential)
high speed 24-bit No Latency Delta Sigma ADCs. They use a proprietary
delta-sigma architecture enabling variable speed/resolution. Through a
simple 4-wire serial interface, ten speed/resolution combinations
6.9Hz/280nVRMS to 3.5kHz/25uVRMS (4kHz with external oscillator) can be
selected with no latency between conversion results or shift in DC accuracy
(offset, full-scale, linearity, drift). Additionally, a 2X speed mode can
be selected enabling output rates up to 7kHz (8kHz if an external
oscillator is used) with one cycle latency.


SPI DATA FORMAT (MSB First):

            Byte #1                            Byte #2

Data Out :  !EOC DMY SIG D28 D27 D26 D25 D24   D23  D22  D21  D20  D19 D18 D17 D16
Data In  :  1    0   EN  SGL OS  S2  S1  S0    OSR3 OSR2 OSR1 OSR1 SPD X   X   X

Byte #3                        Byte #4
D15 D14 D13 D12 D11 D10 D9 D8  D7 D6 D5 D4 *D3 *D2 *D1 *D0
X   X   X   X   X   X   X  X   X  X  X  X   X  X   X   X

!EOC : End of Conversion Bit (Active Low)
DMY  : Dummy Bit (Always 0)
SIG  : Sign Bit (1-data positive, 0-data negative)
Dx   : Data Bits
*Dx  : Data Bits Below lsb
EN   : Enable Bit (0-keep previous mode, 1-change mode)
SGL  : Enable Single-Ended Bit (0-differential, 1-single-ended)
OS   : ODD/Sign Bit
Sx   : Address Select Bit
0SRX : Over Sampling Rate Bits
SPD  : Double Output Rate Select Bit (0-Normal rate, auto-calibration on, 2x rate, auto_calibration off)

Command Byte #1
1    0    EN   SGL  OS   S2   S1   S0   Comments
1    0    0    X    X    X    X    X    Keep Previous Mode
1    0    1    0    X    X    X    X    Differential Mode
1    0    1    1    X    X    X    X    Single-Ended Mode

|  Coversion Rate    |  RMS  | ENOB | OSR  | Latency
Command Byte #2          |Internal | External | Noise |      |      |
|  9MHz   | 10.24MHz |       |      |      |
OSR3 OSR2 OSR1 OSR1 SPD  | Clock   |  Clock   |       |      |      |
0    0    0    0    0      Keep Previous Speed/Resolution
0    0    0    1    0      3.52kHz   4kHz       23uV    17     64     none
0    0    1    0    0      1.76kHz   2kHz       3.5uV   20.1   128    none
0    0    1    1    0      880Hz     1kHz       2uV     21.3   256    none
0    1    0    0    0      440Hz     500Hz      1.4uV   21.8   512    none
0    1    0    1    0      220Hz     250Hz      1uV     22.4   1024   none
0    1    1    0    0      110Hz     125Hz      750nV   22.9   2048   none
0    1    1    1    0      55Hz      62.5Hz     510nV   23.4   4096   none
1    0    0    0    0      27.5Hz    31.25Hz    375nV   24     8192   none
1    0    0    1    0      13.75Hz   15.625Hz   250nV   24.4   16384  none
1    1    1    1    0      6.87kHz   7.8125Hz   200nV   24.6   32768  none
0    0    0    0    1      Keep Previous Speed/Resolution
OSR3 OSR2 OSR1 OSR1 1      2X Mode  *all clock speeds double

Example Code:

Read Channel 0 in Single-Ended with OSR of 65536

    uint16_t miso_timeout = 1000;
    adc_command = LTC2449_CH0 | LTC2449_OSR_32768 | LTC2449_SPEED_2X;   // Build ADC command for channel 0
                                                                        // OSR = 32768*2 = 65536

    if(LTC2449_EOC_timeout(LTC2449_CS, miso_timeout))    // Check for EOC
        return;                                          // Exit if timeout is reached
    LTC2449_read(LTC2449_CS, adc_command, &adc_code);    // Throws out last reading

    if(LTC2449_EOC_timeout(LTC2449_CS, miso_timeout))    // Check for EOC
        return;                                          // Exit if timeout is reached
    LTC2449_read(LTC2449_CS, adc_command, &adc_code);    // Obtains the current reading and stores to adc_code variable

    // Convert adc_code to voltage
    adc_voltage = LTC2449_code_to_voltage(adc_code, LTC2449_lsb, LTC2449_offset_code);

@endverbatim

http://www.linear.com/product/LTC2449
http://www.linear.com/product/LTC2442
http://www.linear.com/product/LTC2448

http://www.linear.com/product/LTC2449#demoboards
http://www.linear.com/product/LTC2442#demoboards
http://www.linear.com/product/LTC2448#demoboards

REVISION HISTORY
$Revision: 4776 $
$Date: 2016-03-14 11:18:29 -0700 (Mon, 14 Mar 2016) $

Copyright (c) 2013, Linear Technology Corp.(LTC)
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this
   list of conditions and the following disclaimer.
2. 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.

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.

The views and conclusions contained in the software and documentation are those
of the authors and should not be interpreted as representing official policies,
either expressed or implied, of Linear Technology Corp.

The Linear Technology Linduino is not affiliated with the official Arduino team.
However, the Linduino is only possible because of the Arduino team's commitment
to the open-source community.  Please, visit http://www.arduino.cc and
http://store.arduino.cc , and consider a purchase that will help fund their
ongoing work.
*/

/*! @file
    @ingroup LTC2449
    Header for LTC2449: 24-Bit, 16-Channel Delta Sigma ADCs with Selectable Speed/Resolution
*/

#ifndef LTC2449_H
#define LTC2449_H

//! Define the SPI CS pin
#ifndef LTC2449_CS
#define LTC2449_CS QUIKEVAL_CS
#endif

/*! @name Mode Configuration
 @{
*/
#define LTC2449_KEEP_PREVIOUS_MODE              0x8000
#define LTC2449_KEEP_PREVIOUS_SPEED_RESOLUTION  0x0000
#define LTC2449_SPEED_1X                        0x0000
#define LTC2449_SPEED_2X                        0x0008
/*!
 @}
*/

/*! @name Single-Ended Channels Configuration
@{ */
#define LTC2449_CH0            0xB000
#define LTC2449_CH1            0xB800
#define LTC2449_CH2            0xB100
#define LTC2449_CH3            0xB900
#define LTC2449_CH4            0xB200
#define LTC2449_CH5            0xBA00
#define LTC2449_CH6            0xB300
#define LTC2449_CH7            0xBB00
#define LTC2449_CH8            0xB400
#define LTC2449_CH9            0xBC00
#define LTC2449_CH10           0xB500
#define LTC2449_CH11           0xBD00
#define LTC2449_CH12           0xB600
#define LTC2449_CH13           0xBE00
#define LTC2449_CH14           0xB700
#define LTC2449_CH15           0xBF00
/*! @} */

/*! @name Differential Channel Configuration
@{ */
#define LTC2449_P0_N1          0xA000
#define LTC2449_P1_N0          0xA800

#define LTC2449_P2_N3          0xA100
#define LTC2449_P3_N2          0xA900

#define LTC2449_P4_N5          0xA200
#define LTC2449_P5_N4          0xAA00

#define LTC2449_P6_N7          0xA300
#define LTC2449_P7_N6          0xAB00

#define LTC2449_P8_N9          0xA400
#define LTC2449_P9_N8          0xAC00

#define LTC2449_P10_N11        0xA500
#define LTC2449_P11_N10        0xAD00

#define LTC2449_P12_N13        0xA600
#define LTC2449_P13_N12        0xAE00

#define LTC2449_P14_N15        0xA700
#define LTC2449_P15_N14        0xAF00
/*! @} */

/*Commands
Construct a channel / resolution control word by bitwise ORing one choice from the channel configuration
and one choice from the Oversample ratio configuration. You can also enable 2Xmode, which will increase
sample rate by a factor of 2 but introduce one cycle of latency.

Example - read channel 3 single-ended at OSR2048, with 2X mode enabled.
adc_command = (LTC2449_CH3 | LTC2449_OSR_2048) | LTC2449_SPEED_2X;
*/

/*! @name Oversample Ratio (OSR) Commands
@{ */
#define LTC2449_OSR_64         0xA010
#define LTC2449_OSR_128        0xA020
#define LTC2449_OSR_256        0xA030
#define LTC2449_OSR_512        0xA040
#define LTC2449_OSR_1024       0xA050
#define LTC2449_OSR_2048       0xA060
#define LTC2449_OSR_4096       0xA070
#define LTC2449_OSR_8192       0xA080
#define LTC2449_OSR_16384      0xA090
#define LTC2449_OSR_32768      0xA0F0
/*! @}*/

//! Checks for EOC with a specified timeout
//! @return Returns 0=successful, 1=unsuccessful (exceeded timeout)
int8_t LTC2449_EOC_timeout(uint8_t cs,           //!< Chip Select pin
                           uint16_t miso_timeout  //!< Timeout (in milliseconds)
                          );

//! Reads from LTC2449.
//! @return  void
void LTC2449_read(uint8_t cs,               //!< Chip Select pin
                  uint16_t adc_command,     //!< 2 byte command written to LTC2449
                  uint32_t *adc_code        //!< 4 byte conversion code read from LTC2449
                 );

//! Calculates the voltage corresponding to an adc code, given lsb weight (in volts) and the calibrated
//! ADC offset code (zero code that is subtracted from adc_code).
//! @return Returns voltage calculated from ADC code.
float LTC2449_code_to_voltage(int32_t adc_code,             //!< Code read from adc
                              float LTC2449_lsb,            //!< LSB weight (in volts)
                              int32_t LTC2449_offset_code   //!< The calibrated offset code (This is the adc code zero code that will be subtraced from adc_code)
                             );

//! Calculate the lsb weight and offset code given a full-scale code and a measured zero-code.
//! @return Void
void LTC2449_cal_voltage(int32_t zero_code,             //!< Measured code with the inputs shorted to ground
                         int32_t fs_code,               //!< Measured code at nearly full-scale
                         float zero_voltage,            //!< Measured zero voltage
                         float fs_voltage,              //!< Voltage measured at input (with voltmeter) when fs_code was read from adc
                         float *LTC2449_lsb,            //!< Overwritten with lsb weight (in volts)
                         int32_t *LTC2449_offset_code   //!< Overwritten with offset code (zero code)
                        );

#endif  // LTC2449_H

Technical Support