ADS1118介绍

基本信息

根据ADS1118数据手册介绍,ADS1118 是一款16位ADC,支持双路差分输入或四路单端输入,通过 SPI 传输数据。
ADS1118手册介绍

引脚介绍

本文使用的是优信电子的ADS118模块。
ADS1118模块图
由于使用的是现成模块,我们对于硬件设计便不需要过多关注。因此只需要关注手册9.5 Programming部分。ADS1118的SPI接口如下

引脚名称 引脚介绍
SCLK 串口时钟,不使用时保持低电平
CS# 片选引脚
DIN 输入引脚
DOUT 数据输出和数据就绪引脚

数据格式与检索

ADS1118提供16位二进制补码格式的数据,最高位对应符号位。正满量程对应0x7fff。负满量程对应0x8000,输入为0时对应0x0000。也就是说,计算数据时,首先通过最高位判断该数据是正数还是负数,然后通过计算得到其数值。
数据格式
如果需要反复回读配置寄存器,那么需要选择32位读写。本文选择使用16位读写,时序图如下:
16位读写时序图SPI通信的模式在10.1.1 Serial Interface Connections中提到是SPI模式1(CPOL = 0 and CPHA = 1)。

寄存器介绍

ADS1118主要是两个寄存器,一个是Conversion Register寄存器,用于存放转换结果,一个Config Register是配置寄存器。通过时序图可以看到,只需要写入配置寄存器就可以获取转换结果的数据。根据介绍各个寄存器的效果如下

位(Bit) 字段(Field) 类型(Type) 复位值(Reset) 描述(Description)
15 SS R/W 0h 用于启动单次转换。仅在掉电状态下可写,转换进行中时写入无效。写入0无效果,写入1在掉电状态下启动单次转换。读取时始终返回0。
14-12 MUX[2:0] R/W 0h 用于选择输入通道,配置模拟输入的正负极连接。
11-9 PGA[2:0] R/W 2h 用于配置可编程增益放大器(PGA)的增益,决定 ADS1118 的满量程范围。
8 MODE R/W 1h 用于选择 ADS1118 的工作模式。0 为连续转换模式,1 为单次转换模式(转换完成后进入掉电状态)。
7-5 DR[2:0] R/W 4h 用于配置数据输出速率,对应不同的采样率,如 128SPS、250SPS 等。
4 TS_MODE R/W 0h 用于选择温度传感器模式。0 禁用温度传感器,1 启用温度传感器(测量内部温度)。
3 PULL_UP_EN R/W 1h 用于启用或禁用 DOUT/DRDY 引脚上的上拉电阻。0 禁用,1 启用。
2-1 NOP[1:0] R/W 1h 无操作位,通常保留用于未来扩展或特定功能,写入时不影响器件操作。
0 Reserved R 1h 保留位,用于未来功能扩展,读取时返回默认值,写入时无效果。

此处需要注意一下NOP寄存器必须要是0x01的情况时才能更新配置寄存器的值,否则是无法修改的。

代码实现

寄存器功能

为了方便调用配置ADS1118,用枚举的方式将每个寄存器可以写入的值进行实现。

typedef enum
{
    Start = 0b1 << 15,
    NoEffect = 0b0 << 15 // default

} SS_t; // 15

typedef enum : uint16_t
{
    AIN0_AIN1 = 0b000 << 12, // default
    AIN0_AIN3 = 0b001 << 12,
    AIN1_AIN3 = 0b010 << 12,
    AIN2_AIN3 = 0b011 << 12,
    AIN0 = 0b100 << 12,
    AIN1 = 0b101 << 12,
    AIN2 = 0b110 << 12,
    AIN3 = 0b111 << 12,
} MUX_t; // 14 13 12

typedef enum : uint16_t
{
    PGA_6144 = 0b000 << 9,
    PGA_4096 = 0b001 << 9,
    PGA_2048 = 0b010 << 9, // default
    PGA_1024 = 0b011 << 9,
    PGA_0512 = 0b100 << 9,
    PGA_0256 = 0b101 << 9,
} PGA_t; // 11 10 9

typedef enum : uint16_t
{
    ContinuousConversion = 0b0 << 8,
    SingleConversion = 0b1 << 8,
} MODE_t;

typedef enum : uint16_t
{
    SPS_8 = 0b000 << 5,
    SPS_16 = 0b001 << 5,
    SPS_32 = 0b010 << 5,
    SPS_64 = 0b011 << 5,
    SPS_128 = 0b100 << 5,
    SPS_250 = 0b101 << 5,
    SPS_470 = 0b110 << 5,
    SPS_860 = 0b111 << 5,
} DR_t;

typedef enum : uint16_t
{
    ADC_MODE = 0b0 << 4,
    TEMPERATURE_MODE = 0b1 << 4,
} TS_MODE_t;

typedef enum : uint16_t
{
    PULL_UP_ENA = 0b0 << 3,
    PULL_UP_DIS = 0b1 << 3,
} PULL_UP_EN_t;

typedef enum : uint16_t
{
    NOP_UPDATE = 0b01 << 1,
} NOP_t;

ADS1118对象

模仿Arduino大部分库的写法,创建一个ADS1118对象,然后完成其中功能。其中主要是setup()radVoltage()函数。对于updateConfig()函数则是在配置玩寄存器功能后,更新到configCmd中方便下一次调用。

class ADS1118
{
public:
    SS_t         SS;
    MUX_t        MUX;
    PGA_t        PGA;
    MODE_t       MODE;
    DR_t         DR;
    TS_MODE_t    TS_MODE;
    PULL_UP_EN_t PULL_UP_EN;
    NOP_t        NOP;
    void         setup();
    void         updateConfig();
    float        readVoltage();

private:
    uint16_t configCmd;
};

setup

setup函数用于建立SPI通讯。根据手册要求设置高位先行和SPI模式1。

SPISettings spiSettings(1000000, MSBFIRST, SPI_MODE1);

/**
 * @brief         初始化ADS1118
 * @author        Fantastic
 * @date          2025-07-14
 * @version       0.0.1
 */
void ADS1118::setup(void)
{
    /*配置SPI通信*/
    SPI.begin();
    pinMode(ADS1118_SS, OUTPUT);

    /*配置CS引脚*/
    digitalWrite(ADS1118_SS, HIGH);
    digitalWrite(ADS1118_SS, LOW);

    /*发送一个默认配置*/
    SPI.beginTransaction(spiSettings);
    SPI.transfer16(0xc28a);
    digitalWrite(ADS1118_SS, HIGH);
    SPI.endTransaction();
}

updateConfig

updateConfig用于将写入的命令更新为用户设置的寄存器值。

/**
 * @brief         更新配置
 * @author        Fantastic
 * @date          2025-07-14
 * @version       0.0.1
 */
void ADS1118::updateConfig()
{
    configCmd = SS | MUX | PGA | MODE | DR | TS_MODE | PULL_UP_EN | NOP;
}

readVoltage

readVoltage函数是读取电压函数,并且完成对数据的解算。
根据手册说明,CS引脚拉低后,当 D R D Y ‾ \overline{DRDY} DRDY(其实就是DOUT引脚)引脚出低电平时说明转换完毕。因此最好等待一下转换结果再进行读取。

/**
 * @brief         读取电压
 * @return        float 电压值
 * @author        Fantastic
 * @date          2025-07-14
 * @version       0.0.1
 */
float ADS1118::readVoltage(void)
{
    /*SPI通讯获取数据*/
    digitalWrite(ADS1118_SS, LOW);
    while (digitalRead(ADS1118_DRDY) == HIGH)
        ;
    SPI.beginTransaction(spiSettings);
    uint16_t rawData = SPI.transfer16(configCmd);
    digitalWrite(ADS1118_SS, HIGH);
    SPI.endTransaction();
    /*转换为电压*/
    int16_t adcValue = static_cast<int16_t>(rawData);

    // 根据PGA计算实际电压
    float voltage;
    switch (PGA) {
    case PGA_6144: voltage = adcValue * 0.1875f; break;
    case PGA_4096: voltage = adcValue * 0.125f; break;
    case PGA_2048: voltage = adcValue * 0.0625f; break;
    case PGA_1024: voltage = adcValue * 0.03125f; break;
    case PGA_0512: voltage = adcValue * 0.015625f; break;
    case PGA_0256: voltage = adcValue * 0.0078125f; break;
    default: voltage = adcValue * 0.125f;
    }
}

完整代码

ADS1118.hpp

#ifndef ADS1118_H
#define ADS1118_H

#include <Arduino.h>
#define ADS1118_SS 10

/* ---------------------------------- 类型定义 ---------------------------------- */

typedef enum
{
    Start    = 0b1 << 15,
    NoEffect = 0b0 << 15   // default

} SS_t;   // 15

typedef enum
{
    AIN0_AIN1 = 0b000 << 14,   // default
    AIN0_AIN3 = 0b001 << 14,
    AIN1_AIN3 = 0b010 << 14,
    AIN2_AIN3 = 0b011 << 14,
    AIN0      = 0b100 << 14,
    AIN1      = 0b101 << 14,
    AIN2      = 0b110 << 14,
    AIN3      = 0b111 << 14,
} MUX_t;   // 14 13 12

typedef enum
{
    PGA_6144 = 0b000 << 11,
    PGA_4096 = 0b001 << 11,
    PGA_2048 = 0b010 << 11,   // default
    PGA_1024 = 0b011 << 11,
    PGA_0512 = 0b100 << 11,
    PGA_0256 = 0b101 << 11,
} PGA_t;   // 11 10 9

typedef enum
{
    ContinuousConversion = 0b0 << 8,
    SingleConversion     = 0b1 << 8,
} MODE_t;

typedef enum
{
    SPS_8   = 0b000 << 7,
    SPS_16  = 0b001 << 7,
    SPS_32  = 0b010 << 7,
    SPS_64  = 0b011 << 7,
    SPS_128 = 0b100 << 7,
    SPS_250 = 0b101 << 7,
    SPS_470 = 0b110 << 7,
    SPS_860 = 0b111 << 7,
} DR_t;

typedef enum
{
    ADC_MODE         = 0b0 << 4,
    TEMPERATURE_MODE = 0b1 << 4,
} TS_MODE_t;

typedef enum
{
    PULL_UP_ENA = 0b0 << 3,
    PULL_UP_DIS = 0b1 << 3,
} PULL_UP_EN_t;

typedef enum
{
    NOP_UPDATE = 0b01 << 2,
} NOP_t;

/* ----------------------------------- 类声明 ---------------------------------- */

class ADS1118
{
public:
    SS_t         SS;
    MUX_t        MUX;
    PGA_t        PGA;
    MODE_t       MODE;
    DR_t         DR;
    TS_MODE_t    TS_MODE;
    PULL_UP_EN_t PULL_UP_EN;
    NOP_t        NOP;
    void         setup();
    void         updateConfig();
    float        readVoltage();

private:
    uint16_t configCmd;
};

// 0xc28a

#endif

ADS1118.cpp

#include "ADS1118.hpp"
#include "Arduino.h"
#include "HardwareSerial.h"
#include "Print.h"
#include "SPI.h"

SPISettings spiSettings(1000000, MSBFIRST, SPI_MODE1);

/**
 * @brief         初始化ADS1118
 * @author        Fantastic
 * @date          2025-07-14
 * @version       0.0.1
 */
void ADS1118::setup(void)
{
    /*配置SPI通信*/
    SPI.begin();
    pinMode(ADS1118_SS, OUTPUT);

    /*配置CS引脚*/
    digitalWrite(ADS1118_SS, HIGH);
    digitalWrite(ADS1118_SS, LOW);

    /*发送一个默认配置*/
    SPI.beginTransaction(spiSettings);
    SPI.transfer16(0xc28a);
    digitalWrite(ADS1118_SS, HIGH);
    SPI.endTransaction();
}

/**
 * @brief         读取电压
 * @return        float 电压值
 * @author        Fantastic
 * @date          2025-07-14
 * @version       0.0.1
 */
float ADS1118::readVoltage(void)
{
     digitalWrite(ADS1118_SS, LOW);


    while (digitalRead(ADS1118_DRDY) == HIGH)
        ;
    SPI.beginTransaction(spiSettings);
    uint16_t rawData = SPI.transfer16(configCmd);
    digitalWrite(ADS1118_SS, HIGH);
    SPI.endTransaction();
    /*转换为电压*/
    int16_t adcValue = static_cast<int16_t>(rawData);

    // 根据PGA计算实际电压
    float voltage;
    switch (PGA) {
    case PGA_6144: voltage = adcValue * 0.1875f; break;
    case PGA_4096: voltage = adcValue * 0.125f; break;
    case PGA_2048: voltage = adcValue * 0.0625f; break;
    case PGA_1024: voltage = adcValue * 0.03125f; break;
    case PGA_0512: voltage = adcValue * 0.015625f; break;
    case PGA_0256: voltage = adcValue * 0.0078125f; break;
    default: voltage = adcValue * 0.125f;
    }
}

/**
 * @brief         更新配置
 * @author        Fantastic
 * @date          2025-07-14
 * @version       0.0.1
 */
void ADS1118::updateConfig()
{
    configCmd = SS | MUX | PGA | MODE | DR | TS_MODE | PULL_UP_EN | NOP;
}

main.ino

#include "ADS1118.hpp"
ADS1118 ads1118;

void setup()
{
    Serial.begin(115200);
    ads1118.SS = Start;
    ads1118.MUX = AIN0;
    ads1118.PGA = PGA_4096;
    ads1118.MODE = ContinuousConversion;
    ads1118.DR = SPS_128;
    ads1118.TS_MODE = ADC_MODE;
    ads1118.PULL_UP_EN = PULL_UP_ENA;
    ads1118.NOP = NOP_UPDATE;
    ads1118.setup();
}

void loop()
{
    int16_t value1, value2;
    ads1118.MUX = AIN1;
    ads1118.updateConfig();
    value1 = ads1118.readVoltage();
    ads1118.MUX = AIN0;
    ads1118.updateConfig();
    value2 = ads1118.readVoltage();

    Serial.println(String(value1) + "," + String(value2));
    delay(10);
}
Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐