
简介这是一份面向电子信息、自动化及相关专业学生的传感器课程大作业完整报告围绕无线温度数据采集系统展开可用于课程作业参考、实验报告撰写与温控报警类小项目设计借鉴。压缩包内共1个doc文档约561KB正文按目录组织为温控设计思路、硬件部分与参考文献三大板块含设计框图、总电路图、报警与显示模块电路图及PCB板示意图硬件上给出蜂鸣器驱动报警与LCD1602显示的具体选型理由和方案对比并说明温度采集、射频传输、监控节点显示与超限报警的完整链路。软件与器件部分介绍了DS18B20数字智能温度传感器的精度范围、响应速度与小型化特点以及数据采集、处理和显示的实现思路末尾附有传感器与检测技术、电子技术基础、单片机原理等参考文献。目前已有175人学习适合需要完整报告框架、图文电路说明与选型论证参考的读者查阅。1. 从一份传感器大作业报告说起DS18B20 无线测温到底难在哪传感器课程设计做到最后一周最常见的场面是液晶上稳定显示 85.0℃换了三根 DS18B20 结果一样报告里的框图画得漂漂亮亮实物却卡在这一步。这份《传感器大作业报告完整版》给出的正是典型的分布式测温方案——前端用 DS18B20 采温通过射频把数据送到监控节点监控节点用 LCD1602 实时显示并配一组 NPN 三极管驱动的蜂鸣器和报警灯。它瞄准的场景很具体电气机箱、配电柜、粮仓、温室这类不方便铺信号线、人又不常驻的位置。选它做课程设计的人通常要同时应付单总线时序、射频收发、液晶驱动和 PCB 打样四件事。下面不按报告章节顺序复述而是把这四件事拆成能直接复现的步骤顺带把报告里一笔带过的参数和坑补上。2. DS18B20 单总线时序与温度换算报告里没写透的部分报告只写了温度传感器选择 DS18B20但真正决定你能不能读到数的是它那套微秒级的单总线协议。这一章先把选型理由讲清楚再落到时序代码和温度换算。2.1 选型为什么这类课题大多落在 DS18B20 上测温元件的选择面其实很宽课程设计里常见的几类对比如下差别主要集中在要不要额外放大电路和输出是模拟还是数字。类型输出形式典型精度接口复杂度单点成本适合场景NTC 热敏电阻电阻变化±1℃ 需标定需分压ADC查表极低成本敏感、精度要求低PT100 铂电阻电阻变化±0.1℃需恒流源仪表放大ADC中高工业计量、宽温区热电偶毫伏级电压±1~2℃需冷端补偿高增益放大中高温炉、窑炉DS18B20数字量单总线±0.5℃(-10~85℃)一根数据线直连 MCU低多点分布式、远距离走线红外测温数字/模拟±1℃ 视发射率需考虑视场与发射率中非接触、移动目标选 DS18B20 的核心理由是数字化和可挂载。它把 ADC、基准、标定全部封在芯片里MCU 端只需要一个 GPIO 加一个 4.7kΩ 上拉电阻就能在一条线上挂 8 个甚至更多探头每个探头有出厂唯一的 64 位 ROM 地址。报告里那套温度采集 射频上传的架构本质上就是靠这个特性把布线成本压下来的。代价是它的转换速度慢12 位分辨率下单次转换要 750ms而且协议对延时的容差很小。提示DS18B20 有三个封装版本TO-92 直插最便宜但引线是刚性针脚防水探头版内部已灌封并带线缆适合机箱外部测温贴片 SOIC-8 适合直接焊在 PCB 上。做机箱测温建议选防水探头版避免探头本体受潮导致读数漂移。2.2 复位脉冲、存在脉冲与读写时隙单总线没有独立时钟线主机和从机全靠约定的时长区分 0 和 1。以 STM32F103 为例系统主频 72MHz 时用 DWT 或定时器做一个微秒级延时是第一步下面这段是最小可用的时序层。// ds18b20.c —— 单总线底层时序STM32F103GPIO 推挽输出 上拉输入切换 #include stm32f10x.h #define DQ_HIGH() do{ GPIOB-CRL ~(0xF 20); GPIOB-CRL | (0x8 20); \ GPIOB-BSRR GPIO_Pin_5; }while(0) // 上拉输入 #define DQ_LOW() do{ GPIOB-CRL ~(0xF 20); GPIOB-CRL | (0x3 20); \ GPIOB-BRR GPIO_Pin_5; }while(0) // 推挽输出低 #define DQ_READ() ((GPIOB-IDR GPIO_Pin_5) ? 1 : 0) static void delay_us(uint32_t n) // 72MHz 下约 1us 粒度 { uint32_t i; for (i 0; i n * 8; i) __NOP(); } /* 复位拉低至少 480us再释放等待从机 60~240us 的存在脉冲 */ uint8_t DS_Reset(void) { uint8_t presence; DQ_LOW(); delay_us(500); DQ_HIGH(); delay_us(70); presence !DQ_READ(); // 读到低电平说明有器件应答 delay_us(430); // 补齐整个时隙等总线回高 return presence; // 1 检测到器件0 无应答 } /* 写一位写 1 拉低 1~15us 后释放写 0 拉低 60us 以上 */ void DS_WriteBit(uint8_t bit) { DQ_LOW(); if (bit) { delay_us(5); DQ_HIGH(); delay_us(60); } else { delay_us(60); DQ_HIGH(); delay_us(5); } } /* 读一位主机拉低 1us 后释放在 15us 内采样从机拉低的时长 */ uint8_t DS_ReadBit(void) { uint8_t bit; DQ_LOW(); delay_us(2); DQ_HIGH(); delay_us(10); bit DQ_READ(); delay_us(50); return bit; } void DS_WriteByte(uint8_t dat) { uint8_t i; for (i 0; i 8; i) { DS_WriteBit(dat 0x01); dat 1; } } uint8_t DS_ReadByte(void) { uint8_t i, dat 0; for (i 0; i 8; i) { dat 1; if (DS_ReadBit()) dat | 0x80; } return dat; }逻辑说明DS_Reset里 500us 的拉低是复位脉冲从机检测到后会拉低总线 60~240us 作为存在脉冲主机在第 70us 左右采样采样点必须落在存在脉冲窗口内。DS_WriteBit的关键是写 1 的拉低时间不能超过 15us否则从机会把它当成写 0写 0 则要持续 60us 以上。DS_ReadBit的采样点放在释放总线后 10~15us 的窗口内从机此时送出的数据保持 15us 左右。这几处延时如果被中断打断读数就会随机出错所以一般在读写期间关掉全局中断。参数说明delay_us的系数随主频变化用示波器量一次 500us 复位脉冲即可校准上拉电阻取 4.7kΩ线长超过 1 米时可降到 2.2kΩ 提高上升沿速度但静态电流会增加到 1.5mA 以上功耗敏感场合要权衡。2.3 温度寄存器格式与分辨率配置DS18B20 上电默认是 12 位分辨率温度寄存器是 16 位带符号数低 4 位是小数部分LSB 权重 0.0625℃。配置寄存器的 bit6、bit5 决定分辨率对应的转换时间和 LSB 如下。bit6:bit5分辨率LSB 权重最大转换时间0:09 位0.5℃93.75ms0:110 位0.25℃187.5ms1:011 位0.125℃375ms1:112 位0.0625℃750ms/* 单点读取跳过 ROM 只适用于总线上只有一个探头 */ float DS_ReadTemp(void) { uint8_t tl, th; int16_t raw; DS_Reset(); DS_WriteByte(0xCC); // SKIP ROM DS_WriteByte(0x44); // CONVERT T发起一次转换 HAL_Delay(750); // 12 位分辨率下必须等够 DS_Reset(); DS_WriteByte(0xCC); DS_WriteByte(0xBE); // READ SCRATCHPAD tl DS_ReadByte(); th DS_ReadByte(); raw (int16_t)((th 8) | tl); return raw * 0.0625f; // 负数会自然取到DS18B20 用补码 }逻辑说明0xCC 是跳过 ROM 命令只在总线上仅挂一个探头时使用多探头时必须先发 0x55 加 8 字节 ROM 地址定位。0x44 发起转换后主机可以去做别的事750ms 后再回来读。0xBE 读出的前两字节就是温度值第三、四字节是高温和低温报警阈值最后两字节分别是配置寄存器和 CRC。参数说明如果只做机箱温度监控9 位分辨率0.5℃、93.75ms足够能把节点功耗降下来需要显示到小数点后一位时用 11 位0.125℃报告里渲染的 0.0625℃ 精度是理论 LSB实际误差由器件本身的 ±0.5℃ 决定别把两者混为一谈。2.4 多点挂载与 85℃ 假值上电瞬间读到的 85.0℃ 是 DS18B20 的转换寄存器默认值不是故障而是你还没让它转换就先把寄存器读出来了。解决办法是在初始化完成后先发一次 0x44 并等够时间再进入正常轮询。如果一直读到 85℃优先查两件事总线有没有 4.7kΩ 上拉、HAL_Delay(750)是否被漏掉。多探头场景要改用 ROM 搜索流程DS_Reset()→ 写 0x33READ ROM只适用单探头或 0xF0SEARCH ROM多探头→ 逐位读取从机响应的 64 位地址用分歧点算法遍历整棵树。常见做法是第一次上电把扫描到的 ROM 地址存进 Flash之后直接用 0x55 地址直读省掉每次搜索的时间。3. 无线温度采集节点与监控端链路实现报告只画了温度传感器—最小系统—射频—显示的框图中间的数据怎么组织、怎么保证不串码才是实物能不能跑起来的关键。这一章按节点分工、帧格式、显示、报警四步走。3.1 节点分工与射频模块选型系统拆成两个角色采集节点负责测温并把数据发出去监控节点负责接收、显示和报警。射频部分的常见选型如下。模块频段空中速率标称距离接口备注433MHz 超再生433.92MHz低几十米单数据脚成本最低抗干扰差需软件编码nRF24L012.4GHz250k~2Mbps空旷 100mSPI自带地址与 CRC最省事SI4432433MHz可调数百米SPI灵敏度高配置寄存器多LoRa 模块470/868MHz0.3~37.5kbps公里级UART/SPI适合更大范围成本高课程设计里用 nRF24L01 的性价比最高它把地址过滤、CRC 校验、自动重传都做在硬件里MCU 端只需要操作 SPI。如果老师指定了 433MHz就得自己在软件层加同步字和校验。3.2 数据帧格式与 CRC8 校验空中传的数据包一定要带校验否则接收端偶发误码会直接把温度显示成离谱数值。推荐帧结构如下。偏移长度字段说明01帧头 0xA5用于接收端字节对齐11节点 ID0x01~0xFE支持多节点区分22温度原始值int16单位 0.0625℃小端41报警标志bit0 高温、bit1 低温、bit2 传感器故障52电池电压mV可选71CRC8前 7 字节的多项式 0x07 校验/* 发送端打包温度放大成整数再发避免浮点跨平台对齐问题 */ uint8_t crc8(const uint8_t *buf, uint8_t len) { uint8_t crc 0x00, i, b; for (i 0; i len; i) { crc ^ buf[i]; for (b 0; b 8; b) crc (crc 0x80) ? (uint8_t)((crc 1) ^ 0x07) : (uint8_t)(crc 1); } return crc; } void BuildFrame(uint8_t *f, uint8_t node, float temp, uint8_t flag) { int16_t raw (int16_t)(temp / 0.0625f); // 转成 DS18B20 原始刻度量纲 f[0] 0xA5; f[1] node; f[2] (uint8_t)(raw 0xFF); f[3] (uint8_t)((raw 8) 0xFF); f[4] flag; f[5] 0x00; // 电压占位 f[6] 0x00; f[7] crc8(f, 7); // 只校验前 7 字节 }逻辑说明温度不做浮点传输而是换算回 0.0625℃ 的整数刻度接收端乘 0.0625f 还原即可这样两端不存在字节序和浮点格式差异。CRC8 用多项式 0x07覆盖除校验位以外的全部字段接收端算出不一致就整帧丢弃不更新显示。参数说明帧头 0xA5 要选得足够有辨识度别用 0x00 或 0xFF 这种容易被噪声凑出来的值如果节点数多可以在帧尾再加一个序号用于丢包统计nRF24L01 本身带 16 位 CRC但由于还可能有应用层拼帧错误双保险不吃亏。3.3 监控端接收与 LCD1602 显示接收端流程是收到中断 → 收包 → 校验 → 更新缓存 → 刷新液晶。校验失败时不改缓存保持上一次有效值同时在液晶上打一个错误计数。/* 监控节点主循环片段 */ uint8_t frame[8]; float last_temp 0.0f; uint8_t err_cnt 0; void Monitor_Loop(void) { if (NRF_DataReady()) { NRF_ReadPayload(frame, 8); if (frame[0] 0xA5 crc8(frame, 7) frame[7]) { int16_t raw (int16_t)((frame[3] 8) | frame[2]); last_temp raw * 0.0625f; } else { err_cnt; // 坏帧只计数不覆盖 last_temp } } LCD_SetCursor(0, 0); LCD_Printf(TEMP:%5.1f C , last_temp); LCD_SetCursor(1, 0); LCD_Printf(ERR:%3d , err_cnt); Alarm_Check(last_temp); }逻辑说明这段循环放在 main 里非阻塞执行射频模块用中断脚触发读取避免轮询丢包。液晶每轮全刷 16 个字符并补空格防止上一次的长数字残留成鬼影。Alarm_Check单独抽出来方便把阈值改成从按键或串口配置。参数说明LCD1602 走 4 位模式只需 D4~D7 四根数据线加 RS、RW、E 三根控制线RW 可以直接接地恒为写模式省一根线对比度引脚 V0 接 10kΩ 电位器中间抽头背光 A/K 串 100Ω 限流到 5V串 220Ω 会偏暗。3.4 报警阈值与回差设置报告只写了超出一定范围发出报警实际做出来最容易被吐槽的是蜂鸣器在阈值附近疯狂启停。原因是温度本身有 ±0.5℃ 波动阈值又设成单点。正确做法是加回差滞回。参数建议值说明高温阈值45.0℃按被测设备允许上限留 5℃ 余量高温解除值42.0℃比阈值低 3℃即回差 3℃低温阈值5.0℃机箱防结露下限低温解除值8.0℃回差同为 3℃报警确认次数连续 3 次过滤单次误码造成的假报警报警确认次数用计数器实现连续 N 次超限才置报警位连续 N 次回到安全区才清零这一段逻辑比阈值本身更影响实物体验。4. 报警与显示模块的硬件落地三极管驱动、PCB 与电源排错报告里报警模块只写了一句话——使用一个 NPN 型三极管作为蜂鸣器的驱动。这一章把这句话拆成能算的参数再补上 PCB 布局和上电排错的顺序。4.1 蜂鸣器驱动三极管的参数计算MCU 的 GPIO 一般只能拉 8~20mA而 5V 有源蜂鸣器工作电流常在 20~40mA直连会把 IO 拉垮甚至损坏。用 NPN 管做低边开关是标准做法型号上 2N3904、S8050、MMBT3904 都能用S8050 的集电极电流余量更大。计算过程设蜂鸣器工作电流 Ic 30mAS8050 的 hFE 取 100保守值手册典型 120~400则基极电流 Ib ≥ Ic / hFE 0.3mA。为保证深度饱和实际取 3~5 倍余量即 Ib ≈ 1.5mA。GPIO 高电平 3.3VVbe 取 0.7V则 Rb (3.3 - 0.7) / 1.5mA ≈ 1.7kΩ取标称值 1.5kΩ 或 2.2kΩ。元件取值作用驱动管 Q1S8050NPN低边开关集电极接蜂鸣器负极基极电阻 Rb1.5kΩ限制基极电流防止 IO 过流基极下拉电阻10kΩ防止 MCU 复位期间悬空误导通续流二极管1N4148并在蜂鸣器两端泄放感性反峰报警 LED 限流470Ω3.3V 供电下约 5mA亮度足够蜂鸣器5V 有源有源自带振荡给电即响接法蜂鸣器正极接 5V负极接三极管集电极发射极接地基极经 Rb 接 GPIO。LED 与 1kΩ 电阻串在另一路 GPIO 上由软件同步闪烁这就是报告里提到的控制蜂鸣器报警的同时控制报警灯闪烁。注意软件上别用GPIO_SetBits之后立刻GPIO_ResetBits做滴滴声中断里频繁翻转会拖慢主循环。用定时器中断按 500ms 周期翻转标志位主循环里根据标志控制引脚更清晰。4.2 LCD1602 的接线、对比度与初始化顺序LCD1602 上电后必须先走一遍初始化序列否则会出现背光亮但无字符。标准流程是上电等待 15ms 以上然后依次发送 0x33、0x32切到 4 位模式再配置显示模式 0x28、开显示 0x0C、清屏 0x01、设置输入模式 0x06。顺序反了就会出现半屏黑块。显示内容上报告明确要实时显示机箱环境温度和风扇转速。转速这类计数型数据建议单独占一行用整数显示避免小数位跳动导致整行重刷。4.3 PCB 布局单总线走线、晶振与射频净空打样前有几个位置值得多花十分钟DS18B20 的数据线尽量远离晶振和 PWM 走线旁边加 4.7kΩ 上拉射频模块的天线区域通常是 PCB 天线或外置天线座下方所有层都不铺铜净空区至少 5mm否则距离会掉一半每个芯片电源脚配 0.1uF 去耦电容紧贴引脚放置模拟地和数字地单点汇接在电源入口。如果探头要引出机箱数据线超过 1 米时建议用屏蔽线并把屏蔽层单端接地同时把上拉电阻改到 2.2kΩ。线更长的话DS18B20 的分布电容会把上升沿拖慢示波器上看就是波形从方波变成圆弧这时候除了减小上拉还要降低总线上的探头数量。4.4 上电不亮、读数异常、报警乱响的排查顺序硬件问题靠猜效率很低按现象分表查会快很多。现象优先怀疑验证方法液晶背光亮但无字符V0 对比度电压、初始化顺序调电位器看是否出现黑块逻辑分析仪抓 E 脚脉冲数读数恒为 85.0℃未发 0x44 或延时不足单步调试看是否执行转换命令读数恒为 0.0℃上拉电阻缺失、DQ 脚方向切换写错万用表量总线空闲时是否被拉到 3.3V读数随机跳变延时被中断打断、线太长读写期间关中断后复测缩短探头引线蜂鸣器一直响基极下拉缺失、GPIO 复位期间悬空加 10kΩ 下拉后复测射频丢包严重天线净空不足、供电纹波大拉开距离测 RSSI示波器看 3.3V 纹波排查时按先电源、再时钟、后信号的顺序走先量 3.3V 和 5V 是否正常且纹波小于 50mV再确认晶振起振最后才用逻辑分析仪看总线时序。5. 进阶用逻辑分析仪和上位机把报告变成可验证的系统报告写完不等于系统做完答辩现场最容易被问的是你怎么证明这个温度是准的。这一章给三个能当场演示的验证手段。5.1 用逻辑分析仪抓单总线时序DS18B20 的时序看代码只能看个大概接上 8 通道逻辑分析仪采样率设 24MHz 以上1us 时隙才抓得清抓 DQ 脚重点看三处复位脉冲宽度是否大于 480us、存在脉冲是否落在 60~240us、读时隙的采样点是否在 15us 窗口内。如果波形上出现晶振般的毛刺多半是上拉电阻偏大或走线过长。抓一次 12 位转换的完整过程大约 750ms采样深度要开到 20M 点以上否则尾部会被截断。5.2 从串口到上位机把数据变成曲线监控节点额外引一路 UART按固定格式输出主机端用 Python 画实时曲线比盯着液晶看有说服力得多。# plot_temp.py —— 读取串口温度并实时绘图帧格式 TEMP:23.5\r\n import serial, matplotlib.pyplot as plt, matplotlib.animation as anim ser serial.Serial(COM3, 115200, timeout0.5) # 按实际端口修改 xs, ys [], [] def update(_): line ser.readline().decode(ascii, ignore).strip() if line.startswith(TEMP:): xs.append(len(xs)) ys.append(float(line[5:])) # 截掉前缀转浮点 xs, ys xs[-200:], ys[-200:] # 只保留最近 200 点 plt.cla() plt.plot(xs, ys, lw1) plt.ylim(0, 60) # 与报警阈值区间对齐 plt.title(temperature / sample index) ani anim.FuncAnimation(plt.gcf(), update, interval200) plt.show()逻辑说明timeout0.5保证读不到数据时不会卡死xs, ys做滑动窗口防止长时间运行时内存持续增长ylim设成和报警阈值一致的量程报警点在图上会非常直观。参数说明波特率必须与 MCU 端一致115200 下每帧 10 字节左右100ms 一次完全够用如果现场干扰大把绘图间隔拉长到 500ms 并加滑动平均窗口 5 点曲线会平滑很多。5.3 用 Modbus 或 MQTT 把数据接到已有系统如果答辩要求能和现有平台对接两条路比较常见。一条是把监控节点做成 Modbus RTU 从机用 ModbusPoll 这类工具直接读保持寄存器温度和报警状态各占一个 16 位寄存器温度放大 10 倍传整数另一条是在监控节点上加一路 Wi-Fi 模组按 MQTT 把 JSON 发到云平台用 PlatformIO 开发时可以直接引用现成的 PubSubClient 库把BuildFrame里那几个字段填进 payload 即可。两条路都不改前端采集只在监控节点侧扩一个转发任务。5.4 精度与响应时间的实测方法最后补一个能写进报告测试章节的做法把探头和一支已校准的温度计或标准水银温度计一起放进恒温水浴从 20℃ 升到 50℃每 5℃ 稳定 3 分钟后记录一次读数和标准值算最大偏差响应时间则用探头从室温快速插入 50℃ 水浴用 5.2 的曲线记录从跳变到达到稳态值 63% 所需的时间。9 位分辨率下这个时间通常在 1~2 秒12 位下 3 秒以上——这组数据比任何理论精度说明都更能说明你选的配置合不合理。本文还有配套的精品资源点击获取