蓝桥杯CT107D实战:DS18B20单总线驱动与避坑指南
1. 为什么CT107D上的DS18B20值得单独拿出来讲蓝桥杯单片机组的板子——CT107D几乎是每个参赛选手绕不开的硬件平台。这块板子上集成了不少外设数码管、独立按键、矩阵键盘、蜂鸣器、继电器、DS1302、AT24C02、DS18B20、超声波、红外接收等等基本上把常见嵌入式外设都塞进去了。其中DS18B20这个温度传感器看起来简单一根线就能读温度但实际在CT107D上跑通它踩坑的人不在少数。我自己第一次在CT107D上写DS18B20驱动的时候读出来的温度要么是85要么是0要么干脆一直是-127。折腾了大半天才发现问题出在时序延时上——51单片机的机器周期和DS18B20的微秒级时序要求之间需要非常精确的配合。后来把延时函数调好了温度一下子就出来了。这篇文章就是把我自己在CT107D上调试DS18B20的完整过程整理出来从单总线协议的底层原理到具体的延时计算再到完整的代码实现和常见问题排查都会讲到。不管你是刚接触蓝桥杯单片机的新手还是已经写过几遍DS18B20但总是读不准的老手应该都能从里面找到有用的东西。DS18B20的核心价值在于它用一根数据线就完成了供电、复位、读写全部通信这在引脚资源紧张的单片机系统里非常实用。CT107D上把它接在P1.4口附近具体引脚后面会详细说通过单总线协议和单片机通信。理解了这个协议你以后遇到DHT11、AM2302这类单总线传感器上手会快很多。2. DS18B20和单总线协议的核心原理拆解2.1 DS18B20到底是怎么工作的DS18B20是Dallas Semiconductor现在归Maxim出的数字温度传感器测温范围-55°C到125°C在-10°C到85°C范围内精度是±0.5°C。它内部有三个主要部件温度敏感元件、ADC转换器和单总线接口逻辑。温度敏感元件把温度转换成电压信号ADC把它变成数字量然后通过单总线接口发出去。它的核心寄存器有两个需要重点关注温度寄存器和配置寄存器。温度寄存器是16位的高5位是符号位低4位是小数位。默认分辨率是12位对应0.0625°C的分度值。配置寄存器用来设置分辨率可以选9到12位分辨率越低转换越快但精度也越低。DS18B20的供电方式有两种寄生电源模式和外部电源模式。寄生电源模式下DS18B20从数据线上偷电——当总线为高电平时内部电容充电当总线为低电平时电容放电维持工作。CT107D上一般用的是外部电源模式VDD直接接3.3V或5V这样通信更稳定也不需要在温度转换期间强拉总线。2.2 单总线协议的时序本质单总线协议1-Wire的核心思想是用一根线通过不同的拉低时长来区分不同的命令。所有通信都由主机单片机发起DS18B20作为从机响应。协议里定义了六种基本信号信号类型主机动作从机响应典型时长复位脉冲拉低总线等待480-960μs存在脉冲释放总线拉低总线60-240μs写0拉低总线无60-120μs写1拉低总线后快速释放无1-15μs拉低释放读0拉低总线后释放保持低电平整个时隙读1拉低总线后释放释放总线整个时隙关键点在于所有的时隙time slot都必须由主机拉低总线来启动。写时隙和读时隙的区别在于写时隙主机在整个时隙内控制总线电平读时隙主机只在开始时拉低然后释放由从机决定总线电平。这里最容易出错的地方是读时隙。主机拉低总线至少1μs然后释放必须在15μs内采样总线电平。如果采样太晚DS18B20可能已经把数据发完了读到的一直是1。我见过不少人读温度一直是0xFFFF就是因为采样时机不对。2.3 CT107D上的硬件连接细节CT107D开发板上DS18B20的数据引脚DQ连接到单片机的P1.4不同批次的板子可能略有差异但绝大多数是P1.4。VDD接电源GND接地。板上通常还有一个跳线帽用来选择DS18B20是否接入总线。这里有个细节需要注意CT107D上的P1口还复用了其他功能比如数码管段选、蜂鸣器、继电器等。P1.4除了接DS18B20还可能和别的外设共享。所以在写代码的时候操作P1口要特别小心不能直接对整个P1赋值否则会干扰其他外设。正确的做法是位操作用sbit DQ P1^4;定义数据引脚然后只对DQ进行读写不影响P1口其他位。这一点在蓝桥杯比赛里非常关键因为题目往往要求同时使用多个外设一个不小心就会互相干扰。3. 在CT107D上实现DS18B20驱动的完整过程3.1 延时函数的精确计算51单片机的时序完全依赖软件延时所以延时函数的精度直接决定了DS18B20能不能正常工作。CT107D上用的晶振通常是12MHz有些板子是11.0592MHz但蓝桥杯官方板一般是12MHz。12MHz晶振下一个机器周期是1μs也就是说一个NOP指令正好是1μs。但C语言写的延时函数实际执行时间还受到编译器优化、函数调用开销等因素影响。所以最可靠的方法是用示波器或者逻辑分析仪实测或者根据经验值反复调整。我常用的微秒级延时函数是这样的void Delay_us(unsigned int us) { while(us--) { _nop_(); _nop_(); } }这个函数在12MHz晶振下每次循环大约2μs两个NOP加循环开销。实际用的时候需要根据DS18B20的时序要求来调整。比如复位脉冲需要拉低480μs以上那就调用Delay_us(240)左右。更精确的做法是用STC-ISP软件里的延时计算器或者直接写汇编。但在蓝桥杯比赛里用C语言加NOP的方式足够了关键是实测调整。3.2 复位和存在脉冲的检测复位脉冲是每次通信的开始。主机拉低总线至少480μs然后释放等待DS18B20拉低总线60-240μs作为存在脉冲。bit DS18B20_Reset(void) { bit presence; DQ 0; Delay_us(240); // 拉低约480μs DQ 1; Delay_us(30); // 等待15-60μs presence DQ; // 采样存在脉冲 Delay_us(200); // 等待存在脉冲结束 return presence; }这段代码里presence为0表示DS18B20有响应为1表示没有检测到器件。如果一直返回1说明硬件连接有问题或者延时不对。注意存在脉冲的采样时机很关键。拉高总线后等待15-60μs再采样太早或太晚都可能读错。我一般用30μs实测比较稳。3.3 写时隙和读时隙的实现写一个字节需要8个写时隙每个时隙至少60μs时隙之间至少恢复1μs。void DS18B20_WriteByte(unsigned char dat) { unsigned char i; for(i0; i8; i) { DQ 0; _nop_(); _nop_(); DQ dat 0x01; Delay_us(30); // 保持60μs左右 DQ 1; dat 1; } }写0和写1的区别在于写0时DQ拉低后保持60μs写1时DQ拉低后很快释放1-15μs内。上面的代码里DQ dat 0x01;这一句决定了是写0还是写1。如果dat的最低位是0DQ保持0如果是1DQ被置1。读时隙稍微复杂一点unsigned char DS18B20_ReadByte(void) { unsigned char i, dat 0; for(i0; i8; i) { dat 1; DQ 0; _nop_(); _nop_(); DQ 1; _nop_(); _nop_(); if(DQ) dat | 0x80; Delay_us(30); } return dat; }读时隙的关键是主机拉低至少1μs然后释放在15μs内采样。上面的代码里拉低后两个NOP约2μs然后释放再两个NOP后采样。这个时机需要根据实际晶振调整。3.4 温度转换和读取的完整流程DS18B20读温度的标准流程是复位跳过ROM0xCC启动温度转换0x44等待转换完成12位分辨率需要750ms复位跳过ROM0xCC读取暂存器0xBE读两个字节的温度数据转换成实际温度值float DS18B20_GetTemp(void) { unsigned char L, H; int temp; float result; DS18B20_Reset(); DS18B20_WriteByte(0xCC); DS18B20_WriteByte(0x44); // 等待转换可以用延时或者检查总线 Delay_ms(750); DS18B20_Reset(); DS18B20_WriteByte(0xCC); DS18B20_WriteByte(0xBE); L DS18B20_ReadByte(); H DS18B20_ReadByte(); temp (H 8) | L; // 处理负温度 if(temp 0x8000) { temp ~temp 1; result -(temp * 0.0625); } else { result temp * 0.0625; } return result; }这里有个细节负温度的处理。DS18B20输出的是补码如果最高位是1表示负温度。需要先取反加一得到绝对值再乘以0.0625最后加上负号。另外12位分辨率下转换时间是750ms如果比赛时时间紧张可以把分辨率降到9位转换时间93.75ms但精度会降到0.5°C。具体怎么选看题目要求。4. 常见问题排查与实战避坑指南4.1 温度一直读85或者-127怎么办这是最经典的问题。85°C是DS18B20上电后的默认值如果你读到的一直是85说明温度转换根本没有启动或者转换命令没有发出去。排查步骤检查复位函数是否返回0有存在脉冲检查写时隙的延时是否足够检查是否发送了0x44命令检查等待转换的时间是否足够-127°C0xFFF通常表示读到的全是1也就是总线一直是高电平。可能的原因DQ引脚定义错了硬件连接松动读时隙采样太晚DS18B20已经释放总线我遇到过一次DQ定义成了P1^3结果怎么读都是-127。后来改成P1^4就正常了。所以引脚定义一定要对照板子原理图确认。4.2 温度跳动很大怎么处理有时候读到的温度会在两个值之间跳比如25.5和25.6来回变。这通常是分辨率设置和显示处理的问题。12位分辨率下温度的最小分度是0.0625°C。如果你直接显示两位小数就会看到跳动。解决办法有两种降低分辨率到11位或10位减少跳动在显示前做滑动平均滤波取最近几次读数的平均值我在比赛里一般用滑动平均取5次读数去掉最高最低再平均效果不错。4.3 和其他外设冲突怎么解决CT107D上P1口复用严重DS18B20用P1.4数码管段选也用P1口蜂鸣器用P1.5继电器用P1.4有些板子。如果同时使用这些外设很容易冲突。解决办法操作DS18B20时先保存P1口状态操作完恢复或者用位操作只改变DQ位不影响其他位数码管动态扫描和DS18B20读取分时进行避免同时操作我一般的做法是DS18B20读取放在主循环里数码管扫描放在定时器中断里两者互不干扰。但要注意DS18B20的延时函数不能被中断打断否则时序会乱。所以读取DS18B20的时候最好关一下总中断读完再开。4.4 常见问题速查表现象可能原因解决方法一直读85转换未启动检查0x44命令和复位一直读-127总线一直高检查DQ定义和硬件连接温度跳动大分辨率过高降低分辨率或滑动平均读数为0读时隙采样太晚调整采样时机偶尔读错中断干扰时序读取时关中断负温度显示错误补码处理不对取反加一再加负号提示蓝桥杯比赛里DS18B20的题目通常要求显示整数温度这时候可以直接取温度值的高字节和低字节的高4位拼成一个整数省去浮点运算速度更快。5. 代码优化与比赛实战建议5.1 用整数运算代替浮点51单片机没有硬件浮点单元浮点运算很慢。如果只需要显示整数温度可以这样处理int temp_int; temp_int ((H 8) | L) 4; // 取整数部分这样得到的就是整数温度省去了浮点乘法和类型转换。如果题目要求一位小数可以这样int temp_int, temp_dec; temp_int ((H 8) | L) 4; temp_dec (((H 0x0F) 4) | (L 4)) * 10 / 16;这样temp_int是整数部分temp_dec是小数部分0-9显示的时候分开显示就行。5.2 状态机方式读取温度在比赛里主循环往往要处理按键、显示、通信等多个任务。如果DS18B20用阻塞式延时750ms整个系统会卡住。更好的方式是状态机状态0发送转换命令状态1等待转换用定时器计时状态2读取温度状态3处理数据这样主循环不会被阻塞其他任务也能正常运行。我在省赛的时候就是用这种方式按键响应和温度显示都很流畅。5.3 比赛中的时间分配建议蓝桥杯单片机组的比赛时间通常是5个小时DS18B20相关的题目一般占10-15分。建议的时间分配硬件确认和引脚定义10分钟复位和读写函数调试30分钟温度转换和显示20分钟与其他外设整合30分钟预留调试时间30分钟如果DS18B20调了超过1小时还没出来先放一放把其他部分做完再回来调。有时候换个思路问题反而迎刃而解。5.4 一个容易被忽略的细节总线释放时间每次通信结束后总线需要至少1μs的恢复时间。如果连续操作DS18B20比如写完命令马上读中间没有足够的恢复时间可能会导致通信失败。我在写读函数的时候每个时隙结束后都会加一个短延时确保总线恢复。另外DS18B20在温度转换期间总线应该保持高电平。如果这时候有其他外设拉低总线转换可能会中断。所以转换期间最好不要操作P1口其他位。6. 从DS18B20延伸出去的单总线思维DS18B20只是单总线协议的一个应用。理解了它的时序本质你会发现很多传感器都用了类似的思想——用一根线通过不同的电平持续时间来编码信息。比如DHT11用一根线传输40位数据红外接收头用一根线输出NEC协议编码超声波模块用两根线触发和回响完成测距。单总线协议的精髓在于时间换空间用精确的时序控制代替多根数据线节省了引脚资源但增加了软件复杂度。在引脚紧张的嵌入式系统里这种取舍非常常见。我在实际项目中用过DS18B20做多点测温一条总线上挂8个传感器每个传感器有唯一的64位ROM地址。通过匹配ROM命令可以单独读取每个传感器的温度。这种方式在分布式测温系统里非常实用比如机房温度监控、农业大棚测温等。回到蓝桥杯DS18B20的题目万变不离其宗读温度、显示温度、温度控制比如超过阈值报警。把底层驱动写稳了上层逻辑就是搭积木。我建议你在练习的时候把DS18B20的驱动单独封装成两个文件.c和.h以后遇到类似的题目直接拿来用省时省力。最后分享一个我自己的小习惯每次写完DS18B20的代码我都会先用一个简单的测试程序只读温度并通过串口打印出来确认底层没问题了再整合到完整的项目里。这样排查问题的时候能快速定位是底层驱动的问题还是上层逻辑的问题。这个习惯帮我省了很多调试时间你也可以试试。

相关新闻

Java爬虫实战:用Jsoup高效解析网页表格并导出CSV

Java爬虫实战:用Jsoup高效解析网页表格并导出CSV

简介:这是一个基于Java与Jsoup库抓取网页表格数据的入门实例,适用于在MyEclipse环境中学习网络爬虫原理的开发者,目标是掌握从HTML页面提取结构化表格信息的完整方法。资源包为zip格式,共24个文件,其中包含7个Java源码…

2026/10/15 21:39:55 阅读更多 →
树莓派4 UART多串口配置与通信实战指南

树莓派4 UART多串口配置与通信实战指南

1. 为什么树莓派 4 的 UART 值得单独拿出来聊 树莓派 4 这块板子,但凡你玩过一阵子,大概率都会碰到一个绕不开的需求:接一个串口设备。可能是 GPS 模块、可能是某款工业传感器、可能是和另一块单片机做点对点通信,也可能是调试一个…

2026/10/15 21:39:55 阅读更多 →
大模型指令微调实战:从LoRA选型到数据配比与避坑指南

大模型指令微调实战:从LoRA选型到数据配比与避坑指南

简介:这份PPT面向自然语言处理与大模型方向的学习者与开发者,系统梳理大模型指令微调(Instruction Tuning)的核心概念与整体脉络。内容从NLP四范式切入,依次讲解传统机器学习、深度学习、预训练加微调以及预训练加Prom…

2026/10/15 21:38:54 阅读更多 →

最新新闻

wow.js滚动触发动画原理与实战:IntersectionObserver轻量封装

wow.js滚动触发动画原理与实战:IntersectionObserver轻量封装

简介:这是一份轻量级网页滚动动画实现方案,面向前端初学者与网页设计师,解决网站静态内容缺乏视觉动效、用户交互体验平淡的问题。资源基于流行的wow.js库封装,通过CSS类绑定实现元素进入视口时的自动动画触发,支持淡入…

2026/10/15 22:26:22 阅读更多 →
手机日志分析实战:从Android底层采集到行为漏斗建模

手机日志分析实战:从Android底层采集到行为漏斗建模

1. 项目概述:从手机屏幕亮起的那一刻,数据就开始说话了 “大数据项目实践——手机日志分析”,这十个字背后不是PPT里的抽象概念,而是一整套可触摸、可验证、可复现的工程闭环。我带过三届某高校数据科学方向的实训项目&#xff0c…

2026/10/15 22:26:22 阅读更多 →
TensorFlow Lite边缘部署实战:模型量化与现场推理调优指南

TensorFlow Lite边缘部署实战:模型量化与现场推理调优指南

这个系列写到第三篇,终于要开始聊真正能在现场设备上跑起来的方案了。前两篇更多是把TensorFlow编程基础过了一遍,而这一篇要解决的问题很具体:当你在做一个边缘计算应用时,手里的算力不再是几百瓦的显卡,而是一块电池…

2026/10/15 22:26:22 阅读更多 →
康耐视扫码枪接线配置与参数调优实战指南

康耐视扫码枪接线配置与参数调优实战指南

简介:康耐视扫码枪使用说明书是一份面向产线调试、设备维护等现场工程师的PDF操作手册,系统讲解如何让扫码枪在物流、仓储、制造等场景下稳定准确地读取条码与二维码。文档从Dataman软件连接读码器入手,覆盖IP网段匹配、自动曝光关闭、曝光与…

2026/10/15 22:26:22 阅读更多 →
微信图文分享+App唤醒闭环实战:服务端重定向方案详解

微信图文分享+App唤醒闭环实战:服务端重定向方案详解

1. 项目概述:一次真实场景下的“图文分享App唤醒”闭环实践最近在帮某高校实验室做一套轻量级教学资源分发系统,核心需求很具体:老师在网页端编辑好一份带图解的实验操作指南,点击“一键分享”,内容要能以图文卡片形式…

2026/10/15 22:26:22 阅读更多 →
代码库变成书:AiReadCode从源码生成结构化阅读指南

代码库变成书:AiReadCode从源码生成结构化阅读指南

1. 为什么要做“代码库变成书”这件事先交代一个背景:有段时间我一直在啃 Spring AI Alibaba 的源码。这个项目体量不算夸张,但牵扯到模型接入、工具调用、Agent 编排、Spring 生态集成,读起来经常是“翻开一个类,跳转三个依赖&am…

2026/10/15 22:25:16 阅读更多 →

日新闻

Docker Compose 容器化部署 ChirpStack LoRaWAN 网络服务器实战

Docker Compose 容器化部署 ChirpStack LoRaWAN 网络服务器实战

1. 为什么选择容器化方式部署 LoRa 网络服务LoRa 物联网项目落地时,网络服务器是整个链路的核心枢纽。它负责接收网关上报的数据包、完成去重与解密、再把有效载荷分发给上层应用。早期大家习惯把网络服务器直接装在物理机上,依赖一堆系统库和特定版本的…

2026/10/15 0:00:46 阅读更多 →
共享LLM服务下的跨模型自动扩缩容:Kubernetes实战与避坑指南

共享LLM服务下的跨模型自动扩缩容:Kubernetes实战与避坑指南

1. 共享推理服务里,扩缩容到底难在哪做过大模型推理服务部署的人,大概都经历过这样的场景:一个团队共用一套推理集群,A 业务跑的是 7B 的小模型,B 业务跑的是 72B 的大模型,C 业务白天流量高、晚上几乎归零…

2026/10/15 0:00:46 阅读更多 →
Systemd 启动阶段根文件系统只读之谜:fstab 与 remount-fs 服务深度解析

Systemd 启动阶段根文件系统只读之谜:fstab 与 remount-fs 服务深度解析

1. 引子:一次内核恐慌引发的追查先从一个真实场景说起。某次我给一台老旧的嵌入式设备折腾系统裁减,为了把启动时间压进两秒以内,我手贱地把一串自认为“没用”的 systemd 服务给 disable 了,其中就包括systemd-remount-fs.servic…

2026/10/15 0:00:46 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/15 16:18:54 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/15 19:41:51 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/15 13:48:15 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 0:14:36 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/14 22:45:47 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 9:49:14 阅读更多 →