news 2026/5/5 19:36:17

用STM32F103的GPIO口模拟SPI,搞定ADS1220高精度ADC数据采集(附完整代码)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
用STM32F103的GPIO口模拟SPI,搞定ADS1220高精度ADC数据采集(附完整代码)

STM32F103 GPIO模拟SPI驱动ADS1220的实战指南

在嵌入式开发中,当硬件SPI接口被占用或需要更灵活的时序控制时,用GPIO模拟SPI通信成为工程师的必备技能。本文将带您深入探索如何用STM32F103的普通GPIO口精准模拟SPI时序,驱动高精度ADS1220 ADC芯片,实现24位精度的数据采集。

1. 理解ADS1220与SPI通信基础

ADS1220是TI推出的24位Δ-Σ型ADC,具有极低的噪声和高达128倍的可编程增益。其SPI接口标准模式下时钟频率可达4MHz,这对GPIO模拟提出了严苛的时序要求。

关键性能参数对比

参数ADS1220规格普通16位ADC典型值
分辨率24位16位
采样率20SPS-2000SPS10kSPS-100kSPS
输入噪声70nV RMS (PGA=128)1μV RMS
功耗120μA (占空比模式)1mA

提示:虽然软件模拟SPI速度不及硬件SPI,但对于ADS1220这类低速高精度ADC完全够用,20SPS时SCLK仅需约10kHz。

2. 硬件连接与GPIO配置

使用STM32F103C8T6的GPIO连接ADS1220时,推荐以下引脚分配方案:

// PB0 -> DRDY (输入) // PB1 -> CS (输出) // PA5 -> MOSI (输出) // PA6 -> SCK (输出) // PA7 -> MISO (输入)

对应的GPIO初始化代码应确保时序关键引脚设置为50MHz输出:

void ADS1220_GPIOInit(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB, ENABLE); // MOSI(PA5)和SCK(PA6)配置为推挽输出 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); // MISO(PA7)配置为上拉输入 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_Init(GPIOA, &GPIO_InitStructure); // DRDY(PB0)输入,CS(PB1)输出 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_Init(GPIOB, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(GPIOB, &GPIO_InitStructure); GPIO_SetBits(GPIOB, GPIO_Pin_1); // 初始CS高电平 }

3. 精准时序实现技巧

SPI模式0(CPOL=0, CPHA=0)是ADS1220的默认通信模式,其时序要点包括:

  • 时钟空闲状态为低电平
  • 数据在时钟上升沿采样
  • 每个字节传输时MSB在前

关键延时控制

#define DELAY_US(n) do { \ uint32_t t = n * 8; \ while(t--) __NOP(); \ } while(0) void WriteByte(uint8_t data) { for(uint8_t i=0; i<8; i++) { (data & 0x80) ? GPIO_SetBits(GPIOA, GPIO_Pin_5) : GPIO_ResetBits(GPIOA, GPIO_Pin_5); data <<= 1; DELAY_US(2); // 保持数据稳定 GPIO_SetBits(GPIOA, GPIO_Pin_6); // 上升沿 DELAY_US(2); GPIO_ResetBits(GPIOA, GPIO_Pin_6); // 下降沿 DELAY_US(2); } }

实测发现,在72MHz主频下,上述代码可实现约500kHz的SCLK频率,完全满足ADS1220的时序要求。

4. 寄存器配置与校准优化

ADS1220有4个配置寄存器,需要根据应用场景精心设置。以下是一个热电偶测量的典型配置:

void ADS1220_InitForThermocouple(void) { uint8_t config[4] = {0}; // 寄存器0: AINP=AIN0, AINN=AIN1, PGA=128, PGA使能 config[0] = MUX_0 | PGA_12 | PGA_BYPASS_Enable; // 寄存器1: 20SPS, 正常模式, 连续转换, 50/60Hz抑制 config[1] = DR_20SPS | MODE_0 | ConverMode_1 | FIR_Mode1; // 寄存器2: 内部2.048V基准, 低侧开关关闭 config[2] = VREF_0 | PSW_ON; // 寄存器3: IDAC关闭, DRDY仅专用引脚 config[3] = IDAC_0 | IDAC1_0 | IDAC2_0 | DRDY_Mode0; CS_Low(); WriteRegister(0x00, 4, config); CS_High(); }

校准技巧

  1. 短接输入引脚读取偏移值
  2. 施加已知基准电压读取满量程值
  3. 在代码中实现线性补偿算法:
float CalibrateReading(uint32_t raw) { static const float offset = -125.3f; // 实测偏移 static const float scale = 0.596f; // 校准系数 return (raw * scale) + offset; }

5. 抗干扰设计与性能提升

在高精度测量中,噪声是主要敌人。通过以下措施可显著提升性能:

PCB布局建议

  • 使用独立模拟地平面
  • 在AVDD和AVSS间放置10μF+0.1μF去耦电容
  • 信号走线尽量短,避免平行数字信号线

软件滤波方案

#define SAMPLE_COUNT 16 uint32_t GetFilteredAD(uint8_t ch) { uint64_t sum = 0; for(uint8_t i=0; i<SAMPLE_COUNT; i++) { sum += GetAD(ch); delay_ms(5); } return (sum + SAMPLE_COUNT/2) / SAMPLE_COUNT; // 四舍五入 }

实测表明,16次平均可使噪声降低约4倍,相当于增加2位有效分辨率。

6. 完整驱动实现

以下是经过优化的完整驱动程序框架:

// ads1220.h #ifndef __ADS1220_H #define __ADS1220_H #include "stm32f10x.h" typedef enum { ADS1220_GAIN_1 = 0, ADS1220_GAIN_2, // ...其他增益设置 } ADS1220_Gain_t; void ADS1220_Init(void); uint32_t ADS1220_ReadData(void); void ADS1220_StartConversion(void); void ADS1220_SetGain(ADS1220_Gain_t gain); #endif
// ads1220.c #include "ads1220.h" #include "delay.h" static void WriteReg(uint8_t addr, uint8_t val) { CS_Low(); WriteByte(WREG | (addr << 2)); WriteByte(val); CS_High(); } uint32_t ADS1220_ReadData(void) { uint8_t buf[3]; CS_Low(); WriteByte(RDATA); buf[0] = ReadByte(); buf[1] = ReadByte(); buf[2] = ReadByte(); CS_High(); return (buf[0]<<16) | (buf[1]<<8) | buf[2]; }

7. 实际应用案例:温度测量系统

将PT100接入ADS1220,配合STM32F103构建高精度温度测量系统:

电路连接

  • PT100 -> 恒流源 -> ADS1220 AIN0/AIN1
  • 基准电阻 -> ADS1220 REFP0/REFN0
float ReadPT100Temperature(void) { uint32_t adc = GetFilteredAD(0); float ratio = (float)adc / 8388608.0f; // 24位满量程 float Rpt100 = 100.0f * ratio / (1.0f - ratio); // 计算电阻值 // 调用PT100分度表查温度 return PT100_ResToTemp(Rpt100); }

在实验室环境下,该系统实现了±0.1°C的测量精度,完全满足工业级应用需求。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/5 19:35:11

为什么AI图层分离技术能彻底改变你的设计工作流程?

为什么AI图层分离技术能彻底改变你的设计工作流程&#xff1f; 【免费下载链接】layerdivider A tool to divide a single illustration into a layered structure. 项目地址: https://gitcode.com/gh_mirrors/la/layerdivider 在数字设计领域&#xff0c;设计师们经常面…

作者头像 李华
网站建设 2026/5/5 19:33:34

Feynman:基于纯文本与费曼学习法的开发者知识管理方案

1. 项目概述&#xff1a;一个面向开发者的知识管理工具 最近在整理个人技术笔记和项目文档时&#xff0c;我一直在寻找一个能兼顾简洁、高效和可编程性的知识管理方案。市面上的笔记软件要么过于封闭&#xff0c;要么功能臃肿&#xff0c;对于需要深度定制和自动化处理技术内容…

作者头像 李华
网站建设 2026/5/5 19:31:37

2026届毕业生推荐的十大降重复率方案实际效果

Ai论文网站排名&#xff08;开题报告、文献综述、降aigc率、降重综合对比&#xff09; TOP1. 千笔AI TOP2. aipasspaper TOP3. 清北论文 TOP4. 豆包 TOP5. kimi TOP6. deepseek 鉴于人工智能生成内容被广泛运用&#xff0c;各种各样的AI检测工具跟着兴起了。为了把文本被…

作者头像 李华
网站建设 2026/5/5 19:28:38

长期项目中使用Taotoken用量预警功能管理资源消耗

长期项目中使用Taotoken用量预警功能管理资源消耗 1. 用量预警功能的项目实践 在持续数月的AI应用开发项目中&#xff0c;资源消耗管理是团队关注的核心问题之一。Taotoken控制台提供的用量预警功能&#xff0c;为项目组提供了主动式的资源监控手段。通过设置每日或每周的Tok…

作者头像 李华