一、系统架构设计
复制代码
┌─────────────────────────────────────────────────────────────┐
│ ADS1256 数据采集系统 │
├─────────────────────────────────────────────────────────────┤
│ STM32主控 │ ADS1256 ADC │ 信号调理 │ 应用层 │
│ │ │ │ │
│ • SPI通信 │ • 24位分辨率 │ • 电压跟随器 │ • 数据显示 │
│ • 时钟配置 │ • 8通道差分输入 │ • RC滤波 │ • 数据存储 │
│ • DMA传输 │ • 可编程增益 │ • 过压保护 │ • 通信上传 │
│ • 中断处理 │ • 30kSPS速率 │ • 屏蔽设计 │ • 报警控制 │
└─────────────────────────────────────────────────────────────┘
二、硬件连接设计
2.1 引脚连接表
复制代码
STM32F103C8T6 ADS1256
─────────────────────────────────────
PA5 (SPI1_SCK) ──────> SCLK
PA6 (SPI1_MISO) ──────> DOUT
PA7 (SPI1_MOSI) ──────> DIN
PA4 (SPI1_NSS) ──────> CS
PB0 ──────> DRDY (数据就绪中断)
3.3V ──────> DVDD (数字电源)
5V ──────> AVDD (模拟电源)
GND ──────> DGND/AGND
2.2 模拟输入电路
复制代码
差分输入配置(以通道0为例):
R1 (100Ω) C1 (100nF)
Vin+ ────╱╱╱───────┬───────┐
│ │
╱╱╱ ╱╱╱
R2 R3 (匹配电阻)
│ │
Vin- ────╱╱╱───────┼───────┘
R3 (100Ω) C2 (100nF)
│
AGND
三、完整源码实现
3.1 ADS1256 驱动头文件 (ads1256.h)
c
复制代码
#ifndef __ADS1256_H
#define __ADS1256_H
#include "stm32f10x.h"
#include <stdint.h>
#include <stdbool.h>
// ADS1256 寄存器地址
#define ADS1256_STATUS 0x00
#define ADS1256_MUX 0x01
#define ADS1256_ADCON 0x02
#define ADS1256_DRATE 0x03
#define ADS1256_IO 0x04
#define ADS1256_OFC0 0x05
#define ADS1256_OFC1 0x06
#define ADS1256_OFC2 0x07
#define ADS1256_FSC0 0x08
#define ADS1256_FSC1 0x09
#define ADS1256_FSC2 0x0A
// 命令定义
#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
// 输入通道定义
typedef enum {
ADS1256_CH0 = 0x00,
ADS1256_CH1 = 0x10,
ADS1256_CH2 = 0x20,
ADS1256_CH3 = 0x30,
ADS1256_CH4 = 0x40,
ADS1256_CH5 = 0x50,
ADS1256_CH6 = 0x60,
ADS1256_CH7 = 0x70,
ADS1256_CH0_CH1 = 0x01, // AIN0 vs AIN1
ADS1256_CH2_CH3 = 0x23, // AIN2 vs AIN3
ADS1256_CH4_CH5 = 0x45, // AIN4 vs AIN5
ADS1256_CH6_CH7 = 0x67 // AIN6 vs AIN7
} ADS1256_Channel_t;
// 增益定义
typedef enum {
ADS1256_GAIN_1 = 0x00,
ADS1256_GAIN_2 = 0x01,
ADS1256_GAIN_4 = 0x02,
ADS1256_GAIN_8 = 0x03,
ADS1256_GAIN_16 = 0x04,
ADS1256_GAIN_32 = 0x05,
ADS1256_GAIN_64 = 0x06
} ADS1256_Gain_t;
// 数据速率定义
typedef enum {
ADS1256_DR_30000 = 0xF0, // 30k SPS
ADS1256_DR_15000 = 0xE0, // 15k SPS
ADS1256_DR_7500 = 0xD0, // 7.5k SPS
ADS1256_DR_3750 = 0xC0, // 3.75k SPS
ADS1256_DR_2000 = 0xB0, // 2k SPS
ADS1256_DR_1000 = 0xA1, // 1k SPS
ADS1256_DR_500 = 0x92, // 500 SPS
ADS1256_DR_100 = 0x82, // 100 SPS
ADS1256_DR_60 = 0x72, // 60 SPS
ADS1256_DR_50 = 0x63, // 50 SPS
ADS1256_DR_30 = 0x53, // 30 SPS
ADS1256_DR_25 = 0x43, // 25 SPS
ADS1256_DR_15 = 0x33, // 15 SPS
ADS1256_DR_10 = 0x23, // 10 SPS
ADS1256_DR_5 = 0x13, // 5 SPS
ADS1256_DR_2_5 = 0x03 // 2.5 SPS
} ADS1256_DataRate_t;
// 采集数据结构体
typedef struct {
int32_t raw_data; // 原始24位数据
float voltage; // 转换后的电压值
uint8_t channel; // 通道号
uint32_t timestamp; // 时间戳
bool valid; // 数据有效性
} ADS1256_Data_t;
// 系统配置结构体
typedef struct {
ADS1256_Gain_t gain; // 增益设置
ADS1256_DataRate_t rate; // 采样率设置
bool buffer_enable; // 输入缓冲使能
bool auto_calibration; // 自动校准使能
float vref; // 参考电压
} ADS1256_Config_t;
// 函数声明
bool ADS1256_Init(void);
void ADS1256_Reset(void);
void ADS1256_Config(ADS1256_Config_t *config);
void ADS1256_SetChannel(ADS1256_Channel_t channel);
void ADS1256_SetGain(ADS1256_Gain_t gain);
void ADS1256_SetDataRate(ADS1256_DataRate_t rate);
bool ADS1256_ReadData(ADS1256_Data_t *data);
bool ADS1256_ReadChannel(uint8_t channel, float *voltage);
void ADS1256_SelfCalibration(void);
void ADS1256_SystemCalibration(void);
float ADS1256_GetVoltage(int32_t raw_data);
void ADS1256_WaitDRDY(void);
void ADS1256_StartConversion(void);
void ADS1256_StopConversion(void);
#endif /* __ADS1256_H */
3.2 SPI 底层驱动 (spi.c)
c
复制代码
#include "spi.h"
#include "stm32f10x_spi.h"
// SPI初始化
void SPI_InitConfig(void) {
GPIO_InitTypeDef GPIO_InitStructure;
SPI_InitTypeDef SPI_InitStructure;
// 使能时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_SPI1, ENABLE);
// 配置SPI引脚
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_7; // SCK, MOSI
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; // MISO
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; // CS
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// 配置SPI参数
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; // CPOL=0
SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; // CPHA=1
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_32; // 2.25MHz
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_InitStructure.SPI_CRCPolynomial = 7;
SPI_Init(SPI1, &SPI_InitStructure);
// 使能SPI
SPI_Cmd(SPI1, ENABLE);
}
// SPI发送接收字节
uint8_t SPI_ReadWriteByte(uint8_t data) {
// 等待发送缓冲区空
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
// 发送数据
SPI_I2S_SendData(SPI1, data);
// 等待接收完成
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);
// 返回接收的数据
return SPI_I2S_ReceiveData(SPI1);
}
// 片选控制
void SPI_CS_Select(void) {
GPIO_ResetBits(GPIOA, GPIO_Pin_4);
}
void SPI_CS_Deselect(void) {
GPIO_SetBits(GPIOA, GPIO_Pin_4);
}
3.3 ADS1256 核心驱动 (ads1256.c)
c
复制代码
#include "ads1256.h"
#include "spi.h"
#include "delay.h"
// 全局变量
static ADS1256_Config_t ads_config = {
.gain = ADS1256_GAIN_1,
.rate = ADS1256_DR_1000,
.buffer_enable = true,
.auto_calibration = true,
.vref = 5.0f
};
// 写寄存器
static void ADS1256_WriteReg(uint8_t reg, uint8_t value) {
SPI_CS_Select();
SPI_ReadWriteByte(ADS1256_CMD_WREG | reg);
SPI_ReadWriteByte(0x00); // 写1个寄存器
SPI_ReadWriteByte(value);
SPI_CS_Deselect();
Delay_us(10);
}
// 读寄存器
static uint8_t ADS1256_ReadReg(uint8_t reg) {
uint8_t value;
SPI_CS_Select();
SPI_ReadWriteByte(ADS1256_CMD_RREG | reg);
SPI_ReadWriteByte(0x00); // 读1个寄存器
Delay_us(10);
value = SPI_ReadWriteByte(0xFF);
SPI_CS_Deselect();
return value;
}
// 发送命令
static void ADS1256_SendCmd(uint8_t cmd) {
SPI_CS_Select();
SPI_ReadWriteByte(cmd);
SPI_CS_Deselect();
Delay_us(10);
}
// 等待DRDY信号
void ADS1256_WaitDRDY(void) {
while (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_0) == 1) {
// 等待DRDY变低
}
}
// 初始化ADS1256
bool ADS1256_Init(void) {
uint8_t id;
// 复位ADS1256
ADS1256_Reset();
Delay_ms(100);
// 读取ID寄存器
id = ADS1256_ReadReg(ADS1256_STATUS);
if ((id & 0x70) != 0x30) { // 检查ID位
return false;
}
// 配置默认参数
ADS1256_Config(&ads_config);
// 执行自校准
if (ads_config.auto_calibration) {
ADS1256_SelfCalibration();
}
return true;
}
// 复位ADS1256
void ADS1256_Reset(void) {
ADS1256_SendCmd(ADS1256_CMD_RESET);
Delay_ms(10);
}
// 配置ADS1256
void ADS1256_Config(ADS1256_Config_t *config) {
uint8_t status_reg;
if (config == NULL) return;
// 配置状态寄存器
status_reg = 0x00;
if (config->buffer_enable) {
status_reg |= 0x02; // 使能输入缓冲
}
ADS1256_WriteReg(ADS1256_STATUS, status_reg);
// 配置MUX寄存器(默认通道0)
ADS1256_WriteReg(ADS1256_MUX, ADS1256_CH0);
// 配置ADCON寄存器(增益设置)
ADS1256_WriteReg(ADS1256_ADCON, config->gain);
// 配置数据速率
ADS1256_WriteReg(ADS1256_DRATE, config->rate);
// 保存配置
ads_config = *config;
}
// 设置通道
void ADS1256_SetChannel(ADS1256_Channel_t channel) {
ADS1256_WriteReg(ADS1256_MUX, channel);
Delay_us(50); // 通道切换后需要稳定时间
}
// 设置增益
void ADS1256_SetGain(ADS1256_Gain_t gain) {
uint8_t adcon = ADS1256_ReadReg(ADS1256_ADCON);
adcon = (adcon & 0xF8) | gain; // 清除低3位,设置增益
ADS1256_WriteReg(ADS1256_ADCON, adcon);
}
// 设置数据速率
void ADS1256_SetDataRate(ADS1256_DataRate_t rate) {
ADS1256_WriteReg(ADS1256_DRATE, rate);
}
// 读取转换数据
bool ADS1256_ReadData(ADS1256_Data_t *data) {
uint8_t buffer[3];
int32_t raw_value;
if (data == NULL) return false;
// 等待数据就绪
ADS1256_WaitDRDY();
// 发送读取数据命令
SPI_CS_Select();
SPI_ReadWriteByte(ADS1256_CMD_RDATA);
Delay_us(10); // t6等待时间
// 读取24位数据
buffer[0] = SPI_ReadWriteByte(0xFF);
buffer[1] = SPI_ReadWriteByte(0xFF);
buffer[2] = SPI_ReadWriteByte(0xFF);
SPI_CS_Deselect();
// 转换为32位有符号整数
raw_value = ((int32_t)buffer[0] << 16) |
((int32_t)buffer[1] << 8) |
(int32_t)buffer[2];
// 符号扩展(24位补码转32位)
if (raw_value & 0x800000) {
raw_value |= 0xFF000000;
}
data->raw_data = raw_value;
data->voltage = ADS1256_GetVoltage(raw_value);
data->timestamp = Get_SystemTick();
data->valid = true;
return true;
}
// 读取指定通道电压
bool ADS1256_ReadChannel(uint8_t channel, float *voltage) {
ADS1256_Channel_t ch;
ADS1256_Data_t data;
if (channel > 7 || voltage == NULL) return false;
// 设置通道
ch = (ADS1256_Channel_t)(channel << 4);
ADS1256_SetChannel(ch);
// 启动转换
ADS1256_SendCmd(ADS1256_CMD_SYNC);
ADS1256_SendCmd(ADS1256_CMD_WAKEUP);
// 读取数据
if (ADS1256_ReadData(&data)) {
*voltage = data.voltage;
return true;
}
return false;
}
// 将原始数据转换为电压值
float ADS1256_GetVoltage(int32_t raw_data) {
float voltage;
float gain_factor;
// 根据增益计算系数
switch (ads_config.gain) {
case ADS1256_GAIN_1: gain_factor = 1.0f; break;
case ADS1256_GAIN_2: gain_factor = 2.0f; break;
case ADS1256_GAIN_4: gain_factor = 4.0f; break;
case ADS1256_GAIN_8: gain_factor = 8.0f; break;
case ADS1256_GAIN_16: gain_factor = 16.0f; break;
case ADS1256_GAIN_32: gain_factor = 32.0f; break;
case ADS1256_GAIN_64: gain_factor = 64.0f; break;
default: gain_factor = 1.0f; break;
}
// 计算电压:V = (RawData / 2^23) * VREF / Gain
voltage = ((float)raw_data / 8388608.0f) * ads_config.vref / gain_factor;
return voltage;
}
// 自校准
void ADS1256_SelfCalibration(void) {
printf("Starting Self-Calibration...\n");
ADS1256_SendCmd(ADS1256_CMD_SELFCAL);
ADS1256_WaitDRDY();
printf("Self-Calibration Complete.\n");
}
// 系统偏移校准
void ADS1256_SystemCalibration(void) {
printf("Starting System Offset Calibration...\n");
ADS1256_SendCmd(ADS1256_CMD_SYSOCAL);
ADS1256_WaitDRDY();
printf("System Calibration Complete.\n");
}
3.4 主程序 (main.c)
c
复制代码
#include "stm32f10x.h"
#include "ads1256.h"
#include "spi.h"
#include "usart.h"
#include "delay.h"
#include "led.h"
// 全局变量
ADS1256_Data_t adc_data[8];
uint8_t current_channel = 0;
uint32_t sample_count = 0;
// 系统初始化
void System_Init(void) {
SystemClock_Init();
Delay_Init();
USART_Init(115200);
LED_Init();
SPI_InitConfig();
printf("ADS1256 High Precision Data Acquisition System\r\n");
printf("================================================\r\n");
// 初始化ADS1256
if (ADS1256_Init()) {
printf("ADS1256 Initialized Successfully!\r\n");
LED_On(LED_GREEN);
} else {
printf("ADS1256 Initialization Failed!\r\n");
LED_On(LED_RED);
while(1);
}
// 配置采集参数
ADS1256_Config_t config = {
.gain = ADS1256_GAIN_1,
.rate = ADS1256_DR_1000, // 1kSPS
.buffer_enable = true,
.auto_calibration = true,
.vref = 5.0f
};
ADS1256_Config(&config);
printf("Configuration Complete.\r\n");
printf("Gain: 1x, Sample Rate: 1kSPS\r\n");
}
// 多通道扫描
void Scan_AllChannels(void) {
for (uint8_t ch = 0; ch < 8; ch++) {
if (ADS1256_ReadChannel(ch, &adc_data[ch].voltage)) {
adc_data[ch].raw_data = (int32_t)(adc_data[ch].voltage * 8388608.0f / 5.0f);
adc_data[ch].channel = ch;
adc_data[ch].valid = true;
}
Delay_ms(1); // 通道切换延时
}
}
// 显示采集结果
void Display_Results(void) {
static uint32_t last_display = 0;
if (Get_SystemTick() - last_display >= 1000) { // 每秒显示一次
printf("Sample Count: %lu\r\n", sample_count);
printf("Channel Voltages (V):\r\n");
for (uint8_t i = 0; i < 8; i++) {
printf("CH%d: %+8.6f ", i, adc_data[i].voltage);
if ((i + 1) % 4 == 0) printf("\r\n");
}
printf("==========================================\r\n");
last_display = Get_SystemTick();
}
}
int main(void) {
// 系统初始化
System_Init();
printf("Starting Data Acquisition...\r\n");
while(1) {
// 扫描所有通道
Scan_AllChannels();
sample_count++;
// 显示结果
Display_Results();
// LED指示采样状态
if (sample_count % 100 == 0) {
LED_Toggle(LED_BLUE);
}
Delay_ms(10); // 控制采样间隔
}
}
参考代码 利用STM32和ADS1256进行数据采集 www.youwenfan.com/contentcsu/60828.html
四、工程配置与优化
4.1 编译配置
复制代码
Keil MDK-ARM 工程配置:
• Target: STM32F103C8
• Code Generation: ARM Compiler 6
• Optimization: Level 2 (-O2)
• Include Paths:
- ./Inc
- ./Drivers/STM32F10x_StdPeriph_Driver/inc
- ./ADS1256
4.2 性能优化建议
| 优化项目 |
建议方案 |
| 采样精度 |
使用外部基准电压源,避免电源噪声 |
| 抗干扰 |
模拟地与数字地单点连接,使用磁珠隔离 |
| 采样速度 |
根据需求选择合适的采样率,避免过高 |
| 温度漂移 |
定期执行系统校准,考虑温度补偿 |
| 数据稳定 |
增加软件滤波(中值滤波、均值滤波) |
4.3 常见问题解决
| 问题 |
原因 |
解决方案 |
| 数据跳动大 |
电源噪声干扰 |
增加电源滤波,使用线性稳压器 |
| 通道间串扰 |
输入阻抗不匹配 |
添加电压跟随器,降低输出阻抗 |
| 采样值偏低 |
增益设置错误 |
检查增益配置,重新校准 |
| 通信失败 |
SPI时序问题 |
降低SPI时钟频率,检查CPOL/CPHA |
| 温度漂移 |
基准电压温漂 |
使用低温漂基准源,如REF5025 |