十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

基于51单片机与ADS1110的4通道高精度电压采集方案全解析

基于51单片机与ADS1110的4通道高精度电压采集方案全解析 简介本资源是一套完整的基于51单片机的四通道高精度电压测量系统开发资料面向嵌入式初学者、课程设计学生及电子类实训教师解决多路模拟信号采集、阈值报警与人机显示等典型工程问题。资源包共41个文件涵盖原理图SchDoc/PDF、Keil工程uvproj/uvopt/hex、C语言源码main.c/ADS1110.c/lcd1602.c、头文件、编译中间文件lst/obj、流程图bmp、物料清单xlsx及Proteus仿真项目pdsprj/pdsbak全面支撑从硬件设计、软件编程到系统联调的全流程学习。压缩包仅577KB结构清晰、模块解耦含完整报警逻辑上下限设定蜂鸣器驱动与0–10V量程适配代码LCD1602显示界面直观可复用。目前已有132人下载学习配套功能说明txt与多张实测截图png便于快速验证效果是掌握ADC外设驱动与嵌入式数据采集实践的高性价比入门方案。1. 项目概述一个精准的4通道电压采集方案最近在整理一些老项目的资料翻出来一个基于经典51单片机和ADS1110模数转换器做的4路电压测量模块。这个项目虽然用的都是“老家伙”但麻雀虽小五脏俱全从原理图、PCB、流程图到完整的C51源代码一应俱全。很多刚接触单片机或者想做一个稳定可靠数据采集的朋友可能会觉得从传感器信号到单片机里的数字值这个过程有点“黑盒”要么精度不够要么读数跳得厉害。这个方案的核心就是用一颗高精度、低漂移的16位ADC芯片ADS1110来替代51单片机内部那个聊胜于无的ADC从而实现最高±2.048V量程、分辨率达到62.5μV的精准测量。它特别适合用来监测电池电压、电源输出、传感器分压信号等场景成本可控稳定性经过实测非常不错。如果你手头有STC89C52、AT89S51这类常见的51核心板想给它增加一个靠谱的模拟量输入功能那这个从硬件到软件的全套设计思路和实现细节应该能给你提供一个清晰的参考模板。2. 系统核心设计与芯片选型考量2.1 为什么是“51单片机 ADS1110”这个组合提到51单片机很多人的第一反应是“古董”、“性能弱”尤其是它缺乏片内ADC在处理模拟信号时显得力不从心。而STM32等ARM Cortex-M核的MCU虽然性能强大、外设丰富但对于一些简单的监测、控制场景或者出于学习成本、供应链、项目继承性考虑51单片机依然有它的用武之地。这个项目的设计出发点就是在保留51单片机作为主控的架构下通过外挂一颗专业的ADC芯片来彻底解决模拟信号采集的精度和稳定性问题。ADS1110是TI德州仪器推出的一款超小型、低功耗、16位精度的Σ-Δ型ADC。我选择它主要基于以下几点考量极高的集成度ADS1110内部集成了可编程增益放大器PGA、基准电压源、时钟振荡器和I2C接口。这意味着外部电路极其简洁只需要在电源引脚加个0.1μF的退耦电容在输入引脚根据信号特性考虑是否加滤波芯片就能工作了。相比需要外部基准、时钟和复杂驱动电路的多芯片方案这大大降低了硬件设计的复杂度和出错概率。出色的直流性能Σ-Δ架构的ADC在抑制噪声和提供高分辨率方面有天然优势。ADS1110在15SPS每秒采样次数速率下能提供真正的16位无失码精度。其内部PGA提供1、2、4、8倍增益可选对应不同的输入量程±2.048V, ±1.024V, ±0.512V, ±0.256V这让它可以灵活适配不同幅度的信号充分利用其分辨率。比如测量一节锂电的电压约3.7V可以通过电阻分压到2V以内然后用±2.048V量程测量依然能获得很高的精度。标准的I2C接口51单片机普遍支持I2C总线通过IO口模拟或硬件接口。I2C是双线制SDA数据线SCL时钟线占用MCU引脚少总线扩展能力强。ADS1110的I2C地址可以通过引脚配置理论上一条总线上可以挂多个ADS1110轻松实现多通道扩展。我们做4路测量一种方案是用1片ADS1110配合模拟开关切换通道另一种更简单稳定的方案是直接用4片ADS1110每片负责一路通过不同的I2C地址区分。本项目采用的是后一种方案虽然成本稍高但各通道完全独立互不干扰软件逻辑也更清晰。低功耗与小型化ADS1110采用SOT23-6封装体积非常小。其工作电流典型值仅为240μA在单次转换模式下转换完成后自动进入休眠功耗可低至0.5μA非常适合电池供电的便携设备。注意ADS1110的输入是差分输入IN和IN-但在单端测量应用中我们可以将IN-接地IN接信号实现单端对地的电压测量。这是最常用的接法。2.2 整体系统架构与信号链路分析整个系统的信号流是这样的待测电压信号 - 输入保护与滤波电路 - ADS1110芯片进行模数转换- I2C数字接口 - 51单片机读取、处理数据- 输出显示或上传。对于输入前端我们不能直接把待测电压接到ADS1110的引脚上需要考虑几个保护环节过压保护虽然ADS1110的输入引脚可以承受高于电源电压0.3V的电压但为了防止意外高压如接错线可以在输入串联一个几百欧姆的电阻并并联一个钳位二极管到电源和地。滤波为了抑制高频噪声可以在输入引脚对地接一个小电容如0.1μF。但需要注意这个电容会和前端的串联电阻形成一个低通滤波器会影响信号的建立时间。对于变化缓慢的直流电压测量这个影响可以忽略。阻抗匹配ADS1110的输入阻抗很高10MΩ所以一般信号源阻抗不会带来明显的测量误差。但如果信号来自高内阻源仍需注意。单片机端我们需要用两个IO口来模拟I2C时序如果单片机没有硬件I2C。程序流程主要分为初始化、启动转换、等待转换完成、读取数据、数据换算几个步骤。显示部分可以根据需求选择LCD1602、OLED或者简单的串口打印到电脑。3. 硬件电路设计详解与物料清单3.1 核心原理图分模块解析原理图是硬件设计的蓝图这里我们分模块拆解。1. 51单片机最小系统电路这是整个系统的大脑。以最常用的STC89C52RC为例需要包括电源VCC5V和GND。通常由USB口或外部稳压模块如AMS1117-5.0提供。复位电路一个10kΩ电阻上拉到VCC一个10μF电解电容接地中间接复位引脚RST。实现上电自动复位和手动复位。时钟电路在XTAL1和XTAL2引脚之间接一个11.0592MHz的晶振这个频率便于产生标准的串口波特率两个引脚分别对地接一个20-30pF的瓷片电容。EA/VPP引脚接VCC表示从内部Flash启动程序。I2C接口引脚例如定义P2.0为SDA数据线P2.1为SCL时钟线。这两个引脚需要接上拉电阻通常4.7kΩ或10kΩ到VCC以保证I2C总线在空闲时为高电平。2. ADS1110模块电路单路这是测量的核心。每个ADS1110的接线都非常简单引脚1 (VIN)接待测电压信号正端。引脚2 (VIN-)接地GND实现单端测量。引脚3 (VDD)接电源2.7V-5.5V本项目与单片机共用5V。引脚4 (GND)接地。引脚5 (SCL)接单片机的I2C时钟线并上拉到VCC。引脚6 (SDA)接单片机的I2C数据线并上拉到VCC。同时SDA引脚也是地址选择引脚ADDR。通过将SDA/ADDR引脚连接到GND、VDD或悬空可以设置芯片的I2C从机地址。这是实现多片共存的关键。接GND地址为0x48默认。接VDD地址为0x49。悬空地址为0x4A。注意具体地址格式需参考数据手册通常为7位地址写作时需左移一位加上读写位。3. 4路测量扩展方案为了实现4路独立测量我们使用4片ADS1110。将它们的SCL引脚全部并联接到单片机的SCL引脚。将它们的SDA引脚也全部并联接到单片机的SDA引脚。然后分别设置4片芯片的ADDR引脚为不同的电平GND, VDD, 悬空或者通过电阻分压得到另一个电平但需确保符合芯片识别逻辑从而赋予它们4个不同的I2C地址例如0x48, 0x49, 0x4A, 0x4B。这样单片机在总线上发送地址时只有地址匹配的那片ADS1110会响应。4. 电源与滤波在每片ADS1110的VDD引脚附近必须放置一个0.1μF的陶瓷电容到地用于电源退耦滤除高频噪声。这是保证ADC工作稳定的关键细节。整个系统的5V输入入口最好也加一个10-100μF的电解电容并联一个0.1μF的瓷片电容。3.2 完整物料清单BOM以下清单基于一个典型的、包含4路ADS1110和STC89C52最小系统的设计类别位号/描述型号/参数数量备注主控U1STC89C52RC (或AT89S52)1DIP-40封装方便插拔ADC芯片U2, U3, U4, U5ADS1110A0IDBVR (或ADS1110A0IDBVT)4SOT23-6封装注意不同量程后缀晶振X111.0592MHz1HC-49S 直插或贴片电容C1, C222pF Ceramic Capacitor2晶振负载电容C310μF/16V Electrolytic Capacitor1复位电路C4100μF/16V Electrolytic Capacitor1电源入口滤波C5-C120.1μF Ceramic Capacitor8每片ADS1110电源退耦1个单片机退耦1个电阻R110kΩ Resistor1复位上拉R2-R94.7kΩ Resistor8I2C总线SDA, SCL上拉电阻每线4个并联等效(可选) R_in1-R_in4100Ω Resistor4输入限流保护电阻连接器J12-Pin Screw Terminal4用于接入4路被测电压P1DC-005 Power Jack15V电源输入(可选)40-Pin IC Socket1用于安装单片机其他LED (Green)1电源指示灯串联1kΩ电阻Tactile Switch1复位按钮PCB1自制或打样实操心得BOM中的电阻电容值都是常见值。I2C上拉电阻的阻值需要权衡阻值小上升沿陡速度快但功耗大阻值大功耗小但上升沿缓在高速模式下可能有问题。对于51单片机模拟I2C和ADS1110标准模式100kbps4.7kΩ或10kΩ在5V系统下是稳妥的选择。如果总线较长或负载较多可以适当减小阻值。3.3 仿真图搭建要点在没有实物前用Proteus这类软件进行仿真可以验证逻辑的正确性。在Proteus中搭建本项目的仿真图需要注意元件模型Proteus元件库可能没有ADS1110。这时有两种方法一是寻找第三方制作的模型文件.LIB和 .IDX二是用功能相近的ADC模型替代如PCF8591带I2C接口的8位ADC但精度和寄存器操作完全不同只能验证I2C通信基本逻辑。对于学习而言重点仿真51单片机的程序逻辑和I2C时序更有意义。信号源用Proteus中的“DC VOLTMETER”或“SIGNAL GENERATOR”设置为直流电压来模拟4路被测电压。虚拟仪器使用“I2C DEBUGGER”工具可以监视I2C总线上的数据流非常利于调试通信程序。用“VIRTUAL TERMINAL”虚拟串口连接单片机的串口可以打印出单片机读取到的电压值。仿真重点通过仿真主要验证单片机能否正确产生I2C的起始、停止、应答信号。单片机能否按正确的地址0x48, 0x49等向对应的ADS1110发送配置命令如设置增益和转换速率。启动单次转换后单片机能否正确判断转换是否完成通过读取时是否收到ACK。读取的2字节数据是否正确换算成电压值的公式是否准确。4. 软件流程图与源代码深度解析4.1 程序主流程图与状态设计整个软件的核心是一个顺序执行的循环但通过良好的状态设计可以避免阻塞。下面是一个清晰的主流程图描述上电初始化-配置所有ADS1110-循环执行以下步骤启动通道1转换向地址0x48的ADS1110发送命令启动一次单次转换。短暂延时延时略大于所选转换速率下完成转换所需的最长时间例如对于15SPS转换时间约67ms。读取通道1数据向地址0x48的ADS1110读取2字节转换结果和1字节配置寄存器用于检查状态。数据换算与存储将2字节原始数据换算成电压值浮点数或整数放大后存入数组。重复步骤1-4对通道2地址0x49、通道30x4A、通道40x4B执行同样的操作。数据处理与输出将4个通道的电压值通过串口发送到电脑或刷新LCD显示。返回循环开始继续下一轮测量。为了提升效率可以采用“轮询”而非“固定延时”的方式。即在启动转换后不是傻等固定时间而是不断尝试去读取数据。ADS1110的配置寄存器最高位DRDY/在转换完成后会变低。我们可以通过读取配置寄存器来判断转换是否完成这样能更精准地利用时间。4.2 源代码关键模块拆解以下是用C51Keil C编写的关键代码片段和分析。假设我们使用软件模拟I2C引脚定义为sbit SDA P2^0; sbit SCL P2^1;。1. I2C底层驱动函数这是所有操作的基础必须严格遵循I2C时序。void I2C_Delay() { /* 短暂延时控制SCL频率 */ } void I2C_Start() { SDA 1; SCL 1; I2C_Delay(); SDA 0; I2C_Delay(); SCL 0; } void I2C_Stop() { SDA 0; SCL 1; I2C_Delay(); SDA 1; I2C_Delay(); } bit I2C_WriteByte(unsigned char dat) { /* 发送一个字节返回ACK位 */ } unsigned char I2C_ReadByte(bit ack) { /* 读取一个字节参数ack决定是否发送ACK */ }2. ADS1110读写函数针对ADS1110的读写封装。ADS1110的写操作是写入配置寄存器读操作是连续读出转换结果的高字节、低字节和配置寄存器。// 向指定地址的ADS1110写入配置字节 void ADS1110_WriteConfig(unsigned char addr, unsigned char config) { I2C_Start(); I2C_WriteByte(addr 1); // 写地址 (7位地址左移1位最低位0表示写) I2C_WriteByte(config); // 写入配置寄存器 I2C_Stop(); } // 从指定地址的ADS1110读取数据 // 返回值一个16位整数转换结果通过指针参数获取当前的配置字节 int ADS1110_ReadData(unsigned char addr, unsigned char *config_reg) { unsigned char msb, lsb, config; int result; I2C_Start(); I2C_WriteByte((addr 1) | 0x01); // 读地址 (最低位1表示读) msb I2C_ReadByte(1); // 读高字节发送ACK lsb I2C_ReadByte(1); // 读低字节发送ACK config I2C_ReadByte(0); // 读配置字节发送NACK I2C_Stop(); result (msb 8) | lsb; // 组合成16位有符号整数 // ADS1110输出是二进制补码形式对于正电压直接使用即可 // 如果需要处理负电压当IN-不为0时需判断符号位 if (config_reg ! NULL) { *config_reg config; } return result; }3. 电压换算函数这是将ADC原始值转换为实际电压的关键。ADS1110的满量程输入电压Vfsr由增益决定GAIN。例如增益为1时Vfsr 2.048V。它是一个16位有符号ADC输出码值从-32768到32767对应-Vfsr到Vfsr。// 将ADS1110的原始读数转换为电压值单位伏特 // raw_data: 16位有符号原始数据 // gain: 当前设置的增益 (1,2,4,8) float ADS1110_ConvertToVoltage(int raw_data, unsigned char gain) { float vfsr; // 满量程电压 switch(gain) { case 1: vfsr 2.048; break; case 2: vfsr 1.024; break; case 4: vfsr 0.512; break; case 8: vfsr 0.256; break; default: vfsr 2.048; break; } // 计算公式电压 (原始数据 / 32768) * 满量程电压 // 注意32768 2^15因为它是16位有符号数最大值是32767 float voltage ((float)raw_data / 32768.0) * vfsr; return voltage; }4. 主程序应用逻辑void main() { unsigned char i; int adc_raw[4]; float voltage[4]; unsigned char ads1110_addr[4] {0x48, 0x49, 0x4A, 0x4B}; // 4片ADC的地址 unsigned char config 0x8C; // 示例配置单次转换模式增益115SPS禁用比较器 // 0x8C 1000 1100b // 最高位(DRDY): 1 (读取时表示数据就绪位) // 配置位: 00 (增益1), 000 (15SPS), 11 (禁用比较器) // 初始化 UART_Init(); // 初始化串口用于打印结果 I2C_Init(); // 初始化I2C引脚 for(i0; i4; i) { ADS1110_WriteConfig(ads1110_addr[i], config); // 配置所有ADS1110 } DelayMs(100); // 等待稳定 while(1) { for(i0; i4; i) { // 启动转换写入配置寄存器即启动单次转换 ADS1110_WriteConfig(ads1110_addr[i], config); // 等待转换完成可以延时也可以轮询状态位 DelayMs(70); // 等待时间略大于15SPS下的转换时间(67ms) // 读取数据 adc_raw[i] ADS1110_ReadData(ads1110_addr[i], NULL); // 换算电压 (假设增益为1) voltage[i] ADS1110_ConvertToVoltage(adc_raw[i], 1); } // 通过串口输出结果 printf(CH1: %.3fV, CH2: %.3fV, CH3: %.3fV, CH4: %.3fV\r\n, voltage[0], voltage[1], voltage[2], voltage[3]); DelayMs(1000); // 每秒刷新一次 } }5. 调试要点、常见问题与精度优化5.1 上电调试流程与排错指南硬件焊接好或PCB打样回来后不要急于写程序先进行硬件检查电源与短路检查用万用表测量5V和GND之间是否短路电压是否稳定在5V左右。检查每个IC的电源引脚电压是否正确。I2C总线电平不接单片机时测量SDA和SCL线对地电压应为5V上拉电阻作用。接上单片机但程序不运行时也应接近5V。如果电压被拉低检查是否有引脚配置为输出低电平或者焊接短路。通信测试编写一个最简单的I2C扫描程序。让单片机遍历所有可能的I2C地址0x00 ~ 0x7F发送地址并检查是否收到应答ACK。如果连接正确你应该能扫描到4个地址0x48, 0x49, 0x4A, 0x4B。扫不到地址是调试I2C问题的第一步。软件调试时善用串口打印调试信息打印出读取到的原始16进制数据。打印出配置寄存器的值确认配置是否写入成功。将输入引脚接地0V和接参考电压如1.024V看读数是否对应正确。5.2 常见问题与解决方案速查表现象可能原因排查步骤与解决方案I2C扫描不到任何设备1. 电源问题。2. I2C引脚接错或虚焊。3. 上拉电阻未接或阻值过大。4. 单片机IO口模式设置错误应设为开漏或准双向并先置高。5. SDA/SCL线接反。1. 测电压。2. 对照原理图检查连线。3. 确认上拉电阻已焊接尝试减小阻值如换为2.2kΩ。4. 检查代码中IO口初始化是否正确。5. 交换SDA和SCL试试。只能扫描到部分ADS11101. 地址相同的芯片冲突。2. 某个芯片的ADDR引脚焊接不良或电平设置错误。3. 某个芯片损坏或电源不良。1. 确认每片ADDR引脚电平设置唯一。2. 用万用表测量每个ADDR引脚的实际电压。3. 单独测试每个芯片。读取的数据全是0或0xFFFF1. 转换未完成就读取。2. 读写时序错误特别是ACK处理。3. 配置寄存器设置错误导致转换器未工作。1. 增加启动转换后的等待时间或实现轮询DRDY位。2. 用逻辑分析仪抓取I2C波形与数据手册时序图对比。3. 检查写入的配置字节值确保正确设置了单次转换模式和有效的速率/增益。读数不稳定跳动大1. 电源噪声大。2. 输入信号本身噪声大或阻抗高。3. 未接输入滤波电容。4. PCB布局布线不佳模拟部分受数字干扰。1. 加强电源滤波模拟部分可采用LC滤波或线性稳压器单独供电。2. 在信号输入端并联一个0.1μF~1μF的电容到地。3. 检查信号源质量对于高阻抗源考虑使用电压跟随器缓冲。4. 遵循模拟和数字地单点连接电源走线尽量粗。测量值有固定偏差增益误差1. ADS1110内部基准电压有微小偏差典型值2.048V但有误差。2. 外部分压电阻精度不够。1. 这是系统误差可通过软件校准来消除。测量一个已知精确的电压如用万用表测得的1.000V记录ADC读数计算出一个校准系数。2. 使用精度更高的分压电阻如0.1%或1%。测量值有随机误差噪声1. 环境电磁干扰。2. 转换速率设置过高导致噪声增大。1. 使用屏蔽线连接被测信号缩短走线。2. 降低转换速率如从15SPS降到8SPSADS1110在更低速率下噪声性能更好。可以在配置寄存器中设置。5.3 精度提升与高级应用技巧软件校准要获得高精度测量软件校准必不可少。至少要做零点校准和满度校准。零点校准将输入短路接GND读取多个样本取平均得到零点偏移值offset。满度校准输入一个已知的、接近满量程的精确电压V_ref如2.000V读取多个样本取平均得到读数adc_ref。计算校准系数实际电压V_real (adc_raw - offset) * (V_ref / (adc_ref - offset))。将这两个校准值存储在单片机的EEPROM中每次上电后调用。数字滤波对于跳动的数据可以在软件中施加滤波。最简单的是一阶低通滤波指数加权平均filtered_value α * new_sample (1 - α) * filtered_value其中α是滤波系数0α1越小滤波效果越强但响应越慢。也可以使用滑动平均滤波取最近N个样本的平均值。自动量程切换进阶如果想测量宽范围电压如0-10V可以设计前端分压网络如10V-2V。更智能的做法是先用高量程低增益测量如果发现读数很小则自动切换到低量程高增益再测一次以获得更高分辨率。这需要程序动态改写ADS1110的配置寄存器。低功耗设计在电池应用中充分利用ADS1110的单次转换模式。每次需要测量时才唤醒它进行一次转换读取数据后让其进入休眠。单片机本身也可以在等待转换完成和数据显示间隔进入空闲模式或掉电模式以大幅降低系统整体功耗。这个基于51单片机和ADS1110的4路电压测量系统其价值在于提供了一个完整、清晰且可高度定制化的高精度模拟采集解决方案。它剥离了复杂MCU的冗余功能直击“精准测量”这个核心需求无论是用于工业现场的简单监测、实验室的数据记录还是嵌入式学习的深入实践都能提供一个稳定可靠的硬件基础和易于理解的软件框架。在实际制作中你可能需要根据具体的被测信号特性范围、频率、阻抗调整前端电路根据显示或通信需求修改软件上层但这个核心的“ADCMCU”的架构和调试思路是相通的。本文还有配套的精品资源点击获取
返回列表