ARTICLE DETAIL

资讯详情

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

51单片机PT100温度控制系统设计与Proteus仿真全解析

51单片机PT100温度控制系统设计与Proteus仿真全解析 简介本资源是一套完整的基于51单片机的温度闭环控制系统设计资料面向嵌入式初学者、课程设计学生及电子类实训教师解决温度实时采集、上下限设定与加热/散热执行控制等典型工程问题。压缩包共39个文件含Proteus仿真工程.DSN、原理图.SchDoc、流程图.bmp、物料清单.xls、C语言源代码main.c、TLC1543.c、编译输出文件.hex、.lst、.obj及PDF版原理图与功能说明文档全面覆盖硬件设计、软件逻辑与仿真验证环节总大小774KB。已有117人学习下载资源结构清晰源码含PT100信号调理与ADC转换处理、数码管动态扫描显示、独立按键参数设置及继电器驱动逻辑配套流程图与原理图便于理解系统架构仿真图可直接加载运行观察温控响应过程是掌握传感器应用与单片机外围控制的高实用性入门项目。 提到51单片机课程设计温度控制几乎是最常见的一道题但很多人在PT100上栽跟头。DS18B20固然省事数字接口直接接IO口就行可题目指定PT100那就必须老老实实从模拟前端开始搭。这篇文章我就把基于51单片机 PT100 数码管 Proteus的完整实现思路写出来包括原理图怎么画、信号链怎么算、软件怎么写、仿真的坑在哪里物料清单和核心源代码也会给到可复现的版本。做完这个项目你会发现PT100并没有想象中那么可怕真正难的是把调理电路和软件标定配合好。1. 项目拆解你要做的到底是一个什么东西1.1 题目要求逐条拆解“基于51单片机的温度控制PT100,上下限,数码管proteus原理图、流程图、物料清单、仿真图、源代码”这句话信息量很大拆开看其实是四件事第一控制器必须是51系列单片机。Proteus里最常用的是AT89C51或者AT89C52做实物推荐STC89C52RC指令兼容下载方便。第二测温元件必须用PT100这是铂热电阻不是数字传感器所以必须设计模拟调理电路。第三系统要有上、下限控制功能也就是温度低于下限要启动加热高于上限要停止加热或报警具体怎么分配由需求决定。第四显示输出用数码管同时还要交付原理图、流程图、物料清单、仿真图和源代码这基本就是一套完整的单片机工程项目。很多同学会把PT100当成DS18B20一样直接接一个IO口这是最典型的错误。PT100是电阻型传感器阻抗随温度变化但单片机不认识电阻只知道高电平和低电平所以必须先把电阻变化转换成电压或数字信号。围绕这一条就引出了运算放大器、ADC、查表、滤波等一系列问题。整个项目并没有复杂的算法难点在于模拟前端的设计和软件标定的一致性。1.2 核心方案从传感器到输出的完整信号链路常见的基于51的PT100测温方案有三类我对比一下方案一PT100 恒流源 运算放大器 ADC。恒流源给PT100供电得到电压经运放放大后送ADC。这种方案精度高、抗干扰好但恒流源电路搭建稍复杂适合对精度有要求的场合。方案二PT100 电桥 运放 ADC。把PT100作为电桥的一个桥臂电桥输出的差分电压经运放放大后送ADC。这是课程设计里最稳妥的方案元件常见计算也直白。方案三PT100 比较器 上下限电位器。这种方案不测真实温度只判断是否超过阈值虽然省掉ADC和数码管但无法显示当前温度。题目要求数码管显示所以直接排除。所以最佳选择是方案二。完整信号链路是PT100 → 三线制电桥 → LM358双运放差分放大 → ADC0832 → 51单片机 → 数码管显示同时按键设置上下限单片机输出IO控制继电器或蜂鸣器。ADC的选型也值得说一下。AT89C51本身没有ADC常用ADC0809或者ADC0832。ADC0809是8路8位并行ADC接口并行但需要外部时钟占用的IO口比较多。ADC0832是两路8位串行ADC只需要CS、CLK、DIO三根线占用引脚少程序时序短我用的是ADC0832。如果使用STC89C52部分型号自带10位ADC实物可以直接用但Proteus里对STC的模拟支持不太完整仿真依旧建议用AT89C51 ADC0832逻辑一致实物换芯片时保留同样的信号链即可。2. 硬件设计PT100调理电路与Proteus里的正确画法2.1 PT100测温到底难在哪非线性、导线电阻与自热PT100比NTC、DS18B20麻烦主要是三个问题第一非线性。PT100在0℃时阻值是100Ω100℃时阻值是138.5Ω中间的阻值-温度曲线并不是严格的直线。在0~100℃范围内非线性误差大概有零点几摄氏度如果测量范围扩展到150℃以上误差会增大到好几度。对课程设计这种精度要求不高的场景可以忽略非线性直接用线性计算但你要较真可以用查表法或分段插值。第二导线电阻。PT100本身是低阻值传感器100Ω级别连接导线的电阻哪怕只有0.5Ω引入的误差就有1℃左右。如果导线比较长误差会更大。解决思路是改用三线制接法激励电流从一根线流进电压从第二根线采样第三根线用来补偿另一根导线的压降这样电桥输出基本不受导线电阻影响。这也是题目里“PT100三线制”这个关键词的意义所在。第三自热效应。PT100在工作时要通过电流电流越大传感器自身发热越明显测量值就会偏高。一般把激励电流控制在1mA左右比较合理自热功率不到0.1mW。电桥电路里用几十毫安的电流显然不行所以我在设计时会在电桥供电端串电阻限流保证流过PT100的电流在小电流范围内。Proteus仿真里其实没有真实PT100模型这一点必须提前说清楚。通常的办法是用固定电阻加电位器模拟PT100在0℃对应100Ω把固定电阻100Ω和电位器串联电位器调到38.5Ω时总电阻138.5Ω就对应100℃。调试时转动电位器就能模拟温度变化。这种方法虽然粗糙但验证整个信号链和软件逻辑完全够用。2.2 三线制电桥加运放最经典也最稳定的前端下面说电路设计。我这里采用的是经典三线制惠斯通电桥结构PT100接在其中一个桥臂。电桥的其他三个桥臂用精密电阻阻值选择和PT100的量程中心有关。为了限制桥臂电流我在供电端串联了限流电阻保证PT100上的工作电流在1mA量级。电桥会输出一个差分电压这个电压的变化量很小。以PT100在0~100℃变化为例阻值从100Ω变到138.5Ω桥路输出通常只有几十毫伏。8位ADC的参考电压是5V1 LSB对应约19.5mV。如果不放大当温度变化1℃时PT100阻值变化约0.385Ω电桥输出电压变化只有不到1mV这显然远低于ADC分辨率所以必须用运放把差分信号放大。运放选用双运放LM358这是最常见的低压低功耗运放。使用一级差分放大电路把电桥输出的差分电压放大到0~5V范围内。放大倍数怎么定假设你希望0~150℃对应ADC输入0~5V那么150℃时电桥输出大概60mV放大倍数大约83倍。实际不用算得特别死只要保证最低温和最高温时运放输出都在0.2~4.8V以内就行。太大的放大倍数会让输出提前饱和太小则浪费ADC分辨率。这里要给一个关键的实操建议在运放反馈回路里加一个10kΩ电位器或者固定电阻微调用于校准增益。仿真时可以先把固定电阻值算好实物焊接时再用电位器调零点和满量程。我的经验是先不接PT100用100Ω标准电阻接上调电桥平衡让ADC输出接近0再接一个138.5Ω的标准电阻调放大倍数让ADC输出接近满量程。两个点校准完中间段的误差就不会太大。2.3 数码管驱动与上下限设置电路数码管显示部分我推荐用四位共阳数码管。在Proteus里搜索7SEG-MPX4-CA就是共阳四位数码管7SEG-MPX4-CC是共阴。共阳显示段码和共阴是取反关系代码里要改表不要搞混。如果直接用P0口接段选P0口内部没有上拉电阻仿真中亮度会很暗或者根本不亮。正确做法是P0口接1kΩ排阻上拉到5V或者改用74HC573锁存器驱动。我常用74HC573来做段选和位选P0口输出数据P2.5控制段选锁存P2.6控制位选锁存。先送段码LE引脚给一个上升沿数据锁存到输出端再送位选码同样锁存。这样数码管显示稳定不会闪烁。上下限设置电路很简单至少三个轻触按键设置键SET、加键INC、减键DEC。按键一端接IO口另一端接地IO口内部上拉或外部接10kΩ上拉。按SET进入上限设置模式再按SET进入下限设置模式第三次按SET退出设置模式回到正常显示。在设置模式下INC和DEC调整数值。控制执行部分我建议用继电器或者发光二极管指示即可。仿真中直接用LED最方便不同温度状态用不同颜色LED指示低于下限亮红色高于上限亮黄色正常范围内亮绿色。实物如果接加热器需要用三极管S8050驱动继电器继电器线圈两端并联1N4007续流二极管否则断电瞬间反向电动势可能会击穿单片机IO口这个细节非常重要。3. 软件设计从ADC采样到数码管显示的控制流程3.1 温度换算查表还是分段线性ADC数据如何变成温度软件的核心是把ADC读到的数字量换算成真实温度。硬件电路确定以后ADC输入电压与PT100阻值近似线性关系所以最简单的方法就是两点线性标定。标定过程如下先把电路调到0℃状态比如用100Ω电阻替代PT100记录此时ADC输出为adc0然后把PT100调到100℃状态用138.5Ω电阻替代记录adc100。实际温度T可以这样计算T (adc_now - adc0) * 100 / (adc100 - adc0)这个公式的前提是ADC转换结果和输入电压线性以及放大电路在线性区。对于8位ADC线性度足够对于课程设计这个算法是最容易实现且理解成本最低的。如果要求高一点可以用查表法。这里不是查PT100分度表而是查你自己硬件电路标定出来的ADC值表在0℃、10℃、20℃……每10℃记录对应的ADC数值放在一个const数组里。程序运行时先二分查找当前ADC值所在区间然后线性插值。查表法可以把非线性误差、器件离散误差都压到很低适合温度范围较大或者不同批次器件之间的校准。查表法的缺点是标定过程麻烦如果你没有标准温度计和恒温源就别折腾了。课程设计大多数场景两点线性标定就够报告中可以写清楚误差来源这反而显得更专业。3.2 按键上下限设置与去抖按键处理最怕抖动。机械按键按下时会在几十毫秒内出现多次闭合和断开如果不消抖一次按下可能被识别成三四次。最简单的消抖方法是软件延时10~20ms后再次确认电平稳定后再执行动作。我的按键状态机是检测到按键按下记录当前系统时间。延时10ms再次读取按键状态。如果仍为按下则确认有效按键执行相应功能。等待按键释放防止长按触发重复事件。如果要支持长按连续调节比如按住INC键不松手每200ms自动加1那就要用定时器计时不能把主程序卡在while里。我实际写代码的时候定义了一个按键扫描函数在10ms定时中断里调用主循环通过标志位判断按键事件。这样长按和短按都能处理也不会影响数码管扫描。上下限的逻辑约束也要写进代码。增加上限时如果数值已经等于或小于下限就自动把上限加到下限1减少下限时如果数值已经等于或大于上限就自动把下限降到上限-1。这个看起来简单的判断能避免后续控制逻辑出现矛盾。3.3 数码管动态扫描与抗干扰四位一体的数码管要显示四位数字如果所有位同时点亮占用的IO口和驱动器会很多所以采用动态扫描。原理是同一时刻只接通一位数码管的公共端并送出这一位要显示的字形码然后关断再切换到下一位。这样高速轮流点亮利用人眼视觉暂留看起来就是四位同时显示。动态扫描的周期很关键。一个完整的四位扫描周期建议控制在20ms以内也就是每位点亮时间不超过5ms。这样刷新率约50Hz人眼感觉不到闪烁。如果主程序里有按键消抖延时或者大循环扫描周期会被拉长就会出现闪烁。所以动态扫描最好放在定时器中断里做主循环只负责更新显示缓冲区。抗干扰方面ADC采集到的数据一定要滤波。最简单的滤波是连续采集5次到10次去掉最大值和最小值剩下的取平均。我实测过不加滤波的时候数码管显示的最后一位会有1~2个字的跳动加上中值平均滤波后基本稳定。注意ADC0832在每次转换之前采样保持电容的建立需要时间所以连续采集之间加一点延时或者调用函数时留出操作时钟间隔。3.4 主程序流程图用文字描述一下主程序流程上电后先初始化设置定时器、中断、I/O方向、ADC引脚读取默认上下限值。然后进入主循环调用ADC采集子程序对当前温度进行多次采样和滤波。调用温度换算子程序把ADC值换算成实际温度。调用控制子程序将当前温度与上限下限做比较。如果温度低于下限开启加热继电器如果温度高于上限关闭加热继电器并触发报警如果温度在上下限之间保持之前的输出状态或者恢复到正常状态。调用显示子程序。如果处于正常模式显示实时温度如果处于设置模式显示当前设定的上限或下限。调用按键扫描子程序处理按键事件。定时器中断同时承担两件事数码管动态扫描和按键去抖计时。主循环和中断之间通过全局变量通信注意中断中用到的变量如果用char类型就不容易出错跨多个字节的变量建议在临界区更新。课程设计报告要画流程图时按照这个层级画出“主程序流程图”和“定时器中断流程图”即可。Proteus仿真验证时将上述流程转换成代码后应该能看到数码管实时更新温度按键调节上下限后控制输出状态发生变化。4. Proteus仿真实战搭建、调试、踩坑4.1 元件选型与Proteus仿真库注意事项Proteus搭建工程时元件名称和实际型号不一定完全一样我列一下常用搜索词单片机AT89C51或AT89C52在Microprocessor ICs目录。运算放大器LM358在Operational Amplifiers目录。ADC芯片ADC0832是常见的如果没有搜索ADC0809也可以。ADC0809有28个引脚连接复杂一些但Proteus支持得很好。数码管7SEG-MPX4-CA是共阳四位数码管7SEG-MPX4-CC是共阴。按键BUTTON。电阻、电容、电位器RES、CAP、POT-HG电位器在调节时旋转滚轮就能改变阻值。继电器搜索RELAY或者直接用一个LED代替。Proteus里没有专门的PT100符号不要浪费时间去找PT100。常规做法是把一个100Ω固定电阻和一个电位器串联这个组合当温度变化时调节阻值。电位器的最大阻值可以用10kΩ但实际只用到38.5Ω的一段调节会比较灵敏不太好拧。解决办法是串联一个标称100Ω的电阻再并联一个100Ω的微调电阻不推荐直接用POT-HG阻值范围选100Ω或50ΩProteus的POT可以设置最大阻值。很多初学者会在Proteus中把51单片机的晶振直接省略但为了仿真精确我建议还是放上12MHz晶振和两个22pF电容复位电路用10μF电容和10kΩ电阻。这样程序下载到实物时至少这部分不需要改。4.2 常见仿真问题与排查我把自己在Proteus仿真中常踩的坑整理成一张速查表照着排查能节约大量时间现象可能原因解决方法仿真运行但单片机不工作没有加载HEX文件双击单片机Program File选择编译生成的HEX数码管不亮或亮度很暗P0口没有上拉P0口加1kΩ排阻到5V或改用P1/P2口数码管乱码共阳和共阴段码表写反确认数码管类型调整段码表ADC读数始终为255运放输出超过ADC参考电压降低放大倍数确保输入在0~5VADC读数始终为0运放输出接近0V或接线错误用电压表检查运放输出脚电压按键没反应按键上拉电阻漏接加10kΩ上拉电阻确认按键另一端接地温度显示不变化电位器阻值没调运行后用鼠标转动电位器或按R/R键调节这里单独说一下ADC0832。ADC0832的时序虽然简单但很多人第一次写会卡住。判断方法很简单用一个固定电压源接到ADC输入通道分别给0V、2.5V、5V如果读出来的数值是0、128、255附近说明ADC时序是正确的。如果数值不对先查CLK和DIO电平时序尤其注意读取数据时是在CLK的哪个边沿采样。STC89C52和AT89C51对IO操作没有本质区别但如果你在Keil里开了优化可能影响时序把优化级别设为0不优化再试试。4.3 仿真与实物的差异仿真通过实物不一定顺利区别体现在几个环节第一PT100换电阻模型。仿真中电位器阻值可以稳定在100Ω但实物的PT100导线长度、焊接点电阻、接线端子阻值都不可忽略。所以实物调试前先量一下PT100两线之间在室温下的实际阻值并和万用表校准。如果室温25℃测出来应该在109.7Ω左右偏差太大就要检查导线和接点。第二运放供电。Proteus里LM358用5V单电源直接仿真实物也一样。但要注意LM358的输出并不是真正的轨到轨输出电压最多到3.5~4V左右。解决办法是不要追求满量程5V把ADC输入范围设计在0.2~4.5V这样在有效测温区间内运放能保持线性。第三继电器驱动。仿真中继电器只是个开关模型实物必须加三极管和续流二极管否则单片机会被继电器线圈的反向电动势打复位。另外继电器吸合时电流比较大5V继电器线圈电流通常50mA以上不能直接接在P1口上驱动电路用S8050加1kΩ基极电阻即可。第四电源干扰。实物用USB转串口供电时容易因为USB带载能力不足导致电压跌落。我建议先用万用表测一下5V电压再接负载。如果电压波动明显在电源输入端加一个100μF电解电容和0.1μF瓷片电容这能解决大部分复位和数字跳动问题。5. 物料清单、源代码框架与二次扩展5.1 标准物料清单做实物时的物料清单如下仿真时有些元件可以简化元件型号/参数数量备注单片机STC89C52RC1实物可用仿真用AT89C52晶振12MHz1配22pF电容两只复位电路10μF电解电容 10kΩ电阻1组标准复位电路PT100铂热电阻三线制1温度传感器运放LM3581双运放ADCADC08321串行8位ADC数码管四位共阳7SEG-MPX4-CA1显示温度/设定值锁存器74HC5732段选和位选驱动按键轻触开关3SET、INC、DEC继电器5V继电器1控制加热设备三极管S80501驱动继电器二极管1N40071继电器续流LED红/黄/绿各13状态指示排阻1kΩ ×81P0口上拉电阻100Ω、1kΩ、10kΩ、100kΩ若干按原理图配置电位器100Ω或10kΩ1校准用蜂鸣器5V有源1可选报警仿真阶段不需要STC芯片、三极管、继电器直接用AT89C51和LED代替就能验证逻辑。实测的物料清单和仿真清单分开列报告会更规范。5.2 源代码核心模块示例这里给一个核心代码框架Keil C51编译通过。首先是ADC0832读取函数这是最常见的写法#include reg51.h #include intrins.h sbit ADC_CS P1^0; sbit ADC_CLK P1^1; sbit ADC_DIO P1^2; unsigned char adc0832_read(unsigned char channel) { unsigned char i, dat 0; ADC_CS 0; ADC_CLK 0; ADC_DIO 1; // start bit ADC_CLK 1; _nop_(); ADC_CLK 0; ADC_DIO 1; // single-ended mode ADC_CLK 1; _nop_(); ADC_CLK 0; ADC_DIO channel; // channel select: 0 or 1 ADC_CLK 1; _nop_(); ADC_CLK 0; ADC_DIO 1; // read mode for (i 0; i 8; i) { ADC_CLK 1; _nop_(); dat (dat 1) | ADC_DIO; ADC_CLK 0; _nop_(); } ADC_CS 1; return dat; }ADC0832的通道选择位通道0时channel0通道1时channel1。这个函数返回8位数据范围0~255。注意读取数据时DIO要改为输入模式程序里通过对IO口赋值后又要读取实际51单片机IO工作在准双向模式先写1再读是没问题的。温度采集滤波函数可以这样写unsigned int filter_adc(void) { unsigned char i, max, min, temp; unsigned int sum 0; max 0; min 255; for (i 0; i 8; i) { temp adc0832_read(0); if (temp max) max temp; if (temp min) min temp; sum temp; } sum sum - max - min; // 去掉最大最小值 return sum / 6; // 取平均 }温度换算部分根据标定值计算例如标定adc030adc100220则当前温度为#define ADC_0C 30 #define ADC_100C 220 int adc_to_temp(unsigned int adc) { int temp; temp (int)(adc - ADC_0C) * 100 / (ADC_100C - ADC_0C); return temp; }这个近似公式忽略了非线性但你可以在报告中说明误差范围。数码管动态扫描代码不细算了核心是定时器中断里每隔2ms切换一位显示缓冲区存放四个位的段码或数字。共阳数码管段码表一般这样定义unsigned char code seg_table[10] { 0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80, 0x90 };按键扫描函数需要放在主循环或者定时器中断中处理。我习惯在10ms定时器中断里做状态机主循环只负责取事件标志。上下限控制逻辑放在主循环里void control(int temp) { if (temp lower_limit) { RELAY 1; // 开启加热 LED_LOW 1; LED_HIGH 0; } else if (temp upper_limit) { RELAY 0; // 关闭加热 LED_LOW 0; LED_HIGH 1; } else { RELAY 1; // 中间温度维持加热可选 LED_LOW 0; LED_HIGH 0; } }这里中间区域的策略可以调整。更合理的是加入滞回控制低于下限加热加热到上限回差值比如上限-5℃再关闭避免继电器频繁通断。比如设置上限80℃下限20℃当温度低于20℃时开启加热加热到75℃就关闭而不是非要到80℃才关。这样会减少设备磨损。5.3 这个项目还能怎么改做完基础的温度控制后可以往几个方向扩展一是把数码管换成LCD1602。LCD1602能显示“Temp: 25.6℃”和“H:80 L:20”可读性比数码管强很多代码量也不会增加太多。二是引入PID控制。当前实现的开关控制会让温度在上下限之间波动如果要精确控温可以用PWM控制加热功率再配合PID算法。51单片机的运算能力完全够跑一个简单的增量式PID只需要定时采集温度、计算偏差、输出PWM占空比。三是增加EEPROM存储功能。用AT24C02把设置好的上下限值存起来掉电不丢失。这样下次上电不用重新设置在实物演示时显得更完整。四是串口通信。单片机每隔1秒把温度通过串口发送到电脑上位机用Python的pyserial读取并画实时曲线。这个功能很加分尤其适合做毕设演示但要注意串口通信和中断优先级的协调。最后仿真和实物都一样硬件上电顺序很重要。先开电源等1秒再让单片机执行主要逻辑避免继电器吸合瞬间拉低电压导致复位。可以在main函数开头加一个延时函数这个看起来没技术含量的小细节往往能解决很多莫名其妙的问题。我在实际调试这个项目的时候最大的体会是不管Proteus仿真跑得多漂亮实物上温度显示的校准永远绕不开。把PT100分度表打印出来放在工作台上用热水和冰水做0℃和100℃附近的粗校准再用线性公式修正你的报告和演示效果都会扎实很多。多备几个电位器每次焊接前先量一遍阻值这些都是花小钱省大功夫的事。本文还有配套的精品资源点击获取
返回列表