文章目录
德州仪器ADS1220概述
-
高性能 24 位Δ-Σ 模数转换器(ADC)
-
支持两个差分输入或四个单端输入
-
集成了低噪声可编程增益放大器(PGA)、双可编程激励电流源、电压基准、振荡器、低侧开关以及精密温度传感器
-
支持高达 2000 SPS 的采样速率,并能在单周期内完成稳定转换
-
其数字滤波器在 20SPS 采样频率下可同时抑制 50Hz 和 60Hz 干扰
-
内部 PGA 提供高达 128V/V 的增益,特别适用于小型传感器信号测量
-
器件支持伪差分或全差分信号测量,并可通过配置禁用内部 PGA,在保持高输入阻抗的同时提供最高 4V/V 增益,实现单端测量
-
在禁用 PGA 的占空比模式下,器件功耗可低至 120µA
-
ADS1220 采用 VQFN-16 或 TSSOP-16 封装,工作温度范围为 -40°C 至 +125°C,适用于严苛环境下的精密测量应用。
资料
引脚&封装
布线

在AIN0和AIN1之间、AIN2和AIN3之间、REFP0和REFN0之间的外围都是两个电阻三个电容,其作用如下:
- 抗混叠滤波
差分电容与电阻构成一阶RC滤波器,用于限制高频噪声和混叠效应。Δ-Σ ADC的调制器以高频(如256kHz)采样输入信号,未衰减的高频成分会混叠到通带,导致测量误差。 - 共模噪声抑制
共模电容用于衰减共模噪声。差分电容应比共模电容大10倍,以避免电容不匹配将共模噪声转为差分噪声。 - 保护ADC输入
外部滤波器电阻还限制输入过压时的电流,保护内部ESD二极管。
寄存器

配置寄存器0(00h)
- MUX[3:0] :输入多路复用器配置,选择差分/单端输入组合或系统监测功能(如电源/基准监测)。
单端测量需禁用PGA,差分测量可启用PGA高增益。 - GAIN[2:0] :设置PGA增益(1至128),禁用PGA时仅支持增益1/2/4。
低噪声放大器,用于放大微小传感器信号(如热电偶/RTD)。 - PGA_BYPASS :禁用和旁路PGA以扩展共模电压范围(AVSS-0.1V至AVDD+0.1V)。
单端信号测量或需宽共模电压时启用。 当PGA旁路时,内部放大器被禁用,牺牲增益换取更宽输入范围。
配置寄存器1(01h)
- DR[2:0]:选择数据速率(5SPS至2kSPS),随工作模式(正常/占空比/Turbo)变化。
- MODE[1:0]:设置工作模式(正常/占空比/Turbo)。
- CM:转换模式选择(单次/连续)。
- TS:启用内部温度传感器模式。
- BCS :控制10μA烧毁电流源,用于传感器故障检测。
烧毁电流源用于检测传感器开路(拉至满量程)或短路(近零读数),但会引入测量误差,精密测量需禁用以避免干扰。
配置寄存器2(02h)
- VREF[1:0] :选择基准源(内部2.048V/外部基准/电源)。
- 50/60[1:0] :配置FIR滤波器抑制50Hz/60Hz工频干扰。
启用抑制会限制数据速率(仅20SPS或5SPS下有效)。
未启用时(50/60[1:0]=00),滤波器带宽更宽,适合高频信号但抗干扰能力下降。 - PSW:控制低侧电源开关(AIN3/REFN1至AVSS)。
- IDAC[2:0] :设置激励电流源输出(10μA至1.5mA)。
典型应用是为RTD(电阻温度检测器)等传感器提供精确的激励电流,通过将IDAC1和IDAC2分别接入RTD的两条引线,利用匹配的电流抵消引线电阻产生的压降误差。
IDAC合规电压是电流源输出端电压需≤AVDD-0.9V,否则精度下降。
配置寄存器3(03h)
- I1MUX[2:0]:路由IDAC1至指定引脚(AINx或基准输入)。
- I2MUX[2:0]:路由IDAC2至指定引脚(AINx或基准输入)。
- DRDYM:选择DRDY指示模式(仅专用引脚或复用DOUT/DRDY)。
- 保留位:固定写0。
连续转换流程
- 上电:延迟以允许电源稳定并完成上电复位(最小50 µs)。
- 配置
SPI
接口:将微控制器的SPI
接口配置为模式1(CPOL = 0
,CPHA = 1
)。 - 配置片选引脚:如果片选(
CS
)引脚未永久接地,将连接到CS
的微控制器GPIO
配置为输出。 - 配置数据准备好引脚:将连接到
DRDY
引脚的微控制器GPIO
配置为下降沿触发的中断输入。 - 拉低片选信号:将
CS
拉低以选中设备。 - 延迟CSSC时间:延迟至少td(
CSSC
)的时间。 - 发送复位命令:发送复位命令(06h),确保设备在上电后正确复位。
- 延迟复位时间:延迟至少50 µs + 32 * t(CLK)的时间。
- 写入寄存器配置:使用
WREG
命令(43h, 08h, 04h, 10h, 和00h)写入相应的寄存器配置。 - 可选配置验证:作为可选的验证步骤,使用RREG命令(23h)读回所有配置寄存器。
- 启动转换:发送
START/SYNC
命令(08h),以连续转换模式启动转换。 - 延迟SCCS时间:延迟至少td(
SCCS
)的时间。 - 释放片选信号:将
CS
拉高以重置串行接口。 - 数据读取循环,循环执行以下操作:
14.1 等待DRDY
引脚变为低电平。
14.2 将CS
拉低。
14.3 延迟至少td(CSSC
)的时间。
14.4 发送24个SCLK
上升沿,以从DOUT/DRDY
读取转换数据。
14.5 延迟至少td(SCCS
)的时间。
14.6 将CS
拉高。 - 进入待机模式
15.1 将CS
拉低。
15.2 延迟至少td(CSSC
)的时间。
15.3 发送POWERDOWN
命令(02h),停止转换并将设备置于待机模式。
15.4 延迟至少td(SCCS
)的时间。
15.5 将CS
拉高。
注:上面的步骤14.1中,等待
DRDY
引脚变为低电平,但在一些应用中,DRDY
引脚可能没有接入MCU。这种情况可以等待
DOUT/DRDY
引脚变为低电平,以确认ADC已经完成转化。
但需要注意先拉低片选,再去等待DOUT/DRDY
引脚变为低电平。.
驱动源码
ads1220.c
c
/**
******************************************************************************
* @file ads1220.c
* @author zjq
* @brief ads1220 bsp
******************************************************************************
*/
#include "ads1220.h"
#include "Gpio.h"
#include "spi.h"
/* Cmd ***********************************************************************/
const uint8_t ADS1220_CMD_RESET = 0x06;
const uint8_t ADS1220_CMD_START = 0x08;
const uint8_t ADS1220_CMD_RDATA = 0x10;
const uint8_t ADS1220_CMD_PWR_DOWN = 0x02;
const uint8_t ADS1220_CMD_READ_REG = 0x20;
const uint8_t ADS1220_CMD_WRITE_REG = 0x40;
/* Static Function ***********************************************************/
static ADS1220_StatusTypedef ADS1220_SPI_Write(uint8_t const *pWrite, uint8_t len);
static ADS1220_StatusTypedef ADS1220_SPI_Receive(uint8_t *pRecv, uint8_t len);
static ADS1220_StatusTypedef ADS1220_WriteRegister(uint32_t regStartAddr, uint32_t regNum, uint8_t *pData);
static ADS1220_StatusTypedef ADS1220_ReadRegister(uint32_t regStartAddr, uint32_t regNum, uint8_t *pData);
/**
* @brief Use SPI Write to ADS1220
* @param pWrite
* @param len
* @retval ADS1220 Status
*/
static ADS1220_StatusTypedef ADS1220_SPI_Write(uint8_t const *pWrite, uint8_t len)
{
for (uint8_t i = 0; i < len; i++)
{
if (HAL_OK != HAL_SPI_Transmit(&hspi3, &pWrite[i], 1, 10))
{
return ADS1220_FAIL;
}
}
return ADS1220_OK;
}
/**
* @brief Use SPI Read From ADS1220
* @param pRecv
* @param len
* @retval ADS1220 Status
*/
static ADS1220_StatusTypedef ADS1220_SPI_Receive(uint8_t *pRecv, uint8_t len)
{
uint8_t temp = 0xff;
for (uint8_t i = 0; i < len; i++)
{
if (HAL_OK != HAL_SPI_TransmitReceive(&hspi3, &temp, &pRecv[i], 1, 10))
{
return ADS1220_FAIL;
}
}
return ADS1220_OK;
}
/**
* @brief Write ADS1220 Register
* @param regStartAddr
* @param regNum
* @param pData
* @retval ADS1220 Status
*/
static ADS1220_StatusTypedef ADS1220_WriteRegister(uint32_t regStartAddr, uint32_t regNum, uint8_t *pData)
{
ADS1220_CS_LOW();
HAL_Delay(10);
uint8_t temp = ((regStartAddr << 2) & 0x0c);
temp |= (regNum - 1) & 0x03;
temp |= ADS1220_CMD_WRITE_REG;
if (ADS1220_OK != ADS1220_SPI_Write(&temp, 1))
{
return ADS1220_FAIL;
}
if (ADS1220_OK != ADS1220_SPI_Write(pData, regNum))
{
return ADS1220_FAIL;
}
ADS1220_CS_HIGH();
return ADS1220_OK;
}
/**
* @brief Read ADS1220 Register
* @param regStartAddr
* @param regNum
* @param pData
* @retval ADS1220 Status
*/
static ADS1220_StatusTypedef ADS1220_ReadRegister(uint32_t regStartAddr, uint32_t regNum, uint8_t *pData)
{
ADS1220_CS_LOW();
HAL_Delay(5);
uint8_t temp = ((regStartAddr << 2) & 0x0c);
temp |= (regNum - 1) & 0x03;
temp |= ADS1220_CMD_READ_REG;
if (ADS1220_OK != ADS1220_SPI_Write(&temp, 1))
{
return ADS1220_FAIL;
}
if (ADS1220_OK != ADS1220_SPI_Receive(pData, regNum))
{
return ADS1220_FAIL;
}
ADS1220_CS_HIGH();
return ADS1220_OK;
}
/* Global Function ***********************************************************/
/**
* @brief Initialize ADS1220
* @param void
* @note
* @retval void
*/
void ADS1220_Init(void)
{
MX_SPI3_Init();
ADS1220_Reset();
}
/**
* @brief Select ADS1220 channel
* @param chl
* @note
* @retval ADS1220 Status
*/
ADS1220_StatusTypedef ADS1220_Channal_Sel(uint8_t chl)
{
static uint8_t recvTemp[4] = {0};
static uint8_t sendTemp[4] = {0};
switch (chl)
{
case ADS1220_CH0:
sendTemp[0] = MUX_P_AIN0_N_AVSS;
break;
case ADS1220_CH1:
sendTemp[0] = MUX_P_AIN1_N_AVSS;
break;
case ADS1220_CH2:
sendTemp[0] = MUX_P_AIN2_N_AVSS;
break;
case ADS1220_CH3:
sendTemp[0] = MUX_P_AIN3_N_AVSS;
break;
}
sendTemp[0] |= GAIN_1 | PGA_BYPASS;
sendTemp[1] = DR_45SPS | MODE_NORMAL | CM_SINGLE | TS_OFF | BCS_OFF;
sendTemp[2] = VREF_EXT_REF0_PINS | FIR_50_60 | PSW_OPEN | IDAC_OFF;
sendTemp[3] = I1MUX_DISABLED | I2MUX_DISABLED | DRDY_ON_DOUT_DRDY;
ADS1220_WriteRegister(0x00, 4, sendTemp);
HAL_Delay(5);
ADS1220_ReadRegister(0x00, 4, recvTemp);
for (uint8_t i = 0; i < 4; i++)
{
if (sendTemp[i] != recvTemp[i])
{
return ADS1220_FAIL;
}
}
return ADS1220_OK;
}
/**
* @brief Start ADS1220 ADC convert
* @param void
* @note
* @retval ADS1220 Status
*/
ADS1220_StatusTypedef ADS1220_Start(void)
{
ADS1220_CS_LOW();
if (ADS1220_OK != ADS1220_SPI_Write(&ADS1220_CMD_START, 1))
{
ADS1220_CS_HIGH();
return ADS1220_FAIL;
}
ADS1220_CS_HIGH();
return ADS1220_OK;
}
/**
* @brief Reset ADS1220
* @param void
* @note
* @retval ADS1220 Status
*/
ADS1220_StatusTypedef ADS1220_Reset(void)
{
ADS1220_CS_LOW();
if (ADS1220_OK != ADS1220_SPI_Write(&ADS1220_CMD_RESET, 1))
{
ADS1220_CS_HIGH();
return ADS1220_FAIL;
}
ADS1220_CS_HIGH();
return ADS1220_OK;
}
/**
* @brief Wait ADS1220 DRDY pin
* @param timeout
* @note
* @retval ADS1220 Status
*/
ADS1220_StatusTypedef ADS1220_Wait_DRDY(uint8_t timeout)
{
uint32_t beginTime = HAL_GetTick();
ADS1220_CS_LOW();
HAL_Delay(5);
while ((HAL_GetTick() - beginTime) < timeout)
{
if (ADS1220_DRDY_RDY == ADS1220_DRDY_GET())
{
ADS1220_CS_HIGH();
return ADS1220_OK;
}
}
ADS1220_CS_HIGH();
return ADS1220_FAIL;
}
/**
* @brief Read ADS1220 ADC convert result
* @param void
* @note
* @retval Convert result
*/
int32_t ADS1220_Read_Data(void)
{
uint8_t temp[3] = {0};
uint32_t returnVal = 0;
ADS1220_CS_LOW();
if (ADS1220_OK != ADS1220_SPI_Write(&ADS1220_CMD_RDATA, 1))
{
return 0;
}
if (ADS1220_OK != ADS1220_SPI_Receive(temp, 3))
{
return 0;
}
ADS1220_CS_HIGH();
returnVal = (temp[0] << 16) | (temp[1] << 8) | (temp[2]);
if (returnVal & 0x800000)
{
returnVal |= 0xff000000;
}
return returnVal;
}
/**
* @brief ADS1220 ADC convert once and read result
* @param chl
* @note
* @retval Convert result
*/
int32_t ADS1220_ReadConvertOnce(uint8_t chl)
{
ADS1220_Channal_Sel(chl);
ADS1220_Start();
ADS1220_Wait_DRDY(30);
return ADS1220_Read_Data();
}
ads1220.h
c
/**
******************************************************************************
* @file ads1220.h
* @author zjq
* @brief ads1220 bsp
******************************************************************************
*/
#ifndef __ADS_1220_H
#define __ADS_1220_H
#include "stdint.h"
#include "sys.h"
/* 函数返回值 */
typedef enum
{
ADS1220_OK = 0x00U,
ADS1220_FAIL = 0x01U,
} ADS1220_StatusTypedef;
/* 通道选择 */
#define ADS1220_CH0 (0)
#define ADS1220_CH1 (1)
#define ADS1220_CH2 (2)
#define ADS1220_CH3 (3)
/* Reg0 [7:4]MUX */
#define MUX_P_AIN0_N_AIN1 (0X00U)
#define MUX_P_AIN0_N_AIN2 (0X10U)
#define MUX_P_AIN0_N_AIN3 (0X20U)
#define MUX_P_AIN1_N_AIN2 (0X30U)
#define MUX_P_AIN1_N_AIN3 (0X40U)
#define MUX_P_AIN2_N_AIN3 (0X50U)
#define MUX_P_AIN1_N_AIN0 (0X60U)
#define MUX_P_AIN3_N_AIN2 (0X70U)
#define MUX_P_AIN0_N_AVSS (0X80U)
#define MUX_P_AIN1_N_AVSS (0X90U)
#define MUX_P_AIN2_N_AVSS (0XA0U)
#define MUX_P_AIN3_N_AVSS (0XB0U)
#define MUX_P_REFP_N_REFN (0XC0U)
#define MUX_P_AVDD_N_AVSS (0XD0U)
#define MUX_PN_SHORT_HALFVDD (0XE0U)
/* Reg0 [3:1]GAIN */
#define GAIN_1 (0X00U)
#define GAIN_2 (0X02U)
#define GAIN_4 (0X04U)
#define GAIN_8 (0X06U)
#define GAIN_16 (0X08U)
#define GAIN_32 (0X0AU)
#define GAIN_64 (0X0CU)
#define GAIN_128 (0X0EU)
/* Reg0 [0]PGA_BYPASS */
#define PGA_BYPASS (0X01U)
#define PGA_AMP (0X00U)
/* Reg1 [7:5]DR */
#define DR_20SPS (0X00U)
#define DR_45SPS (0X20U)
#define DR_90SPS (0X40U)
#define DR_175SPS (0X60U)
#define DR_330SPS (0X80U)
#define DR_600SPS (0XA0U)
#define DR_1000SPS (0XC0U)
/* Reg1 [4:3]MODE */
#define MODE_NORMAL (0X00U)
#define MODE_DUTY (0X08U)
#define MODE_TURBO (0X10U)
/* Reg1 [2]CM */
#define CM_SINGLE (0X00U)
#define CM_CONTINUE (0X04U)
/* Reg1 [1]TS */
#define TS_ON (0X02U)
#define TS_OFF (0X00U)
/* Reg1 [0]BCS */
#define BCS_ON (0X01U)
#define BCS_OFF (0X00U)
/* Reg2 [7:6]VREF */
#define VREF_INTERNAL (0X00U)
#define VREF_EXT_REF0_PINS (0X40U)
#define VREF_EXT_REF1_PINS (0X80U)
#define VREF_AVDD (0XC0U)
/* Reg2 [5:4]50/60 */
#define FIR_NONE (0X00U)
#define FIR_50_60 (0X10U)
#define FIR_50 (0X20U)
#define FIR_60 (0X30U)
/* Reg2 [3]PSW */
#define PSW_OPEN (0X00U)
#define PSW_CLOSES (0X08U)
/* Reg2 [2:0]IDAC */
#define IDAC_OFF (0X00U)
#define IDAC_10uA (0X01U)
#define IDAC_50uA (0X02U)
#define IDAC_100uA (0X03U)
#define IDAC_250uA (0X04U)
#define IDAC_500uA (0X05U)
#define IDAC_1000uA (0X06U)
#define IDAC_1500uA (0X07U)
/* Reg3 [7:5]I1MUX */
#define I1MUX_DISABLED (0X00U)
#define I1MUX_AIN0 (0X20U)
#define I1MUX_AIN1 (0X40U)
#define I1MUX_AIN2 (0X60U)
#define I1MUX_AIN3 (0X80U)
#define I1MUX_REFP0 (0XA0U)
#define I1MUX_REFN0 (0XC0U)
/* Reg3 [4:2]I2MUX */
#define I2MUX_DISABLED (0X00U)
#define I2MUX_AIN0 (0X04U)
#define I2MUX_AIN1 (0X08U)
#define I2MUX_AIN2 (0X0CU)
#define I2MUX_AIN3 (0X10U)
#define I2MUX_REFP0 (0X14U)
#define I2MUX_REFN0 (0X18U)
/* Reg3 [1]DRDYM */
#define DRDY_ON_DOUT_DRDY (0X02U)
#define DRDY_ON_DRDY_ONLY (0X00U)
/* Global Function ***********************************************************/
/**
* @brief Initialize ADS1220
* @param void
* @note
* @retval void
*/
void ADS1220_Init(void);
/**
* @brief Select ADS1220 channel
* @param chl
* @note
* @retval ADS1220 Status
*/
ADS1220_StatusTypedef ADS1220_Channal_Sel(uint8_t chl);
/**
* @brief Start ADS1220 ADC convert
* @param void
* @note
* @retval ADS1220 Status
*/
ADS1220_StatusTypedef ADS1220_Start(void);
/**
* @brief Reset ADS1220
* @param void
* @note
* @retval ADS1220 Status
*/
ADS1220_StatusTypedef ADS1220_Reset(void);
/**
* @brief Wait ADS1220 DRDY pin
* @param timeout
* @note
* @retval ADS1220 Status
*/
ADS1220_StatusTypedef ADS1220_Wait_DRDY(uint8_t timeout);
/**
* @brief Read ADS1220 ADC convert result
* @param void
* @note
* @retval Convert result
*/
int32_t ADS1220_Read_Data(void);
/**
* @brief ADS1220 ADC convert once and read result
* @param chl
* @note
* @retval Convert result
*/
int32_t ADS1220_ReadConvertOnce(uint8_t chl);
#endif