简介:面向电子信息、自动化等专业单片机课程设计与嵌入式入门实践,这份文档给出基于AT89C51与DS18B20的多点温度检测系统完整设计方案,重点解决两点温度采集、循环显示与LCD界面呈现等问题。压缩包内为1个doc文件,约199KB,以课程设计报告为主体,串联总体方案、硬件设计、软件设计、系统仿真与设计总结等章节,并附源程序代码。硬件部分展开主控制器、1602LCD显示模块和温度采集模块,说明DS18B20内部结构、高速暂存存储器、分辨率配置、温度数据格式与换算方法,以及单总线连接和单片机最小系统电路图;软件与仿真部分则便于对照理解采集、转换和显示流程。已有1652人学习下载,适合需要撰写课设报告、搭建温控实验或查漏补缺的读者参考,也可作为多点温度监测方案的入门模板。
1. 从冰箱两个温区要同时盯住说起
一台冰箱的保鲜层和冷冻层,温度要求根本不是一回事:保鲜层大概在 0 到 8 摄氏度之间,冷冻层要压到零下十八度以下。只放一个探头,你只能知道某个点的温度,另一层的变化完全是个黑匣子。这类「一个小系统里多个位置要分别盯着」的需求,在恒温箱、机柜、仓储、电力电讯设备的过热预检里到处都是。这份基于单片机多点温度检测系统设计(含代码与原理图)就是冲这个场景来的:两路数字温度传感器挂在单片机的两个 IO 上,一片 8 位单片机轮流读取、1602 液晶循环显示,两秒换一屏。它适合两类人——正在做课程设计、需要一套能跑通仿真的完整方案的学生,以及要快速搭一个多点测温原型的从业者。整套东西器件不多,但单总线时序、定点小数换算、液晶驱动这几件最容易翻车的事,一样都没落下。
2. 总体方案设计:采集、处理、显示三段怎么切
2.1 三条技术路线摆在桌上比一比
多点测温这件事,能走的路不止一条。最传统的是热敏电阻加分压电路,再送 ADC 采样;中间路线是用模拟输出的温度传感器,比如每度对应 10mV 的那种;最后一条是数字温度传感器直接输出二进制温度值,单片机读就行。三条路在课程设计和实际原型里的差别,比想象中大。
热敏电阻便宜,但它的阻值和温度之间是非线性关系,要么查表,要么做多项式拟合,每一颗还要单独标定。更麻烦的是多点——你有几个测点就要几路模拟通道,要么加模拟多路开关,要么上多通道 ADC,硬件一下子复杂了,模拟线拉长之后噪声也跟着进来。模拟输出型传感器省掉了非线性,但多路问题依旧存在,总不能一路一个 ADC。
数字单总线方案的取舍非常清晰:它把 ADC、标定、非线性补偿全部塞进了传感器内部,单片机拿到的就是已经算好的温度值,抗干扰能力天然强于长距离模拟传输;代价是时序要求严格,微秒级的窗口一旦被中断打断,读回来就是一堆 85 或者全 0。对课程设计这种「板子不一定做得漂亮、但结果必须对」的场景,我一般优先选这条。
| 对比项 | 热敏电阻 + ADC | 模拟输出传感器 | 数字单总线传感器 |
|---|---|---|---|
| 外围器件 | 分压电阻、ADC、多路开关 | 多路开关、多路 ADC | 一只上拉电阻 |
| 多点扩展 | 每点一路模拟通道 | 每点一路模拟通道 | 可挂同一根总线 |
| 标定工作量 | 每颗单独标定 | 小 | 出厂已标定 |
| 抗干扰 | 弱,模拟线易受影响 | 中等 | 强,数字量传输 |
| 主要风险 | 非线性、精度漂移 | 通道串扰 | 时序严格、易读错 |
2.2 系统框图:三段各管什么,边界在哪
整个系统按信号流切成三段,这个划分在后面写代码时会直接影响子程序怎么拆。
采集段是两片 DS18B20,分别接在单片机的 P1.7 和 P1.6 上,各自配上拉电阻,采用外部供电而不是寄生供电。处理段是 AT89C51 最小系统:12MHz 晶振加两只 22pF 起振电容,复位电路用 10uF 电解电容配 1k 电阻,EA 引脚接高电平让程序从片内 flash 跑。显示段是一片 LM016L(和常见的 1602 引脚兼容),8 位数据口 D0–D7 接单片机的 P0 口,因为 P0 是开漏结构,外面必须挂 10k 排阻上拉;RS、R/W、EN 三个控制脚分别接 P2.0、P2.1、P2.2。
三段之间的契约很干净:采集段只负责把温度变成两个字节的数字;处理段只负责把两个字节换算成带符号的定点数再拆成字符;显示段只负责把字符按坐标写进液晶的 DDRAM。这种「谁也别管别人的事」的划法,好处是调试时可以逐段断电验证——先让液晶显示固定字符串,确认显示层没问题;再单独读传感器串口打印原始两字节;最后才把两段接起来。血泪经验是,新手常常一上来就整机联调,结果液晶不亮、温度不对、程序跑飞三个问题同时出现,根本无从下手。
2.3 从技术参数反推设计约束
给定的指标是:测温范围 -30℃ 到 +99℃,测量精度 0.0625℃,显示精度 0.1℃,LCD 循环显示,两秒间隔。这四个数字看着简单,其实每一个都在往下压设计。
0.0625℃ 这个精度是怎么来的?DS18B20 在 12 位分辨率下,温度寄存器的最低有效位权重就是 0.0625℃。也就是说,想要这个精度,配置寄存器里的 R0、R1 必须都是 1,走 12 位模式。而 12 位模式的单次转换时间最长 750ms——这个数字很关键,它决定了两路顺序采集至少要占掉 1.5 秒,那么「两秒循环一次」就不是随便定的,而是被转换时间卡出来的下限。如果强行改成 500ms 一循环,第二路读到的其实是上一次的旧值,看起来在跳动,实际是数据没刷新,这种玄学现象后面会专门讲。
再看显示精度 0.1℃。既然只显示一位小数,就没必要把 0.0625 的四位小数全展开,只需要取低字节低四位的值 t,算 625×t/1000 取整,得到小数点后那一位。这个换算后面单独一节讲,是这份方案里最容易写错的地方。
| 参数 | 给定值 | 反推出的设计约束 |
|---|---|---|
| 测温范围 | -30℃ 到 +99℃ | 需处理符号位,缓冲区要能放负号 |
| 测量精度 | 0.0625℃ | 配置寄存器置 12 位模式 |
| 转换时间 | 最长 750ms | 两路顺序采集 ≥1.5s,循环周期定 2s |
| 显示精度 | 0.1℃ | 只取一位小数,走整数运算 |
| 显示方式 | 1602 循环 | 两行各放一路,或轮流占满屏 |
2.4 两路各占一个 IO,还是共用一根总线
DS18B20 最吸引人的特性是可以在一条总线上挂很多片,靠 64 位激光 ROM 里的 48 位序列号区分。理论上两路只用一个 IO 就够了:先发 0x33 读 ROM 命令把所有器件的序列号读出来登记,之后每次操作先发 0x55 匹配 ROM,再把这 64 位序列号发出去,点名操作某一片。听起来很优雅,但代价是程序里要多维护一张序列号表,还要处理总线上多器件同时应答时的冲突。
这份方案选的是更朴素的做法:两片传感器各占一个 IO,程序里发 0xCC(跳过 ROM)直接对总线上的所有器件操作,因为一根线上只有一片,跳过 ROM 就等于点名。舍掉的是引脚——两个 IO 换来了程序结构的大幅简化,对 32 个 IO 的 AT89C51 来说这笔买卖很划算。如果哪天要扩到 8 路,引脚还够,代码只需要把 DQ 那几行按位展开成数组;真到十几路的时候,再考虑共用总线加匹配 ROM 的方案才合理。
提示:单总线挂多片时,如果总线上有一片损坏拉低总线,整个总线上的器件全部失联。各占一个 IO 的方案在故障隔离上反而更好,坏一路不影响另一路。
3. 硬件设计:最小系统、单总线与液晶接口
3.1 单片机最小系统:晶振、复位和 EA 三个不能省
最小系统是整块板子的地基,它出问题,后面所有调试都是白费。12MHz 晶振跨接在 XTAL1 和 XTAL2 之间,两端各接一只 22pF 电容到地。这两个电容不是可有可无的装饰,它们和晶振一起构成振荡回路,容值偏差太大会导致起振困难或者频率偏移。我见过把 22pF 换成 104(0.1uF)的,结果上电后晶振压根不振,程序当然一行都不跑。
复位电路是 10uF 电解电容正极接 VCC、负极接 RST,同时 RST 通过 1k 电阻接地,另外并一个按键做手动复位。上电瞬间电容相当于短路,RST 被拉到高电平,随着电容充电电流减小,RST 电压下降到低电平,完成一次上电复位。这里的时间常数要够长,51 系列要求 RST 保持高电平至少两个机器周期,10uF 配 1k 得到的毫秒级时间绰绰有余。
EA 引脚必须接高电平。这个脚的名字叫「外部访问允许」,接高时 CPU 从片内 flash 取指,接低时从外部存储器取指。板子上没有外扩 ROM,EA 悬空或者接地,程序就跑到了一个不存在的地址上,现象是「烧录成功但毫无反应」,很多人会误以为是芯片坏了。
| 引脚 | 接法 | 作用 | 常见错误 |
|---|---|---|---|
| XTAL1/XTAL2 | 12MHz 晶振 + 2×22pF 对地 | 提供时钟 | 电容容值取错导致不起振 |
| RST | 10uF 到 VCC,1k 到 GND,并按键 | 上电/手动复位 | 电容极性接反 |
| EA | 接 VCC | 从片内 flash 取指 | 悬空导致不执行程序 |
| VCC/GND | 5V 供电,每组电源脚就近去耦 | 供电 | 缺 0.1uF 去耦电容 |
3.2 DS18B20 的接法:供电方式与上拉电阻
DS18B20 只有三个脚:GND、DQ、VCC。DQ 是单总线数据脚,它同时承担供电和数据传输两种角色,这也是「寄生供电」这个名字的由来——当 VCC 接地时,器件从 DQ 线上的高电平期间「偷电」存进内部电容。寄生供电省一根线,但代价很实在:转换期间电流需求大,长线上一压降就超时,读回来的温度直接是错的。所以这份方案老老实实走外部供电,VCC 接 5V。
DQ 上必须挂上拉电阻,因为单总线是开漏结构,主机和从机都只能主动拉低,高电平靠电阻拉回来。这个电阻的取值是个权衡:阻值小,上升沿陡,时序干净,但器件拉低时的灌电流大;阻值大,功耗低,但上升沿变缓,长线时读时序容易出错。手册推荐的典型值是 4.7k。原图里画的是 1k,短线、单器件、5V 供电的条件下也能跑,仿真里更是看不出差别,但如果把线拉到几米长,1k 和 4.7k 的差别就出来了——我一般直接按 4.7k 画,省得后面改板。
注意:上拉电阻是接在 DQ 和 VCC 之间的,不是串在 DQ 上。串一个电阻进去,总线永远拉不到低电平,现象是初始化一直失败。
3.3 1602 液晶:P0 口上拉、对比度和背光
LM016L 是 2 行 16 列的字符型液晶,内部有 80 字节的 DDRAM 和一套固定的字库,单片机送进去的是 ASCII 码,它自己查表点阵。数据口 D0–D7 接 P0,控制脚 RS、R/W、EN 接 P2.0、P2.1、P2.2。P0 口在 51 系列里是开漏输出,不接上拉的话输出高电平时是悬空的,液晶收到的全是低电平,屏幕表现就是「什么都不显示」。所以 P0 上必须挂 10k 排阻,这一点在原理图上很容易漏。
VEE(第 3 脚)是对比度调节脚,接一个 10k 电位器的中间抽头,两端分别接 VCC 和 GND。调得太高,字符黑成一团;调得太低,字符淡到看不见。仿真里 LM016L 通常不需要调,但实物板上这一步非做不可,而且不同批次的液晶最佳位置不一样。
坐标定位这一块也要留意。1602 的显示地址不是连续的:第一行是 0x00–0x0F,第二行是 0x40–0x4F。写指令时要发 0x80|地址。所以第一行第 x 列的指令是 0x80|x,第二行第 x 列是 0xC0|x。原代码里写成了 0x80|(x-0x40),靠无符号数截断碰巧也能得到正确结果,但这种写法一旦换成 4 行液晶就会失效,直接写成 0xC0|x 更稳。
3.4 连线核对表与元件清单
焊接或连仿真图之前,我习惯先把连线整理成一张表逐条核对。这张表的价值在于,调试时如果某一路不工作,可以顺着表从单片机引脚一路查到器件脚,而不是盲目怀疑程序。
| 网络 | 起点 | 终点 | 备注 |
|---|---|---|---|
| 数据总线 | P0.0–P0.7 | LCD D0–D7 | P0 需 10k 排阻上拉 |
| RS | P2.0 | LCD 第 4 脚 | 高电平为数据,低为指令 |
| R/W | P2.1 | LCD 第 5 脚 | 本方案只写不读时可直接接地 |
| EN | P2.2 | LCD 第 6 脚 | 下降沿锁存 |
| 对比度 | LCD 第 3 脚 | 10k 电位器中间抽头 | 实物必备 |
| 第一路总线 | P1.7 | DS18B20(1) DQ | 4.7k 上拉到 5V |
| 第二路总线 | P1.6 | DS18B20(2) DQ | 4.7k 上拉到 5V |
| 时钟 | XTAL1/XTAL2 | 12MHz 晶振 | 各配 22pF 对地 |
主要器件就五类:AT89C51 一片、DS18B20 两片、LM016L 一片、12MHz 晶振一只、10k 排阻一只,加上若干电阻电容。器件少的好处是任何一个环节出问题,排查范围都小。
4. 软件设计:单总线时序与温度换算的两个难点
4.1 主程序结构:一个开机画面加四个子程序
主程序的骨架非常短:上电先调液晶初始化,依次送 0x38(8 位数据口、2 行显示、5×7 点阵)、0x0C(开显示、关光标)、0x01(清屏)、0x06(地址递增、画面不动),然后显示一屏欢迎画面停两秒,之后进入死循环,读第一路、显示、延时两秒,读第二路、显示、延时两秒。
把功能拆成子程序,好处在调试阶段特别明显。液晶初始化、传感器初始化、读温度、显示字符这四块各自独立,哪一块出问题就单独测哪一块:显示层可以用固定字符串验证,传感器层可以把读到的原始高低字节通过串口打出来看。等两块都单独验证过,再拼进主循环,剩下的基本只有时序配合问题。如果一开始就写成一整坨,出错时连「是没读到」还是「读到了没显示对」都分不清。
4.2 单总线时序:复位、写时隙、读时隙三件事
单总线所有的通信都建立在三种基本时隙上。复位是主机拉低总线至少 480us,然后释放,器件会在 15–60us 后拉低总线作为应答。写时隙是主机拉低总线,根据写 1 还是写 0 决定保持多久:写 1 保持很短(约 1–15us)就释放,写 0 要拉低至少 60us。读时隙是主机先拉低至少 1us 再释放,器件在 15us 内把数据放到线上,主机在拉低后 15us 左右采样。
// 12MHz 晶振下的单总线底层:复位、写一字节、读一字节 sbit DQ = P1^7; // 第一路 DS18B20 数据线 sbit DQ1 = P1^6; // 第二路 void delay_18B20(unsigned int i) { while(i--); } // 复位:拉低 480us 以上,释放后采样应答 bit Init_DS18B20(void) { bit ok; DQ = 1; delay_18B20(8); DQ = 0; // 主机拉低,进入复位脉冲 delay_18B20(80); // 保持约 640us,留足余量 DQ = 1; // 释放总线,等器件应答 delay_18B20(14); // 约 100us 后采样 ok = DQ; // 0 表示器件应答成功 delay_18B20(20); return ok; } // 写一字节:低位先出 void WriteOneChar(uchar dat) { uchar i; for (i = 0; i < 8; i++) { DQ = 0; DQ = dat & 0x01; // 写 1 时极短低电平,写 0 时保持 delay_18B20(5); // 约 40us,覆盖写 0 的窗口 DQ = 1; dat >>= 1; } } // 读一字节:主机拉低 1us 后释放,15us 内采样 uchar ReadOneChar(void) { uchar i, dat = 0; for (i = 0; i < 8; i++) { DQ = 0; dat >>= 1; DQ = 1; delay_18B20(2); // 等器件把数据放上线,再采样 if (DQ) dat |= 0x80; delay_18B20(4); // 补足整个读时隙的时长 } return dat; }这段代码里有三个参数需要在实际环境里标定,不能照抄。delay_18B20(80)对应复位脉冲的宽度,循环 80 次在 12MHz 下大约 640us,满足大于 480us 的要求,但换成 11.0592MHz 或者换编译器优化等级,这个次数就得重算。delay_18B20(5)对应写时隙的保持时间,覆盖了写 0 需要的 60us 窗口。delay_18B20(2)是读时隙里的采样延时,太早采会读到总线还没被器件拉下来的状态,太晚采会错过器件的有效数据窗口。原代码里是拉高后立即采样,在仿真里能过,实物上很容易读出全 0 或全 1,这是我建议一定要补上这行延时的原因。
4.3 温度换算:把 0.0625 做成整数运算
读回来的两个字节里,低字节的低四位是小数部分,高字节的低四位是符号位扩展。12 位分辨率下,低字节整体右移 4 位拼上高字节左移 4 位,得到的就是温度的整数部分。
真正的坑在小数。0.0625 乘以一个 4 位二进制数,结果最多是 0.9375。51 单片机没有浮点运算单元,走浮点库又慢又占空间,所以必须改成定点:低位低四位的值记作 t,小数点后第一位等于 625×t/1000。比如 t=15,625×15=9375,除以 1000 得 9,显示 0.9,和 0.9375 四舍五入前的结果一致。
// 读温度并按定点方式拆出整数与一位小数 void ReadTemp(void) { uchar a, b; char t; long tt; Init_DS18B20(); WriteOneChar(0xCC); // 跳过 ROM,总线上只有一片 WriteOneChar(0x44); // 启动温度转换 delay_18B20(100); // 等待转换完成,不可省 Init_DS18B20(); WriteOneChar(0xCC); WriteOneChar(0xBE); // 读暂存器,前两字节即温度 a = ReadOneChar(); // 低字节 b = ReadOneChar(); // 高字节 temp_value = (b << 4) | ((a & 0xF0) >> 4); // 整数部分 t = a & 0x0F; // 小数部分原始值 tt = (long)t * 625; // 放大 10000 倍 xiaoshu = tt / 1000; // 取一位小数 }这里有两个细节值得说明。(long)t * 625里的强制类型转换不能省,t 是 char,乘以 625 时如果按 8 位中间结果计算会溢出,得到完全错误的小数。另外temp_value声明成uchar只能表示 0–255,测到负温度时高字节的符号位被截掉,显示出来会是正数,这是原代码的一个隐患,改成int并单独处理符号位才完整——负温度时先取补码再按位求反加一,然后前面加个负号。
注意:转换命令 0x44 发完之后必须等待,12 位模式下最长 750ms。原代码里那个
delay_18B20(100)的循环次数要在实际环境里核对,等待不足会读到上一次的转换结果,这种现象在制冷场景里特别难发现,因为温度变化本来就慢。
4.4 显示层:数值到字符的搬运
液晶只认 ASCII 码,数字 5 送过去要变成字符 '5',做法是数字加 0x30(也就是加字符 '0')。整个显示流程是:先调 GotoXY 定位坐标,再逐个字符写进 DDRAM。温度缓冲区的组织方式是约定俗成的六到七字节:十位、个位、小数点、小数位、度符号 0xDF、字母 C,最后必须有一个 '\0' 收尾。
// 把定点数拆成可显示的字符序列 void temp_to_str(void) { TempBuffer[0] = temp_value / 10 + '0'; // 十位 TempBuffer[1] = temp_value % 10 + '0'; // 个位 TempBuffer[2] = '.'; TempBuffer[3] = xiaoshu + '0'; // 一位小数 TempBuffer[4] = 0xDF; // 度符号 TempBuffer[5] = 'C'; TempBuffer[6] = '\0'; // 结束符必须有 }最后那个结束符是血泪教训。显示函数通常写成while(*str != '\0')的循环,如果缓冲区没有结束符,循环会一直往后读,把内存里其他变量当成字符全打上屏,现象是屏幕上温度后面跟着一串乱七八糟的字符,或者第二行被莫名其妙覆盖。原代码里把结束符写到了另一个数组TempBuffer1[6],就是这个错误的典型——单看能跑,稍微改点东西就原形毕露。
5. 仿真与实物调试:五个最容易翻车的点
5.1 现象:液晶全黑或者一个字符都不显示
原因通常不在液晶本身,而在三处:P0 口没接上拉排阻,输出高电平时悬空,液晶收到的数据全被拉低;对比度电位器调到极端,字符要么黑成一片要么淡到看不见;初始化时序里没有等待液晶内部复位完成,上电后立刻发指令,芯片还没准备好。
解决顺序是固定的:先用万用表量 P0 各脚在写数据时的电压,正常应该在 0 和 5V 之间跳变,如果一直是 0V,就是上拉缺失;再慢慢转对比度电位器,找到字符最清晰的位置;最后在初始化函数开头加 15ms 以上的延时,等液晶上电稳定。仿真里 LM016L 对上拉和对比度都不敏感,所以这套检查要在实物上做才有意义。
5.2 现象:温度显示恒定为 85.0
85 是 DS18B20 上电复位的默认值,寄存器里初始就是 0x0550,换算出来正好 85℃。看到这个数字,说明单片机读到的是器件的初始值,转换命令根本没有生效。
原因有两个层面。硬件层面,DQ 上拉电阻缺失或者阻值太大,复位脉冲释放后总线拉不高,器件检测不到有效的复位信号;软件层面,发完 0x44 转换命令后等待时间不够,或者两次通信之间没有重新复位。解决办法是先用示波器或者逻辑分析仪看 DQ 线上有没有完整的复位低脉冲和随后的应答低脉冲,如果没有应答,问题在硬件;有应答但读数恒为 85,就往等待时间上加。
5.3 现象:两路温度永远一模一样
两路读数完全相同,而且跟着同一个热源变化,基本可以断定程序里两路用的是同一个 DQ 引脚。原代码里定义了DQ和DQ1两个位变量,但读第二路时如果忘了把底层函数里的DQ换成DQ1,两次读的就是同一片传感器。
解决方式是给每一路单独写一套底层函数,或者在底层函数里加一个引脚选择参数。前者代码冗余但清晰,后者省空间但容易传错参数。我一般选前者,因为课程设计的代码量本来就不大,清晰比省字节重要得多。
5.4 现象:小数位一直是 0 或者乱跳
小数位恒为 0,先查配置寄存器有没有真的被写成 12 位模式。上电默认就是 12 位,但如果程序里发过写配置的命令而参数算错,可能被改成 9 位,此时低四位全是 0,小数自然一直为 0。小数位乱跳,通常是整数部分和小数部分用了不同的数据源,比如整数取的是上一次的缓存,小数取的是这一次的新值。
排查方法是把读到的原始高低两个字节先不做任何换算,直接通过串口或者液晶显示成十六进制。原始值稳定,问题在换算;原始值本身就在跳,问题在时序或者等待时间。
5.5 现象:仿真能跑,焊到板子上就不行
Proteus 里的器件模型是理想化的,时序容差比实物宽得多,很多在仿真里「刚好能过」的写法到了实物上就崩。最常见的三处差异:仿真不关心上拉电阻的阻值,实物上 1k 和 4.7k 的上升沿差别明显;仿真里晶振频率是精确的 12MHz,实物晶振有偏差,靠循环次数凑出来的延时全部漂移;仿真没有电源噪声,实物上电机、继电器一动作,单总线就读错。
对策是把仿真当功能验证,不当电气验证。所有延时函数在实物上用示波器标一遍,单总线加 4.7k 上拉,电源脚就近加 0.1uF 去耦,传感器线尽量短并且远离干扰源。这几条做到了,仿真和实物的一致性能到九成以上。
6. 验收与答辩:怎么证明这套系统真的能跑
答辩现场最怕的不是被问到不会的,而是被要求现场演示时系统不动。所以验收这件事要提前设计,不能等到答辩前一天晚上才想起来。
我通常按四层来验。第一层是静态检查,断电状态下用万用表蜂鸣档顺着连线表把每一根线量一遍,重点量电源和地有没有短路、EA 有没有接高、P0 排阻有没有焊好。第二层是分段上电,先只焊最小系统,烧一个让某个 IO 周期性翻转的测试程序,用万用表或 LED 看有没有翻转,确认单片机能跑;再焊液晶,烧固定字符串显示程序;最后才接传感器。第三层是功能验证,用一杯热水和一杯冰水混合物做两个温度基准点,冰水混合物在常压下稳定在 0℃ 附近,热水自然冷却过程中可以观察读数是否单调下降,两路同时插进不同温度的水里,看显示是否跟随。第四层是边界验证,把传感器放到接近 -30℃ 和 +99℃ 的环境里各测一次,看符号位和数值有没有溢出。
| 验收项 | 方法 | 合格判据 |
|---|---|---|
| 最小系统 | 烧 IO 翻转程序 | 引脚电平周期性变化 |
| 显示层 | 显示固定字符串 | 两行 16 字符完整无乱码 |
| 单路采集 | 冰水混合物 / 室温对比 | 读数在 0℃ 和室温附近 |
| 双路独立 | 两探头插入不同水温 | 两行数值不同且各自跟随 |
| 循环显示 | 秒表计时 | 每两秒切换一次,不丢帧 |
| 边界 | 低温与高温环境 | 负值带负号,无溢出跳变 |
答辩时被问得最多的是三个问题:为什么不用热敏电阻、为什么循环周期是两秒、精度 0.0625 是怎么保证的。前两个在第 2 章里已经有完整答案,第三个要注意别说错——0.0625℃ 是传感器的分辨率,不是系统的绝对精度,传感器本身的精度在 -10℃ 到 +85℃ 范围内是 ±0.5℃,答辩时说清这两个概念的区别,比背参数更能体现你真的读懂了手册。
还有一个容易被忽略的加分项:把调试过程中遇到的问题整理成一页纸带过去。比如「曾经显示恒定 85℃,原因是上拉电阻缺失」,这种记录比任何漂亮的框图都有说服力,因为它证明了这套系统是你自己一点点调出来的,不是照抄的。
从那以后我每次做带单总线的板子,都会在上电前先用示波器看一眼复位脉冲和应答脉冲这对「握手」,确认时序对了再往下写代码——这一步花五分钟,能省掉后面好几个小时的玄学排查。希望帮到你。
本文还有配套的精品资源,点击获取