当前位置: 首页 > news >正文

STM32与ADS1256的SPI通信实战:从寄存器配置到串口数据可视化

1. 硬件准备与电路连接

第一次接触ADS1256这块24位ADC芯片时,我被它的精度吓到了——理论上能分辨出0.000000119V的电压变化!不过要让STM32和它正常对话,硬件连接是第一个门槛。我用的STM32F103C8T6最小系统板,和ADS1256模块之间需要接7根线,这里最容易出错的是SPI引脚分配。

记得有次调试时发现数据全是乱码,折腾半天才发现把MOSI和MISO接反了。正确的接法应该是:

  • PB13接SCLK(时钟线)
  • PB14接DOUT(MISO,主设备输入)
  • PB15接DIN(MOSI,主设备输出)
  • PB12接CS(片选)
  • PB11接DRDY(数据就绪中断)

电源部分要特别注意,ADS1256的模拟供电最好用LDO稳压,我用的AMS1117-5.0给模块供电。如果采集的信号有高频噪声,建议在AIN引脚加RC滤波,比如100Ω电阻串联104瓷片电容到地。

2. SPI初始化与时序调试

SPI配置是第一个软件难关,ADS1256的SPI时序比较特殊:

  1. 时钟极性要设低电平空闲(CPOL=0)
  2. 数据在第二个边沿采样(CPHA=1)
  3. 必须使用软件控制片选
void SPI2_Init(void) { SPI_InitTypeDef SPI_InitStructure; GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE); // PB13(SCK), PB14(MISO), PB15(MOSI) GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure); 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_2Edge; // CPHA=1 SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_32; SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; SPI_Init(SPI2, &SPI_InitStructure); SPI_Cmd(SPI2, ENABLE); }

调试时建议用逻辑分析仪抓SPI波形,重点看:

  • CS拉低后是否有时钟信号
  • 数据线变化是否发生在时钟边沿
  • DRDY信号变化是否正常

3. 寄存器配置详解

ADS1256有11个可配置寄存器,最关键的三个是:

寄存器地址功能说明
STATUS0x00控制数据顺序、自动校准
ADCON0x02设置PGA增益和传感器检测
DRATE0x03配置数据输出速率

比如要设置10SPS采样率、增益为1的配置代码:

void ADS1256_Config(void) { // 高位在前,启用输入缓冲 ADS1256_WriteReg(ADS1256_STATUS, 0x06); // 增益设为1,关闭传感器检测 ADS1256_WriteReg(ADS1256_ADCON, 0x00); // 10SPS采样率 ADS1256_WriteReg(ADS1256_DRATE, 0xF0); // 执行自校准 while(ADS1256_DRDY_PIN); // 等待DRDY变低 ADS1256_CS_LOW(); SPI_SendByte(ADS1256_CMD_SELFCAL); while(ADS1256_DRDY_PIN); // 等待校准完成 ADS1256_CS_HIGH(); }

特别注意写寄存器时序:

  1. 先发送写寄存器命令(0x50|寄存器地址)
  2. 接着发送要写入的数值
  3. 最后需要执行WAKEUP命令(0x00)

4. 数据采集与电压转换

读取24位AD值是个精细活,要注意符号位处理:

int32_t ADS1256_ReadADC(uint8_t channel) { uint32_t adc_value = 0; // 设置输入通道 (单端模式示例) ADS1256_WriteReg(ADS1256_MUX, (channel<<4) | 0x08); // 发送同步命令 ADS1256_CS_LOW(); SPI_SendByte(ADS1256_CMD_SYNC); SPI_SendByte(ADS1256_CMD_WAKEUP); // 请求读取数据 SPI_SendByte(ADS1256_CMD_RDATA); Delay_us(10); // 等待转换完成 // 读取24位数据 adc_value |= (SPI_ReceiveByte() << 16); adc_value |= (SPI_ReceiveByte() << 8); adc_value |= SPI_ReceiveByte(); ADS1256_CS_HIGH(); // 处理负数 (24位有符号数转换) if(adc_value & 0x800000) { adc_value |= 0xFF000000; } return (int32_t)adc_value; }

电压转换公式需要根据参考电压计算:

float VREF = 5.0f; // 假设使用内部5V参考 float voltage = (adc_value * VREF) / 8388608.0f; // 8388608=2^23

实际测试中发现,接地通道会有约0.001V的底噪,这是正常现象。如果要更高精度,可以:

  1. 采集10次取平均值
  2. 使用外部精密基准源
  3. 在代码里做软件滤波

5. 串口输出与数据可视化

最后把采集到的数据通过串口发送到上位机,我用的是最简协议:

void Send_ADC_Values(void) { char buffer[64]; for(uint8_t ch=0; ch<8; ch++) { int32_t raw = ADS1256_ReadADC(ch); float voltage = (raw * 5.0f) / 8388608.0f; sprintf(buffer, "CH%d: %.6fV\r\n", ch, voltage); USART_SendString(USART1, buffer); } }

在PC端可以用串口助手,或者自己用Python写个简单的接收程序:

import serial import matplotlib.pyplot as plt ser = serial.Serial('COM3', 115200) voltages = [[] for _ in range(8)] while True: line = ser.readline().decode().strip() if line.startswith('CH'): ch = int(line[2]) v = float(line.split(':')[1].replace('V','')) voltages[ch].append(v) # 简单绘图 plt.clf() for i in range(8): plt.plot(voltages[i][-100:], label=f'CH{i}') plt.legend() plt.pause(0.01)

调试时遇到过串口数据错位的问题,后来发现是printf浮点打印占用了太多时间,导致SPI时序错乱。解决方法是用sprintf先格式化好字符串,再一次性发送。

http://www.jsqmd.com/news/838032/

相关文章:

  • 开源阅读鸿蒙版:如何在HarmonyOS上打造你的专属电子书库?
  • 2026年5月性价比之选:如何找到靠谱的气浴恒温振荡器厂家 - 品牌推荐大师1
  • 误删/lib64/libc.so.6软连接:从系统“脑死亡”到紧急救援
  • C语言函数指针数组:从概念到实战,构建高效嵌入式系统架构
  • 敦煌徒步|选择企业徒步执行公司就选新沙州 - 新沙州文旅
  • 如何彻底解决腾讯游戏ACE-Guard卡顿问题:免费开源性能优化工具指南
  • 2026年大润发购物卡回收平台正规推荐榜 - 速递信息
  • 如何5分钟搞定Windows和Office永久激活:开源智能工具完整指南
  • NCM解密终极指南:3步释放网易云音乐到任何播放器
  • idea 安装cline
  • 如何通过TaoToken CLI一键安装包并配置多模型环境
  • 如何5步完成Windows和Office智能激活:KMS_VL_ALL_AIO完整指南
  • Linux高效运维:从安全操作到脚本优化的实战习惯指南
  • UE5 产品三维交互展示 创意实现
  • 告别dd命令焦虑:用Clonezilla给FT2000+做系统备份,安全又省心
  • B站视频转文字终极指南:3分钟掌握高效内容整理神器
  • 耐高温耐腐蚀合金厂商推荐:高端Hastelloy C-276合金厂商联系方式 - 品牌2025
  • RISC-V PMP内存保护单元调试实战:从原理到问题排查
  • 为ChatGPT集成OCR功能:从原理到实现的浏览器扩展开发指南
  • 如何用Pixelle-Video一键生成多语言短视频:终极AI内容创作指南
  • 2025最权威的六大AI辅助写作神器推荐
  • Easy-RSA 终极配置指南:5分钟掌握证书颁发机构核心设置
  • 三步搞定海量图片二维码识别:QrScan批量检测工具终极指南
  • 2026护发素推荐:主打顺滑功效的好物 - 速递信息
  • 基于LabVIEW与FlexRIO FPGA的微型OCT系统开发:从原理到实时成像实现
  • SpringBoot项目实战:5分钟搞定ip2region离线IP库集成(含Nginx代理IP获取避坑指南)
  • 在STM32上为LwIP添加自定义软件定时器:以心跳包和断线重连为例
  • Equalizer APO专业配置指南:系统级音频均衡解决方案
  • 从零构建回声状态网络(ESN):Python实战时间序列预测
  • GBFR-Logs终极指南:三步搞定《碧蓝幻想:Relink》DPS统计问题