基于STM32、HAL库的ADS1256IDBR模数转换器ADC驱动程序设计
一、简介:
ADS1256IDBR是德州仪器(TI)生产的一款高精度、24位Δ-Σ模数转换器(ADC),主要特性包括:
-
24位无丢失码分辨率
-
最高30kSPS的数据速率
-
低噪声:2.5μV RMS(在30SPS时)
-
8个单端或4个差分输入通道
-
内置可编程增益放大器(PGA):1至64V/V
-
内置低漂移电压基准(2.5V)
-
SPI兼容接口
-
工作电压:3.3V或5V
二、硬件接口:
ADS1256引脚 | STM32L4引脚 | 功能描述 |
---|---|---|
DVDD | 3.3V | 数字电源 |
AVDD | 3.3V | 模拟电源 |
DGND | GND | 数字地 |
AGND | GND | 模拟地 |
CS | PA4 | 片选(低电平有效) |
DIN | PA7 | SPI数据输入(MOSI) |
DOUT | PA6 | SPI数据输出(MISO) |
SCLK | PA5 | SPI时钟 |
DRDY | PA3 | 数据就绪(低电平有效) |
RESET | PA2 | 复位(低电平有效) |
注意:模拟和数字地应在一点连接,电源引脚应加去耦电容(0.1μF)
三、头文件:
#ifndef ADS1256_H
#define ADS1256_H
#include "stm32l4xx_hal.h"
// ADS1256寄存器地址
#define ADS1256_REG_STATUS 0x00
#define ADS1256_REG_MUX 0x01
#define ADS1256_REG_ADCON 0x02
#define ADS1256_REG_DRATE 0x03
#define ADS1256_REG_IO 0x04
#define ADS1256_REG_OFC0 0x05
#define ADS1256_REG_OFC1 0x06
#define ADS1256_REG_OFC2 0x07
#define ADS1256_REG_FSC0 0x08
#define ADS1256_REG_FSC1 0x09
#define ADS1256_REG_FSC2 0x0A
// ADS1256命令
#define ADS1256_CMD_WAKEUP 0x00
#define ADS1256_CMD_RDATA 0x01
#define ADS1256_CMD_RDATAC 0x03
#define ADS1256_CMD_SDATAC 0x0F
#define ADS1256_CMD_RREG 0x10
#define ADS1256_CMD_WREG 0x50
#define ADS1256_CMD_SELFCAL 0xF0
#define ADS1256_CMD_SELFOCAL 0xF1
#define ADS1256_CMD_SELFGCAL 0xF2
#define ADS1256_CMD_SYSOCAL 0xF3
#define ADS1256_CMD_SYSGCAL 0xF4
#define ADS1256_CMD_SYNC 0xFC
#define ADS1256_CMD_STANDBY 0xFD
#define ADS1256_CMD_RESET 0xFE
// PGA增益设置
typedef enum {
ADS1256_GAIN_1 = 0,
ADS1256_GAIN_2,
ADS1256_GAIN_4,
ADS1256_GAIN_8,
ADS1256_GAIN_16,
ADS1256_GAIN_32,
ADS1256_GAIN_64
} ADS1256_Gain;
// 数据速率设置
typedef enum {
ADS1256_DRATE_30000 = 0xF0,
ADS1256_DRATE_15000 = 0xE0,
ADS1256_DRATE_7500 = 0xD0,
ADS1256_DRATE_3750 = 0xC0,
ADS1256_DRATE_2000 = 0xB0,
ADS1256_DRATE_1000 = 0xA1,
ADS1256_DRATE_500 = 0x92,
ADS1256_DRATE_100 = 0x82,
ADS1256_DRATE_60 = 0x72,
ADS1256_DRATE_50 = 0x63,
ADS1256_DRATE_30 = 0x53,
ADS1256_DRATE_25 = 0x43,
ADS1256_DRATE_15 = 0x33,
ADS1256_DRATE_10 = 0x23,
ADS1256_DRATE_5 = 0x13,
ADS1256_DRATE_2_5 = 0x03
} ADS1256_DataRate;
// 输入通道选择
typedef enum {
ADS1256_AIN0 = 0,
ADS1256_AIN1,
ADS1256_AIN2,
ADS1256_AIN3,
ADS1256_AIN4,
ADS1256_AIN5,
ADS1256_AIN6,
ADS1256_AIN7,
ADS1256_AINCOM
} ADS1256_Input;
typedef struct {
SPI_HandleTypeDef *hspi;
GPIO_TypeDef *cs_port;
uint16_t cs_pin;
GPIO_TypeDef *drdy_port;
uint16_t drdy_pin;
GPIO_TypeDef *reset_port;
uint16_t reset_pin;
ADS1256_Gain gain;
ADS1256_DataRate data_rate;
} ADS1256_HandleTypeDef;
// 函数声明
void ADS1256_Init(ADS1256_HandleTypeDef *hadc);
void ADS1256_Reset(ADS1256_HandleTypeDef *hadc);
void ADS1256_WriteReg(ADS1256_HandleTypeDef *hadc, uint8_t reg, uint8_t data);
uint8_t ADS1256_ReadReg(ADS1256_HandleTypeDef *hadc, uint8_t reg);
void ADS1256_SendCommand(ADS1256_HandleTypeDef *hadc, uint8_t cmd);
void ADS1256_WaitDRDY(ADS1256_HandleTypeDef *hadc);
void ADS1256_SetChannel(ADS1256_HandleTypeDef *hadc, ADS1256_Input positive, ADS1256_Input negative);
int32_t ADS1256_ReadData(ADS1256_HandleTypeDef *hadc);
float ADS1256_ReadVoltage(ADS1256_HandleTypeDef *hadc);
#endif // ADS1256_H
四、源文件:
#include "ads1256.h"
#include "stm32l4xx_hal.h"
#include <string.h>
// 私有函数声明
static void ADS1256_CS_Low(ADS1256_HandleTypeDef *hadc);
static void ADS1256_CS_High(ADS1256_HandleTypeDef *hadc);
static void ADS1256_Delay(uint32_t delay);
void ADS1256_Init(ADS1256_HandleTypeDef *hadc) {
// 硬件复位
ADS1256_Reset(hadc);
// 等待DRDY变低
ADS1256_WaitDRDY(hadc);
// 发送同步命令
ADS1256_SendCommand(hadc, ADS1256_CMD_SYNC);
ADS1256_Delay(10);
ADS1256_SendCommand(hadc, ADS1256_CMD_WAKEUP);
ADS1256_Delay(10);
// 配置寄存器
uint8_t buf[4];
// 配置MUX寄存器 (AIN0和AINCOM差分输入)
buf[0] = (ADS1256_AIN0 << 4) | ADS1256_AINCOM;
ADS1256_WriteReg(hadc, ADS1256_REG_MUX, buf[0]);
// 配置ADCON寄存器 (PGA使能,增益设置)
buf[1] = (0 << 3) | hadc->gain; // CLKOUT关闭,增益设置
ADS1256_WriteReg(hadc, ADS1256_REG_ADCON, buf[1]);
// 配置数据速率
ADS1256_WriteReg(hadc, ADS1256_REG_DRATE, hadc->data_rate);
// 自校准
ADS1256_SendCommand(hadc, ADS1256_CMD_SELFCAL);
ADS1256_Delay(100); // 等待校准完成
}
void ADS1256_Reset(ADS1256_HandleTypeDef *hadc) {
// 拉低复位引脚
HAL_GPIO_WritePin(hadc->reset_port, hadc->reset_pin, GPIO_PIN_RESET);
ADS1256_Delay(100);
// 释放复位引脚
HAL_GPIO_WritePin(hadc->reset_port, hadc->reset_pin, GPIO_PIN_SET);
ADS1256_Delay(1000); // 等待复位完成
}
void ADS1256_WriteReg(ADS1256_HandleTypeDef *hadc, uint8_t reg, uint8_t data) {
ADS1256_WaitDRDY(hadc);
ADS1256_CS_Low(hadc);
uint8_t txBuf[2];
txBuf[0] = ADS1256_CMD_WREG | reg;
txBuf[1] = 0x00; // 写入1个寄存器
txBuf[2] = data;
HAL_SPI_Transmit(hadc->hspi, txBuf, 3, HAL_MAX_DELAY);
ADS1256_CS_High(hadc);
}
uint8_t ADS1256_ReadReg(ADS1256_HandleTypeDef *hadc, uint8_t reg) {
ADS1256_WaitDRDY(hadc);
ADS1256_CS_Low(hadc);
uint8_t txBuf[3] = {0};
uint8_t rxBuf[3] = {0};
txBuf[0] = ADS1256_CMD_RREG | reg;
txBuf[1] = 0x00; // 读取1个寄存器
HAL_SPI_TransmitReceive(hadc->hspi, txBuf, rxBuf, 3, HAL_MAX_DELAY);
ADS1256_CS_High(hadc);
return rxBuf[2];
}
void ADS1256_SendCommand(ADS1256_HandleTypeDef *hadc, uint8_t cmd) {
ADS1256_WaitDRDY(hadc);
ADS1256_CS_Low(hadc);
HAL_SPI_Transmit(hadc->hspi, &cmd, 1, HAL_MAX_DELAY);
ADS1256_CS_High(hadc);
}
void ADS1256_WaitDRDY(ADS1256_HandleTypeDef *hadc) {
while (HAL_GPIO_ReadPin(hadc->drdy_port, hadc->drdy_pin) == GPIO_PIN_SET) {
// 等待DRDY变低
}
}
void ADS1256_SetChannel(ADS1256_HandleTypeDef *hadc, ADS1256_Input positive, ADS1256_Input negative) {
uint8_t mux = (positive << 4) | negative;
ADS1256_WriteReg(hadc, ADS1256_REG_MUX, mux);
// 发送同步和唤醒命令以应用新设置
ADS1256_SendCommand(hadc, ADS1256_CMD_SYNC);
ADS1256_Delay(10);
ADS1256_SendCommand(hadc, ADS1256_CMD_WAKEUP);
ADS1256_Delay(10);
}
int32_t ADS1256_ReadData(ADS1256_HandleTypeDef *hadc) {
ADS1256_WaitDRDY(hadc);
ADS1256_CS_Low(hadc);
uint8_t txBuf[4] = {ADS1256_CMD_RDATA, 0x00, 0x00, 0x00};
uint8_t rxBuf[4] = {0};
HAL_SPI_TransmitReceive(hadc->hspi, txBuf, rxBuf, 4, HAL_MAX_DELAY);
ADS1256_CS_High(hadc);
// 组合24位数据
int32_t value = (rxBuf[1] << 16) | (rxBuf[2] << 8) | rxBuf[3];
// 处理符号位扩展
if (value & 0x00800000) {
value |= 0xFF000000;
}
return value;
}
float ADS1256_ReadVoltage(ADS1256_HandleTypeDef *hadc) {
int32_t raw = ADS1256_ReadData(hadc);
// 计算电压 (假设使用内部2.5V基准)
float voltage = (raw * 2.5f) / (8388607.0f * (1 << hadc->gain));
return voltage;
}
static void ADS1256_CS_Low(ADS1256_HandleTypeDef *hadc) {
HAL_GPIO_WritePin(hadc->cs_port, hadc->cs_pin, GPIO_PIN_RESET);
}
static void ADS1256_CS_High(ADS1256_HandleTypeDef *hadc) {
HAL_GPIO_WritePin(hadc->cs_port, hadc->cs_pin, GPIO_PIN_SET);
}
static void ADS1256_Delay(uint32_t delay) {
HAL_Delay(delay);
}
五、应用:
#include "stm32l4xx_hal.h"
#include "ads1256.h"
SPI_HandleTypeDef hspi1;
ADS1256_HandleTypeDef hadc1;
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_SPI1_Init(void);
int main(void) {
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_SPI1_Init();
// 初始化ADS1256
hadc1.hspi = &hspi1;
hadc1.cs_port = GPIOA;
hadc1.cs_pin = GPIO_PIN_4;
hadc1.drdy_port = GPIOA;
hadc1.drdy_pin = GPIO_PIN_3;
hadc1.reset_port = GPIOA;
hadc1.reset_pin = GPIO_PIN_2;
hadc1.gain = ADS1256_GAIN_1;
hadc1.data_rate = ADS1256_DRATE_100;
ADS1256_Init(&hadc1);
while (1) {
// 读取AIN0电压
float voltage = ADS1256_ReadVoltage(&hadc1);
// 可以在此处添加电压处理逻辑
// 例如发送到串口或进行其他处理
HAL_Delay(100); // 每100ms读取一次
}
}
void SystemClock_Config(void) {
// 系统时钟配置代码 (根据具体硬件配置)
}
static void MX_SPI1_Init(void) {
hspi1.Instance = SPI1;
hspi1.Init.Mode = SPI_MODE_MASTER;
hspi1.Init.Direction = SPI_DIRECTION_2LINES;
hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi1.Init.NSS = SPI_NSS_SOFT;
hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_32;
hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi1.Init.CRCPolynomial = 7;
if (HAL_SPI_Init(&hspi1) != HAL_OK) {
Error_Handler();
}
}
static void MX_GPIO_Init(void) {
GPIO_InitTypeDef GPIO_InitStruct = {0};
// 启用时钟
__HAL_RCC_GPIOA_CLK_ENABLE();
// DRDY引脚配置 (输入)
GPIO_InitStruct.Pin = GPIO_PIN_3;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
// CS引脚配置 (输出)
GPIO_InitStruct.Pin = GPIO_PIN_4;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET); // 初始高电平
// RESET引脚配置 (输出)
GPIO_InitStruct.Pin = GPIO_PIN_2;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_SET); // 初始高电平
// SPI引脚配置
GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}
void Error_Handler(void) {
while(1) {
// 错误处理
}
}