资讯动态

基于51单片机的PT100温度测量系统:TLC1543采样与Proteus仿真

发布时间:2026/9/16 9:40:30 来源:尧图企业网站定制
简介基于51单片机的PT100铂电阻温度测量方案覆盖原理图、C语言源代码和Proteus仿真工程面向单片机学习者、课程设计或电子竞赛备赛人群解决一路铂电阻温度信号从采集、调理、模数转换到液晶屏显示的全流程设计问题。资源包共46个文件、约905KB压缩包内除原理图文档与仿真工程外还提供C语言源码、工程配置文件、烧录文件、编译列表以及元件清单、功能介绍、流程图等辅助材料并将仿真、源码、原理图分类放置便于按模块查阅。目前已有346人学习下载适合用来快速搭建一套完整的单片机测温实验环境。通过该资源可以理解PT100铂电阻的恒流源或电桥测量思路、TLC1543芯片的数据采集时序、线性化处理与量程转换算法以及LCD1602驱动显示代码的编写方式。在Proteus中直接打开仿真文件即可观察温度变化对显示结果的实时影响再配合源码逐段分析信号通路能帮助读者从硬件连接和软件逻辑两个层面掌握典型的单片机测量系统设计方法。1. 从 PT100 到 TLC1543一路温度测量系统到底要解决什么拿到一个“基于 51 单片机的温度测量PT100、TLC1543、1 路”这样的压缩包里面通常是一张 Proteus 仿真图、一张原理图还有一份 Keil 工程。做这套东西的人往往不是要研究 PT100 本身而是想搞清楚一条完整的信号链铂电阻把温度变成电阻电阻再变成电压电压进 10 位串行 ADC最后被 51 单片机读走、换算成摄氏度。这个标题的关键在于“1 路”——只测一路温度却选了 TLC1543 这种 11 通道串行 ADC很多人不理解为什么不用更常见的 ADC0809。答案是引脚和精度。51 的 IO 本来就紧张ADC0809 八位并行接口要占掉一整组端口而 TLC1543 是三线串行P1 口随便拨三根线就能驱动还能拿到 10 位分辨率。这篇文章就把这套系统的信号调理、接口时序、代码换算和 Proteus 排错一次讲完适合做课程设计、毕业设计或者在老产品上做低成本温采扩展的工程师参考。2. 信号链路设计PT100 桥路、放大倍率与 TLC1543 的 10 位采样2.1 PT100 的温度特性与阻值-电压变换选型PT100 是铂电阻温度传感器0℃ 时标称电阻 100Ω100℃ 时约 138.5Ω平均温度系数大约 0.385Ω/℃。这个变化量很小直接分压进 ADC 的话VCC 的波动、基准电阻的温漂都会被当成温度变化。所以常见做法是先把 PT100 放进电桥让桥路输出一个差分电压再由运放放大到 ADC 的输入范围。电桥的一个典型接法是上桥臂用两个阻值相同的电阻 R1、R2下桥臂一边放 PT100另一边放固定电阻 R0。取 R1R21kΩ、R0100Ω电桥输出可以写成Vdiff VCC × ( R_pt / (R1 R_pt) − R0 / (R1 R0) )代入 VCC5V、R11kΩ、R0100Ω算出来的结果大致是温度PT100 阻值桥路差分电压放大 20 倍后0℃100.0Ω0V0V25℃109.7Ω约 39.8mV约 0.80V50℃119.4Ω约 78.7mV约 1.57V100℃138.5Ω约 153.7mV约 3.07V10 位 ADC 的量化步长是 4.88mV5V 满量程放大后每摄氏度大约对应 30.8mV也就是说每个 LSB 约合 0.16℃对 1 路温度采集足够用。比 ADC0809 的 8 位分辨率提高了一个数量级而且没有多占 IO。2.2 TLC1543 的串行接口为什么三根线就能读回 10 位TLC1543 是 TI 的 11 通道 10 位逐次逼近型 ADC单 5V 供电内置采样保持。它和单片机之间只需要 I/O CLOCK、ADDRESS/DATA IN、DATA OUT 三根线再加上一根片选 CS。读一次转换结果分两步先通过 DATA IN 移入 4 位通道地址选好要采哪一路再通过 DATA OUT 在时钟驱动下移出 10 位数据先出最高位。之所以用这种串行方式是因为 11 个模拟通道只需要 4 位地址地址线和数据线还能分时复用。对“1 路”这个场景来说A0 固定接放大器的输出代码里每次读通道 0 就行但通道号参数还是保留方便以后扩成两路、三路不用改硬件。2.3 引脚分配与接线表TLC1543 的 DIP-20 封装脚位比较多但本次只需要其中几个关键引脚。P1 口的四根线分配如下TLC1543 引脚功能接到 51 单片机A0模拟输入 0运放输出I/O CLOCK串行时钟P1.1ADDRESS/DATA IN通道地址输入P1.2DATA OUT转换结果输出P1.3CS片选低有效P1.0VCC5V电源VREF参考电压高端5VVREF-参考电压低端GND没有用到的 A1~A10 全部接地避免浮空输入把内部多路开关的漏电流带进参考网络。EOC 引脚在纯软件读时序里可以不接保守做法是接一个 10kΩ 上拉到 VCC。51 单片机的 IO 是准双向口直接和 TLC1543 的三根信号线相连没问题两者都是 5V 电平不需要电平转换。在 Proteus 里画仿真图时TLC1543 的 VREF 默认就是 VCCVREF- 是 GND不用额外设置。如果以后改用外部精密基准才需要把 VREF 从 VCC 上摘下来单独接基准源。3. 原理图搭建51 最小系统、运放差分放大与 TLC1543 接线3.1 差动放大电路的电阻取值与增益计算PT100 桥路的差分电压只有 0~153.7mV不能直接进 ADC中间要加一级差动放大。常见做法是用 LM358 或者 OP07 搭一个减法放大器。LM358 便宜、单电源供电也方便但输出摆幅到不了电源轨5V 供电时输出上限大约 3.5VOP07 失调电压更小适合精度要求更高的场合。这里按 LM358、增益 20 来算。差动放大电路用四个电阻增益由反馈电阻和输入电阻的比值决定。取输入电阻 R_in10kΩ、反馈电阻 R_f200kΩ增益就是 200k/10k20。四个电阻可以全用 10kΩ 做输入臂上边两个反馈电阻用 200kΩ等效电路如下同相输入端接桥路中的 PT100 侧电压反相输入端接桥路中的固定电阻 R0 侧电压输出接 TLC1543 的 A0电源用单 5V0℃ 时桥路两端电压相等输出为 0V100℃ 时输出约 3.07V没有超过 LM358 的实际输出能力也不会触到 TLC1543 的 VREF。留出的 0~5V 余量正好可以覆盖 0~130℃ 范围给超量程留一点空间。3.2 51 最小系统与各模块连接顺序单片机部分用一个标准的 AT89C51 最小系统晶振选 11.0592MHz而不是常见的 12MHz。原因很简单后面串口调试要输出温度值9600 波特率在 11.0592MHz 下 TH10xFD 没有误差12MHz 下会有约 2% 的误差虚拟终端上容易出现乱码。复位电路用 10μF 电解电容和 10kΩ 电阻串联到 VCC 即可。整体信号流向是PT100 桥路 → LM358 差动放大 → TLC1543 A0 → P1 口数据交换 → P3.1 串口输出。电源和地线建议在 Proteus 里用 POWER/GROUND 端子统一标注TLC1543 的模拟地和数字地先连在一起再回到电源地避免在仿真图上出现悬空网络。3.3 Proteus 元件搜索与放置顺序在 Proteus 的元件拾取框中搜索并放置以下器件元件搜索关键词备注51 单片机AT89C51也可用 AT89C52ADCTLC1543在 Analog ICs 分类下运放LM358双运放只用到其中一个PT100 模拟POT-HG用电位器代替阻值变化固定电阻RES100Ω、1kΩ、10kΩ、200kΩ晶振CRYSTAL设置 11.0592MHz虚拟终端VIRTUAL TERMINAL显示温度输出POT-HG 的三端接法要特别注意不是直接短路当成可变电阻用而是把固定端一端接地中间滑动端接桥路中的 PT100 位置另一端悬空或接高阻。Proteus 里双击 POT-HG 可以直接输入电阻值100Ω 模拟 0℃138.5Ω 模拟 100℃比拖动画滑块精确得多。画图时先放 51 最小系统再放 TLC1543最后放桥路和运放这样网络标号不容易乱。桥路中的 R0 建议单独取出来在仿真阶段不要和 PT100 共用同一个 100Ω 电阻否则电桥永远处于平衡状态输出始终是 0V。4. Keil C 代码TLC1543 读时序、查表线性化与串口输出4.1 用 GPIO 模拟 TLC1543 的串行时序TLC1543 没有标准的 SPI 控制器直接用 51 的普通 IO 翻转时钟即可。每次转换需要 14 个时钟周期前 4 个周期把通道地址从 ADDRESS/DATA IN 移入后 10 个周期从 DATA OUT 读回转换结果。下面这个函数是完整可跑的通道号从 0 到 10本次工程固定传 0。#include reg52.h sbit ADC_CS P1^0; sbit ADC_CLK P1^1; sbit ADC_DIN P1^2; sbit ADC_DOUT P1^3; // 读取 TLC1543 指定通道的 10 位转换结果 unsigned int read_tlc1543(unsigned char channel) { unsigned char i; unsigned int value 0; ADC_CS 0; // 拉低片选进入读时序 ADC_CLK 0; // 阶段1移入 4 位通道地址MSB 在前 for (i 0; i 4; i) { ADC_DIN (channel 0x08) ? 1 : 0; channel 1; ADC_CLK 1; // 上升沿锁存地址位 ADC_CLK 0; } // 阶段2读取 10 位数据每次上升沿移出一位 for (i 0; i 10; i) { ADC_CLK 1; value (value 1) | ADC_DOUT; ADC_CLK 0; } ADC_CS 1; // 释放片选 return value; }地址移位循环里channel 每次都左移判断最高位是 0 还是 1这样写的好处是不用单独维护一个 bit 指针。数据读取循环中先拉高时钟再从 DOUT 取值然后在下降沿之后准备下一位时序上留足了数据建立时间。整个函数不需要精确延时因为 51 的指令周期本身就在几百纳秒到微秒级远低于 TLC1543 的 2.1MHz 最高时钟频率。4.2 从 ADC 值反推 PT100 电阻桥路方程与整数运算ADC 值不能直接查温度要先换算成 PT100 的电阻值。这里不用浮点用整数运算就够了。核心思路ADC 值先还原出运放输出电压再除以增益 20 得到桥路差分电压然后用桥路方程反解 R_pt。推导后的计算公式是R_pt 1000 × (x 91) / (909 − x)其中 x 输出电压毫伏值 / 100这里把 Vdiff/VCC 放大 1000 倍转成整数。写成 C 代码如下// 根据 ADC 数值计算 PT100 电阻返回电阻值乘以 10单位 0.1Ω unsigned int calc_rpt_x10(unsigned int adc_val) { unsigned long vout_mv; // 运放输出电压单位 mV unsigned int x; // Vdiff/VCC 的千分值 unsigned long r_pt; // 电阻中间值 vout_mv (unsigned long)adc_val * 5000UL / 1023UL; x (unsigned int)(vout_mv / 100UL); // 对应 20 倍增益、5V 参考 if (x 818) x 818; // 防止分母趋近于 0 r_pt 1000UL * (x 91) / (909 - x); // 结果约为 10000~13850 return (unsigned int)r_pt; }为什么用vout_mv / 100而不是直接除因为放大 20 倍后100℃ 对应的满幅输出是 3074mV除以 100 得到 30代入公式后 R_pt 约等于 13850也就是 138.5Ω正好和分度表对得上。整数运算在 Keil C51 下编译出来的代码体积远小于浮点库51 没硬件除法器也能接受。4.3 PT100 分度表查表与线性插值把电阻换算成温度最稳的办法是查表。0~100℃ 的温度区间内PT100 标准分度表表现为一条略微弯曲的曲线每 10℃ 取一个点表值存成电阻×10可以精确到 0.1Ω。code unsigned int pt100_table[11] { 1000, 1039, 1078, 1117, 1155, 1194, 1232, 1271, 1309, 1347, 1385 }; // 输入电阻0.1Ω返回温度乘以 100.1℃ unsigned int temp_from_r(unsigned int r_x10) { unsigned char i; if (r_x10 pt100_table[0]) return 0; if (r_x10 pt100_table[10]) return 1000; for (i 0; i 10; i) { if (r_x10 pt100_table[i] r_x10 pt100_table[i 1]) { unsigned int numerator; unsigned int denominator; numerator (r_x10 - pt100_table[i]) * 100UL; denominator pt100_table[i 1] - pt100_table[i]; return (i * 100) numerator / denominator; } } return 1000; }循环里先找到温度落在哪两个分度点之间再用线性插值细化。例如电阻值 1130113.0Ω落在表中 111730℃和 115540℃之间插值结果就是 33.4℃。由于 10bit ADC 的量化误差本身约 0.16℃分段线性插值的误差远小于量化误差不需要上浮点公式。串口输出部分用标准 UART初始化 9600 波特率主循环里采一次、算一次、发一次void uart_init(void) { TMOD 0x20; // 定时器1模式2 自动重装 TH1 0xFD; // 9600 波特率 11.0592MHz TL1 0xFD; TR1 1; SCON 0x50; // 模式1允许接收 } void send_char(char c) { SBUF c; while (!TI); TI 0; } void main(void) { unsigned int adc_val, r_x10, temp_x10; uart_init(); while (1) { adc_val read_tlc1543(0); r_x10 calc_rpt_x10(adc_val); temp_x10 temp_from_r(r_x10); // 输出形如 T25.3 C\r\n 的文本 send_char(T); send_char(); send_char(0 temp_x10 / 100 % 10); send_char(0 temp_x10 / 10 % 10); send_char(.); send_char(0 temp_x10 % 10); send_char( ); send_char(C); send_char(\r); send_char(\n); } }每次循环中间没有加延时TLC1543 连续转换完全能跟上注意虚拟终端刷屏会非常快。实际使用时可以在两次采样之间加 200ms 延时把输出频率压到每秒 5 次左右方便观察。5. Proteus 仿真验证POT 模拟 PT100、虚拟终端读数与排错5.1 装载 hex 文件并启动仿真的顺序Proteus 仿真图里双击 AT89C51在 Program File 一栏选择 Keil 生成的 hex 文件晶振频率改成 11.0592MHz。然后从左侧元件列表里找到 VIRTUAL TERMINAL把它的 RXD 接单片机 P3.1TXDTXD 接 P3.0RXD两线交叉否则虚拟终端什么都收不到。波特率固定在 96008 位数据无校验。放置 TLC1543 时确认 VREF 和 VCC 连到了同一个 5V 电源端。有部分 Proteus 版本里 TLC1543 的 VREF- 不能在元件属性里留空必须显式接地。模拟输入端 A0 不要直接连 LM358 输出中间可以加一个 100Ω 保护电阻方便示波器探针单独测量。5.2 用 POT 阻值模拟不同温度点双击 POT-HG把 Minimum 设为 100Maximum 设为 200然后用按键结合手动输入阻值。PT100 有几个关键温度点的阻值可以直接对照温度PT100 标准阻值理论 ADC 值虚拟终端应显示0℃100.0Ω00.0℃25℃109.7Ω16325.3℃50℃119.4Ω32150.0℃75℃128.7Ω47574.8℃100℃138.5Ω628100.0℃注意这里的 ADC 值是理论计算值实际跑仿真时因为运放模型和电阻误差会有一两个 LSB 的偏差属正常现象。POT 阻值改完后要重新运行仿真或者暂停后继续运行TLC1543 才会重新采样。5.3 虚拟终端无输出或读数为零的排查最常见的三个问题是串口线接反、POT 阻值没生效、TLC1543 的 CS 引脚没被拉低。排查顺序先用示波器图标放在 P1.1 和 P1.3 上确认有没有时钟和输出数据再量 LM358 的输出电压看它是不是真的在 0~3.07V 范围内变化最后检查主函数里的 P1 口定义和原理图上的网络标号是否一致。如果虚拟终端有输出但数值固定不变多半是read_tlc1543(0)里的通道号写错或者 A0 引脚接成了 A1。TLC1543 的通道地址是从 0 开始数的A0 对应地址 0不是地址 1。还有一类情况是电桥输出反向PT100 侧电压高于固定电阻侧电压时LM358 输出会冲到接近电源电压ADC 读出满量程 1023这时把运放的同相、反相输入端对调即可。6. 实际测温中的两个精度细节中值平均滤波与两点标定6.1 连续采样去掉毛刺7 次中值平均PT100 桥路输出的信号本身很稳定但 Proteus 仿真里如果叠加了电源纹波或运放自激ADC 读数会跳动。简单平均滤波对突变毛刺无能为力更稳妥的是连采 7 次去掉最大和最小剩下 5 个取平均。这样既滤掉偶发尖峰又不会像滑动平均那样拖慢响应。unsigned int adc_mid_filter(void) { unsigned char i, j; unsigned int buf[7]; unsigned int tmp; unsigned long sum 0; for (i 0; i 7; i) { buf[i] read_tlc1543(0); } // 冒泡排序长度只有7无所谓效率 for (i 0; i 6; i) { for (j i 1; j 7; j) { if (buf[j] buf[i]) { tmp buf[i]; buf[i] buf[j]; buf[j] tmp; } } } // 去掉 buf[0]、buf[6]剩下5个取平均 for (i 1; i 6; i) { sum buf[i]; } return (unsigned int)(sum / 5); }7 次采样在 14 个时钟周期的基数上只多出几十微秒51 跑起来毫无压力。把主循环里的adc_val read_tlc1543(0)换成adc_val adc_mid_filter()虚拟终端上的末位跳动会明显减少。排序虽然用了最简单的冒泡但数组长度固定为 7代码体积和耗时都可控不需要引入快速排序。6.2 用两个已知阻值修正系统增益电桥里的 R0、R1 电阻和运放的反馈电阻实际值都不可能完全等于标称值。Proteus 仿真用的是理想电阻误差看不出来但实物上随便一个 5% 精度的 100Ω 电阻就会让 0℃ 输出偏离好几十毫伏。解决方法是两点标定取两个已知阻值的电阻代替 PT100一个 100Ω 对应 0℃一个 138.5Ω 对应 100℃测出 ADC 值后反推实际增益 K而不是用标称的 20。标定公式很简单K (ADC_hot − ADC_cold) × 5.0V / (1023 × 0.1537V)把 K 写死成一个常量替换calc_rpt_x10函数里的 100 这个除数。比如实测 100℃ 时 ADC 读数是 641反推 K 约等于 20.4就把vout_mv / 100UL改成vout_mv / 102UL结果会立刻准确。这个做法不改变硬件只改一个常量在批量做板子的时候特别有用。6.3 用固定电阻代替 PT100 的粗标定手法如果手头没有精密电阻箱可以用几个 1% 精度的金属膜电阻串并联凑出 100Ω、110.5Ω、138.5Ω 三个点。在 Proteus 里更简单直接把 POT-HG 的阻值精确设到这三个值记下虚拟终端显示的温度。只要三个点的误差都在 ±0.5℃ 以内这套代码和电路就可以拿去实际测温了。0~100℃ 之外如果还要扩展量程再把 PT100 分度表加长到 150℃、200℃查表代码本身不用改。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价