news 2026/9/9 22:14:53

基于STM32的DS18B20温度报警系统设计与实现

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
基于STM32的DS18B20温度报警系统设计与实现

简介:面向嵌入式课程设计场景,这套资料以STM32F401微控制器和DS18B20数字温度传感器为核心,提供完整的温度报警系统方案,包含Keil5工程源码、Proteus仿真电路图和配套设计报告,适合高校相关专业学生作为课程设计、课设答辩或毕业设计参考。系统支持实时温度采集、液晶显示、手动设置上下限预警参数、超限LED指示灯报警,并可在LCD上显示题目、姓名、学号等定制信息,同时预警范围覆盖-100至100摄氏度,满足常规环境监测要求。压缩包内共190个文件,整体约9.27MB,以C/H源码、Proteus仿真文件、编译生成的hex/axf文件以及Word文档设计报告为主,类型区分明确,便于查看逻辑、运行仿真和继续修改。目前已有12656人学习使用,说明这套方案在同类嵌入式课程设计中具有较高人气与参考价值。通过源码阅读和仿真复现,能够快速掌握STM32外设配置、DS18B20单总线驱动时序、按键交互和显示逻辑,适合在此基础上扩展风扇控制、声光报警或其他物联网功能。 “基于STM32的温度报警设计”是我见过被最多学生拿来当年终课设或者毕业设计的题目之一。说它简单,是因为功能很清晰:读个温度、设个阈值、超了就叫。说它不简单,是因为实际调试中总会在传感器时序、报警抖动、下载失败这些地方翻车。这篇文章我打算把整个方案从头到尾拆一遍,从硬件选型到软件状态机,再到那些网上教程不会明说的坑,尽量让第一次做毕设的人也能照着落地。在开始看代码之前,正好用一句话点出核心:这个项目的本质不是做一个温度计,而是做一个稳定的事件响应系统。

1. 项目整体思路与方案选型

1.1 功能拆解:别急着写代码,先画状态机

很多人拿到题目就直接打开STM32CubeMX配置引脚,但这样很容易漏需求。温度报警看着只涉及“读取温度”和“超过阈值报警”,实际上系统至少有这几个状态:正常态、报警态、恢复态,还可以再加上错误态。

什么条件触发报警?温度大于等于阈值。什么条件取消报警?注意不是“回落到阈值以下”就立刻取消,否则蜂鸣器或继电器会在临界点来回跳。我建议加滞回区间,比如报警阈值是60摄氏度,那么等温度回落到57摄氏度再解除报警,这3摄氏度的差值就是回差。为什么需要回差?因为温度本身有波动,传感器读数也有噪声,如果没有滞回,系统会不停地在报警和正常之间切换。

还有一个容易被忽略的点:当传感器故障、读不到数据时,系统不能当作正常温度处理。如果这是一台温控柜,传感器断线但报警不响,可能造成设备烧毁。所以错误状态也要触发报警,至少要有明显的异常指示。状态机先想清楚,后面写代码就是水到渠成的事。

1.2 为什么选STM32:控制器的取舍

做这个项目,很多初学者会问:用51单片机不香吗?确实能实现,尤其只接一个DS18B20,51绰绰有余。但我还是建议用STM32来做,理由有三点。

第一,STM32主频高、外设丰富,后续要扩展OLED显示、ESP8266联网、上位机串口监控,不需要换平台。第二,HAL库配合STM32CubeMX能快速生成工程,把精力放在业务逻辑上,这也是目前企业里常见的工作方式。第三,从毕业设计或者项目答辩角度看,用STM32可展示的东西更多:DMA、定时器输入捕获、FreeRTOS,都是现成的扩展方向。

如果只是追求最低成本、最简单,51完全可以;但如果想学到东西,STM32的知识复利明显更高。具体型号我推荐STM32F103C8T6,淘宝十几块钱的小系统板,资料多,教程多,遇到问题几乎都能搜到答案。

1.3 温度传感器选型:DS18B20、NTC、LM75怎么挑

温度传感器常见的有三种,各有优劣:

传感器通信方式典型精度成本优点缺点
DS18B20单总线±0.5℃(-10~85℃)接线少、数字输出、可直接读温度时序要求严格,单总线容易受干扰
NTC热敏电阻模拟电压取决于校准很低电路简单,成本极低需要ADC、查表,温漂明显
LM75I2C±3℃中低总线稳定,可并联多个精度一般,需要I2C协议调试

我做这个项目一般推荐DS18B20,原因很现实:只有一根数据线,代码例程多,调试相对容易。但要注意,它必须外接一个4.7kΩ左右的上拉电阻到VCC,否则数据线没法正常工作。而且“单总线”意味着所有通信都挤在一根线上,时序要求苛刻,后面软件部分我会专门讲。

2. 硬件电路设计与搭建

2.1 最小系统与引脚规划

这里以最常见的STM32F103C8T6核心板为例,整板不用自己画最小系统,只需要考虑外设连接。我的引脚规划如下:DS18B20数据引脚接PA0,配置成开漏输出模式;蜂鸣器控制引脚接PB1;状态指示LED接PC13;PA9和PA10作为串口1的TX、RX,用来打印调试信息。

重点强调一下GPIO模式:DS18B20的GPIO不要用推挽输出,更不要用普通输入模式。单总线协议要求主机在读取时释放总线,让外部上拉电阻把电平拉高,你用开漏输出模式最省心。如果配成推挽输出,操作不当很容易导致引脚和传感器输出打架,轻则读不到数据,重则损坏端口。CubeMX里把PA0选成GPIO_Output,然后设置为Output Open Drain,再开启内部上拉或者外部加4.7kΩ上拉,这样读和写都能搞定。

2.2 报警执行电路:蜂鸣器、继电器、LED

报警执行机构可以根据场景选蜂鸣器、LED,或者继电器。先说蜂鸣器,很多人直接把IO口接蜂鸣器正极,结果发现声音很小,或者IO口烧了。原因很简单:无源蜂鸣器工作电流往往超过30mA,STM32的GPIO输出能力有限,而且蜂鸣器是感性元件,关断瞬间会产生反向电动势。

正确做法是用一片NPN三极管做开关。GPIO经过1kΩ电阻接到三极管基极,发射极接地,集电极接蜂鸣器负极,蜂鸣器正极接VCC。IO输出高电平,三极管导通,蜂鸣器响;IO输出低电平,蜂鸣器停。如果控制的是继电器,继电器线圈两端必须并联一个反向续流二极管,比如1N4148,否则线圈断电瞬间的感应电压很容易击穿三极管或单片机的引脚。LED就简单了,串一个330Ω或1kΩ电阻到地。

2.3 电源与去耦:小细节影响大稳定

整个系统可以用USB的5V供电,核心板上的AMS1117稳压到3.3V。DS18B20的工作电压范围是3.0V到5.5V,建议直接使用和单片机一致的3.3V,避免电平不匹配。这里有一个容易被忽略的点:DS18B20的数据线在3.3V供电时,上拉电阻也可以接3.3V,不要一股脑接5V。

另外,去耦电容特别重要。我会在MCU的VCC引脚旁边放一个100nF陶瓷电容,电源入口放一个10μF电解电容并联100nF。别小看这几毛钱的电容,驱动继电器或蜂鸣器这种开关负载时,电源瞬间跌落会导致DS18B20时序错乱,温度数据飘忽不定。加上去耦电容之后,很多莫名其妙的故障会直接消失。

3. 软件设计与核心代码实现

3.1 开发环境配置:HAL库还是标准库

现在STM32开发主流方案有三种:标准外设库、HAL库配合STM32CubeMX、LL库。对于这个项目,我最推荐STM32CubeMX生成工程加HAL库,理由是图形化配置时钟和外设,代码自动生成,以后加串口、I2C都方便。

CubeMX配置大致是:选择芯片STM32F103C8Tx,RCC设为HSE外部晶振,SYS的Debug设为Serial Wire。这一步非常重要,如果Debug不选Serial Wire,代码下载一次之后,第二次就可能报找不到目标设备。然后配置USART1的TX是PA9、RX是PA10,PA0设为开漏输出接DS18B20,PB1设为推挽输出接蜂鸣器,PC13设为输出接LED。时钟树直接选72MHz。生成MDK-ARM工程,用Keil打开。

如果你习惯VSCode加EIDE插件或者PlatformIO,也不是不行,但新手用Keil更稳,至少报错定位更直接。工程生成之后,第一件事是编译一次确认环境没问题,再开始写业务代码。

3.2 DS18B20驱动:核心时序和代码

DS18B20通信过程,就是一个主机对从机的严格时序控制,任何一个延时不对,都可能读回0或者85。关键步骤我记成四步:

  1. 复位:主机拉低总线480μs以上,然后释放,等待从机拉低60到240μs;如果检测到存在脉冲,说明传感器在线。
  2. 跳过ROM:发送0xCC。总线上只有一个设备时不需要匹配64位序列号。
  3. 启动温度转换:发送0x44。转换时间最长750ms,如果设置为12位分辨率。
  4. 再复位、跳过ROM、发送0xBE读暂存器,连续读9个字节,前两个字节是温度低字节和高字节。

关键的复位和读写时序代码看起来是这样:

static uint8_t DS18B20_Reset(void) { uint8_t presence; DQ_LOW(); delay_us(500); DQ_HIGH(); delay_us(60); presence = DQ_READ(); delay_us(420); return presence; } static void DS18B20_WriteByte(uint8_t data) { for (int i = 0; i < 8; i++) { DQ_LOW(); delay_us(2); if (data & 0x01) DQ_HIGH(); else DQ_LOW(); delay_us(60); DQ_HIGH(); data >>= 1; } } static uint8_t DS18B20_ReadByte(void) { uint8_t data = 0; for (int i = 0; i < 8; i++) { data >>= 1; DQ_LOW(); delay_us(2); DQ_HIGH(); delay_us(5); if (DQ_READ()) data |= 0x80; delay_us(60); } return data; }

这段代码里的delay_us是软件延时,不能用HAL_Delay,因为HAL_Delay最小单位是1ms,而单总线时序要求的是微秒级。我习惯用SysTick写一个delay_us,或者直接用一个基本定时器做微秒延时。软件延时会受编译器优化等级影响,如果读数据不对,先检查这段延时是否校准。

3.3 报警状态机:不要用if堆业务

很多教程里的写法是:

if (temp > 60) buzzer_on(); else buzzer_off();

这样做在阈值附近大概率会产生继电器弹跳一样的“哒哒声”。用状态机会清晰很多,扩展错误处理也方便:

typedef enum { STATE_NORMAL, STATE_ALARM, STATE_ERROR } SysState_t; SysState_t state = STATE_NORMAL; float temp = 0; while (1) { if (DS18B20_ReadTemp(&temp) != DS18B20_OK) { state = STATE_ERROR; } else { switch (state) { case STATE_NORMAL: if (temp >= ALARM_TEMP) state = STATE_ALARM; break; case STATE_ALARM: if (temp <= RELEASE_TEMP) state = STATE_NORMAL; break; case STATE_ERROR: if (temp < ALARM_TEMP) state = STATE_NORMAL; break; default: break; } } UpdateOutput(state, temp); HAL_Delay(500); }

这里ALARM_TEMP设成60.0f,RELEASE_TEMP设成57.0f。因为主循环间隔500ms采样一次,相当于软件消抖,蜂鸣器不会再乱响。在错误状态下,我一般让蜂鸣器以1秒间隔间歇报警,和持续报警的高温状态区分开。

3.4 串口打印与调试

调试时,串口的功劳最大。我会重定向printf到串口1,每隔500毫秒打印一次温度值和当前状态,这样不用猜代码走到哪了。

int fputc(int ch, FILE *f) { HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xFFFF); return ch; }

然后插上USB转TTL模块,打开串口助手,波特率115200,就能看到实时温度。如果手头有OLED,加一个I2C显示屏把温度显示出来,整个项目就更有“产品”的感觉。但要注意,OLED的I2C总线和DS18B20的单总线在代码里不要混用延时,否则容易互相卡顿。

4. 调试常见问题与排查技巧

4.1 温度永远读到85℃或-55℃

这是DS18B20项目里出镜率最高的两个故障值。85℃是DS18B20上电复位后暂存器的默认值,说明复位和ROM命令基本正常,但读取的温度是旧值;-55℃则通常是读出了0xFFFF,也就是时序错乱导致读不到有效数据。

排查顺序我建议是这样:第一,检查原理图或面包板,数据线上有没有4.7kΩ上拉电阻;第二,确认GPIO配置的是开漏输出,外部上拉正常;第三,用逻辑分析仪看时序,或者先跑一个官方开发板例程。最容易犯的错误是上来就改代码,其实是硬件接触不良。我自己的习惯是把串口打印加在复位和读取之间,看到底是哪一步返回异常,这样能快速缩小范围。

4.2 蜂鸣器在阈值附近反复报警

这个现象我在项目评审现场见过好多次:温度在59.9到60.1之间来回跳,蜂鸣器跟着一会儿响一会儿停,非常掉价。原因就是两个:没有滞回,采样值本身有噪声。解决办法第一位是软件加上滞回区间,就是前面提到的60℃报警、57℃解除。第二位是对温度连续采样多次,比如5次,去掉最大值和最小值,再取平均或中值。这种滑动滤波对控温场景足够,不需要上卡尔曼滤波。

这里还要注意一个细节:报警输出之后,尽量不要在ISR或者延时函数里直接翻转引脚。用一个标志位,主循环根据状态机统一更新输出,看起来更规整,也避免中断嵌套把单总线时序搞乱。

4.3 ST-Link下载失败:no stm32 target found

搜索热度非常高的一个问题,报错大概是“Error: no STM32 target found! If your product embeds Debug Authentication...”。绝大多数情况不是芯片锁死,而是连接或配置问题。我遇到过的常见原因有:

  1. SWDIO、SWCLK、GND三根线没接对,或者杜邦线接触不良。
  2. 核心板没有独立供电,只靠ST-Link的3.3V输出供电,电流不够导致芯片没正常工作。
  3. BOOT0没有拉低,芯片进入了系统存储器模式。
  4. 上一次程序占用了SWD引脚,比如把PA13、PA14配置成普通GPIO,也没有在CubeMX里把SYS Debug选成Serial Wire。
  5. ST-Link和目标板连线太长,环境干扰严重,可以尝试降低SWD频率。

一个很实用的土办法:按住目标板的复位键不放,点击下载的同时松开复位键。很多“死活连不上”的情况,这样就能刷进去。如果还是不行,用STM32 ST-LINK Utility连接一下,看能不能识别到芯片,能识别说明硬件基本没问题。

4.4 程序卡死在HAL_Delay或延时函数

如果之前在中断回调里写了HAL_Delay,而且中断优先级和SysTick相同甚至更高,程序很容易卡在延时函数里出不来。正确做法是中断服务函数里只置标志位,主循环处理实际业务。DS18B20的微秒延时也不要用HAL_Delay,它最小单位1ms,满足不了时序要求。

我自己的延时方案是用DWT计数器实现delay_us。DWT是内核调试单元,不需要占用定时器,精度也很稳。如果你不想折腾,用TIM4做一个1MHz的计数也行,但注意不要让定时器中断和DS18B20死等同时发生。

5. 扩展方向与个人经验

5.1 能往哪些方向继续扩展

这个项目想拿高分,完全可以在稳定跑通之后扩展:用ESP8266通过MQTT把温度上报到手机;加一块OLED显示实时曲线;把继电器换成SSR控制加热器,就变成闭环温控系统;再复杂一点用FreeRTOS把传感器采集、显示、报警拆成独立任务。但我不建议一开始就堆模块,先把核心的温度采集和报警逻辑做到稳如老狗,再加扩展,不然出了问题都不知道该查哪一块。

5.2 踩坑之后说几句实话

最后分享一点个人经验。早期我也照着网上的代码抄DS18B20,结果怎么调都读到85℃,后来借了一台逻辑分析仪才发现是延时不准确,换了编译器优化等级就好了。从那以后我养成一个习惯:任何传感器调试,先通过串口打印原始数据,再谈业务逻辑。

温度报警看似是一个入门项目,但能把复位时序、状态机、硬件驱动、故障处理都讲清楚,才算是真正理解嵌入式开发。希望这篇记录能让你少走一点弯路,也祝你的项目一次点亮。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/9 22:12:23

C++实现影像金字塔:图像重采样与插值算法实战解析

简介&#xff1a;一套面向遥感影像分析与计算机视觉开发者的C图像处理代码&#xff0c;以双线性内插算法为核心&#xff0c;对8位和24位Windows位图进行22模板重采样&#xff0c;并据此构造多分辨率影像金字塔&#xff0c;适用于图像缩放、目标检测与尺度空间分析等场景。压缩包…

作者头像 李华
网站建设 2026/9/9 22:11:49

基于TCP/IP的展厅智能中控系统搭建实践

简介&#xff1a;这套基于TCP/IP的展厅智能中控软件&#xff0c;主要面向展厅、展项及多媒体环境的中控系统集成人员&#xff0c;可解决多设备统一控制、界面快速配置等问题。软件采用所见即所得的拖拽式编辑&#xff0c;无需编程即可完成界面布局&#xff1b;UI素材集中在user…

作者头像 李华
网站建设 2026/9/9 22:10:30

NB-IoT采集终端与Qt上位机开发实战:从串口通信到FFT频谱分析

做嵌入式的人都知道&#xff0c;这两年NB-IoT几乎是远程采集类项目的默认答案。低功耗、广覆盖、室内深覆盖能力强&#xff0c;一块电池跑几年&#xff0c;专门为物联网碎片化场景设计。我去年接手了一个中国移动NB-IoT QT采集终端的项目&#xff0c;说白了就是做一个既能本地采…

作者头像 李华
网站建设 2026/9/9 22:10:19

Linux开发环境与工具链:从环境搭建到真机实战一次讲透

做嵌入式这些年&#xff0c;我换了四台笔记本&#xff0c;每一回重装 Linux 开发环境都要折腾大半天。后来慢慢摸清楚一件事&#xff1a;Linux 开发环境与工具链&#xff0c;表面上看是“装个系统、装几个软件”的事&#xff0c;骨子里其实是两样东西——环境是地基&#xff0c…

作者头像 李华