【Arduino】从零开始使用Arduino驱动ADS1118
本文介绍了如何使用Arduino驱动ADS1118模数转换器的详细方法。ADS1118是一款16位精度的ADC芯片,支持SPI通信,具有双路差分或四路单端输入。文章重点解析了芯片的寄存器配置,包括输入通道选择、增益设置、工作模式等关键参数,并提供了完整的C++实现代码。通过创建ADS1118类封装核心功能,实现了寄存器配置更新和电压读取功能,其中电压解算部分针对±4.096V量程进行了优化。该驱动
【Arduino】从零开始使用Arduino驱动ADS1118
ADS1118介绍
基本信息
根据ADS1118数据手册介绍,ADS1118 是一款16位ADC,支持双路差分输入或四路单端输入,通过 SPI 传输数据。
引脚介绍
本文使用的是优信电子的ADS118模块。
由于使用的是现成模块,我们对于硬件设计便不需要过多关注。因此只需要关注手册9.5 Programming部分。ADS1118的SPI接口如下
| 引脚名称 | 引脚介绍 |
|---|---|
| SCLK | 串口时钟,不使用时保持低电平 |
| CS# | 片选引脚 |
| DIN | 输入引脚 |
| DOUT | 数据输出和数据就绪引脚 |
数据格式与检索
ADS1118提供16位二进制补码格式的数据,最高位对应符号位。正满量程对应0x7fff。负满量程对应0x8000,输入为0时对应0x0000。也就是说,计算数据时,首先通过最高位判断该数据是正数还是负数,然后通过计算得到其数值。
如果需要反复回读配置寄存器,那么需要选择32位读写。本文选择使用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);
}
更多推荐



所有评论(0)