news 2026/10/21 3:09:24

51单片机DS18B20温度采集与NRF905无线传输实战程序

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
51单片机DS18B20温度采集与NRF905无线传输实战程序

简介:这是一套面向单片机爱好者、电子类专业学生与DIY玩家的温度采集与无线传输实践方案,基于51单片机搭配NRF905无线模块,解决短距离温度数据采集与无线收发的问题。压缩包共34个文件,约80KB,以C语言源码、头文件、Keil工程文件及编译产物为主,包含发射机与接收机两套程序,涉及DS18B20温度传感器与LCD1602显示驱动,另含hex烧录文件、lst列表文件与obj中间文件等,便于直接编译与下载验证。已有173人学习下载。读者可从中掌握温度采集、NRF905无线通信、LCD显示等模块的代码组织方式,对照电路理解元器件工作原理,并借助完整工程结构学习Keil环境下的编译配置与调试流程,适合具备一定电子技术与C语言基础的学习者参考。

1. 从一块“哑巴”板子说起:这套51单片机温度采集NRF905无线传输程序到底能干什么

如果你手头有两块51单片机开发板,一块插着DS18B20温度传感器,另一块接着NRF905无线模块,想让它们之间不用一根线就能把温度数据传过去——这套程序就是干这个的。它解决的是一个非常具体的场景:前端采集节点负责读温度,后端接收节点负责收数据并显示或上传,中间靠NRF905做无线透传。适合谁?适合正在做课程设计、毕业设计、或者工业现场小规模数据采集的开发者,尤其是那些不想碰复杂协议栈、只想用寄存器操作把无线链路跑通的人。NRF905这颗芯片虽然老,但胜在时序简单、不用握手协议、SPI直接读写,配合51单片机这种资源紧张的平台反而比一些新模块更好调。整套程序的核心就是三件事:DS18B20的1-Wire时序、NRF905的SPI配置与收发模式切换、以及主从节点之间的数据帧约定。把这三点吃透,你就能在一天之内让两块板子“隔空对话”。

2. 硬件链路与工程结构:先搞清楚数据从哪来到哪去

2.1 两个节点的角色划分与引脚连接

这套程序默认是“一主一从”的点对点结构。采集节点(从机)挂DS18B20,NRF905配置为发送模式;接收节点(主机)挂NRF905,配置为接收模式,通常还会接一个LCD1602或者串口打印。NRF905与51单片机的连接方式常见做法是SPI三线加控制线:SCK、MOSI、MISO接普通IO口模拟SPI,CSN、CE、PWR_UP、TX_EN、TRX_CE这些控制脚分别接到另外的IO上。DS18B20则单总线接一个IO,外加4.7k上拉电阻。供电方面注意NRF905是3.3V器件,如果51单片机是5V系统,SPI线上最好串电阻分压或者用电平转换,否则长期跑容易玄学丢包。

2.2 工程目录与文件职责

源码包一般会分成两个独立工程:一个TX_Node,一个RX_Node。每个工程里通常包含这些文件:

  • main.c:主循环,负责调度采集、发送、接收、显示
  • nrf905.c / nrf905.h:NRF905的SPI读写、寄存器配置、收发模式切换
  • ds18b20.c / ds18b20.h:1-Wire复位、写字节、读字节、温度转换
  • lcd1602.c(接收端):本地显示
  • delay.c:微秒级延时,给1-Wire和SPI时序用
  • uart.c(可选):调试打印

这种拆分方式很“51”,没有RTOS,没有复杂的状态机,全靠主循环轮询加标志位。好处是逻辑直白,坏处是时序敏感的地方必须关中断或者用精确延时。

2.3 数据帧格式约定

NRF905一次最多传32字节,这套程序一般只用了前几个字节。常见帧结构是:1字节帧头(比如0xAA)、2字节温度整数、1字节温度小数、1字节校验和。接收端先判断帧头,再校验,最后解析。这个约定写在两个工程的nrf905.h里,改的时候两边必须同步改,否则收端会一直丢帧。

// nrf905.h 中常见的帧定义 #define FRAME_HEADER 0xAA #define FRAME_LEN 5 typedef struct { uint8_t header; int16_t temp_int; // 温度整数部分,带符号 uint8_t temp_dec; // 温度小数部分 uint8_t checksum; // 前4字节异或 } TempFrame_t;

这里把温度拆成整数和小数两部分,是为了避免在51上做浮点运算。DS18B20原始数据是16位带符号数,低4位是小数,直接移位就能拿到整数和小数,比float省太多ROM和RAM。校验和用异或,计算快,能挡住大部分误码。

3. 核心模块拆解:DS18B20时序、NRF905配置与主循环调度

3.1 DS18B20温度读取:1-Wire时序不能有中断打扰

DS18B20的难点全在时序上。复位脉冲要拉低至少480us,然后释放,等待15-60us后检测存在脉冲。写时隙分写0和写1,写0拉低60us,写1拉低1-15us后释放。读时隙则是主机拉低1us后释放,在15us内采样。这些时间全靠delay_us撑着,所以读温度的时候最好关总中断,否则一个定时器中断进来就可能把时隙拉长,读出来就是85度——这是新手最常见的翻车点。

// ds18b20.c 中的复位与读写 uint8_t ds18b20_reset(void) { uint8_t presence; DS18B20_DQ = 0; delay_us(480); // 拉低至少480us DS18B20_DQ = 1; delay_us(60); // 等待15-60us presence = DS18B20_DQ; // 读存在脉冲,0表示存在 delay_us(420); // 补足整个时隙 return presence; } void ds18b20_write_byte(uint8_t dat) { uint8_t i; for (i = 0; i < 8; i++) { DS18B20_DQ = 0; delay_us(2); DS18B20_DQ = dat & 0x01; // 写1则释放,写0则继续拉低 delay_us(60); DS18B20_DQ = 1; dat >>= 1; } }

delay_us的精度直接决定成败。如果用的是11.0592MHz晶振,一个机器周期约1.085us,空循环次数要算准。我一般会在delay.c里用_nop_()拼,而不是靠循环,这样不同优化等级下偏差小。读温度完整流程是:复位→跳过ROM→启动转换→延时750ms→复位→跳过ROM→读暂存器→取前两字节→换算。换算时注意低4位是小数,乘以0.0625就是实际小数部分,但为了不用浮点,可以直接查表或者用整数运算。

3.2 NRF905的SPI模拟与寄存器配置

NRF905的配置分两步:先写配置寄存器(频率、地址、功率、数据长度),再切换模式。SPI模拟的关键是CPOL=0、CPHA=0,即空闲低电平,上升沿采样。写寄存器时先拉低CSN,发命令字节(比如0x00写配置),然后发寄存器地址,再发数据,最后拉高CSN。读的时候类似,但命令字节是0x03。

// nrf905.c 中的SPI写字节与配置函数 void nrf905_spi_write(uint8_t dat) { uint8_t i; for (i = 0; i < 8; i++) { NRF_MOSI = dat & 0x80; dat <<= 1; NRF_SCK = 1; // 上升沿采样 delay_us(1); NRF_SCK = 0; delay_us(1); } } void nrf905_config(void) { NRF_CSN = 0; nrf905_spi_write(0x00); // 写配置命令 nrf905_spi_write(0x00); // 配置寄存器起始地址 nrf905_spi_write(0x4C); // 频率等参数,按实际频段改 nrf905_spi_write(0x0C); // 输出功率和地址宽度 nrf905_spi_write(0x44); // 接收地址低字节 nrf905_spi_write(0x20); // 接收地址高字节 nrf905_spi_write(0x20); // 发送地址,需与接收一致 nrf905_spi_write(0x20); // 数据长度,这里设为32字节 NRF_CSN = 1; }

频率参数0x4C对应433MHz频段,具体值要查手册的频段表。地址宽度和地址值必须收发一致,否则收不到。数据长度设32字节,实际只用前5字节,剩下的补0。配置完后,发送端要拉高TX_EN、拉低TRX_CE进入发送模式;接收端拉低TX_EN、拉高TRX_CE进入接收模式。每次发送前拉低TRX_CE再拉高,产生一个脉冲启动发送,然后轮询DR(数据就绪)引脚或者延时等待。

3.3 主循环调度:采集、发送、接收、显示四件事怎么排

发送端主循环很简单:延时→读温度→组帧→NRF905发送→延时。接收端则是:轮询DR引脚→读数据→校验→解析→显示。这里有个细节:NRF905接收模式下,DR引脚变高表示收到数据,读完后DR会自动变低。如果轮询不到,检查TRX_CE和PWR_UP是否拉高,以及地址是否匹配。

// TX_Node main.c 主循环片段 while (1) { temp = ds18b20_read_temp(); // 读温度 frame.header = FRAME_HEADER; frame.temp_int = temp >> 4; // 整数部分 frame.temp_dec = temp & 0x0F; // 小数部分 frame.checksum = frame.header ^ (frame.temp_int >> 8) ^ (frame.temp_int & 0xFF) ^ frame.temp_dec; nrf905_send((uint8_t *)&frame, FRAME_LEN); delay_ms(1000); // 1秒发一次 }

接收端在解析时,先判断header == 0xAA,再算校验和,都对才更新显示。如果校验错,直接丢弃,不要显示乱码。显示部分用LCD1602的话,注意温度整数可能是负数,要处理符号位。

4. 避坑与排查:调NRF905和DS18B20时最容易翻车的几个点

4.1 现象:读温度永远是85度

原因:DS18B20上电默认就是85度,说明转换命令没发出去或者时序被中断打断。解决:检查复位是否存在脉冲,检查写字节时是否关中断,检查延时是否够。用示波器看DQ线,正常应该有复位脉冲和存在脉冲。

4.2 现象:NRF905发送端DR一直不置高

原因:最常见的是SPI配置没写进去,或者TX_EN/TRX_CE时序不对。解决:先读回配置寄存器验证,再检查发送启动脉冲是否给了。另外注意NRF905的VCC和GND要接好,3.3V供电电流要够,有些开发板LDO带不动。

4.3 现象:接收端能收到但数据全是0xFF

原因:地址不匹配或者数据长度设错。解决:确认收发地址寄存器的值完全一致,数据长度寄存器两边都设成一样的值。如果用的是增强模式,还要检查是否开了CRC。

4.4 现象:通信距离很短,隔一堵墙就断

原因:天线没接好或者输出功率设太低。解决:NRF905必须接天线,弹簧天线也行,但一定要焊。输出功率寄存器可以调高,但注意功耗。另外电源去耦电容要加,100nF和10uF并联在VCC脚附近。

4.5 现象:两块板子单独跑都正常,一合起来就丢包

原因:两个节点的地电位不同或者电源噪声互相干扰。解决:共地,或者用电池分别供电。如果必须共电源,加磁珠或者电感隔离。软件上可以加应答重传,但NRF905本身不带ACK,需要自己在上层做。

5. 二次开发与改造:从点对点走向多点组网的一个实用技巧

这套程序默认是点对点,但实际项目里经常需要多个采集节点。NRF905本身支持地址过滤,你可以给每个采集节点分配不同的发送地址,接收端轮流切换接收地址来轮询。但更省事的做法是:所有节点用同一个接收地址,在数据帧里加一个字节的节点ID,接收端根据ID区分。这样接收端不用频繁改寄存器,软件上更好维护。

// 扩展帧结构,增加节点ID typedef struct { uint8_t header; uint8_t node_id; // 新增:节点编号 int16_t temp_int; uint8_t temp_dec; uint8_t checksum; } TempFrameEx_t;

改的时候注意校验和要把node_id也算进去。接收端解析后,用一个数组按node_id存温度,再统一显示或上传。这个改动很小,但能让你的系统从“一对一”变成“多对一”,课程设计里直接多一个亮点。

另一个常见改造是加串口上传。接收端解析完温度后,通过UART发给电脑或者ESP8266之类的模块。51的串口配置很简单,定时器1做波特率发生器,SCON = 0x50,TMOD设好,TH1/TL1按波特率算。发的时候用printf重定向或者直接写SBUF。注意串口中断和NRF905轮询的优先级,别让串口中断把NRF905的时序打乱。

我自己的习惯是:每次改完帧结构或者地址,先在两块板子上用串口打印原始字节,确认收发一致再往下做显示。这个“后悔药”步骤能省掉大量猜谜时间。从那以后我每次调无线模块都强制走一遍“串口看原始数据”的流程,希望帮到你。

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

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

SpringBoot+Vue+MyBatis+MySQL实战:网上超市管理系统核心业务闭环

看到“网上超市管理系统”这个标题&#xff0c;多数人的第一反应是&#xff1a;又是一个商城项目。但如果把SpringBoot、Vue、MyBatis、MySQL这四个词放在一起看&#xff0c;它其实是在讲一件事——如何用一套主流Java技术栈&#xff0c;把一个涉及商品、购物车、订单、库存、后…

作者头像 李华
网站建设 2026/10/21 3:08:57

MySQL百万数据统计优化:Redis预计算实战,从27秒到250毫秒

百万数据统计在 MySQL 里能慢到什么程度&#xff1f;这次我是真真切切体会到了。当时我手头维护的是一个电商后台系统&#xff0c;里面有一张订单明细表&#xff0c;负责给运营看板提供数据。最开始表里也就三四十万行&#xff0c;统计接口基本秒开。可等量级爬到两百多万行之后…

作者头像 李华
网站建设 2026/10/21 3:08:56

AI自动生成SOP:视频+语音+LLM,让工艺文档从2天缩短到1小时

一份SOP从动笔到最终发布&#xff0c;传统做法要多久&#xff1f;我在某装备制造企业做工艺数字化的时候&#xff0c;团队统计过一个平均数&#xff1a;2天。这还只是顺顺利利不出幺蛾子的情况。半天去产线拍照片&#xff0c;半天整理动作拆步骤&#xff0c;半天写描述画流程图…

作者头像 李华
网站建设 2026/10/21 3:08:54

WordPress图片Alt标签优化:设置、批量补全与避坑全指南

做WordPress站点优化的时候&#xff0c;很多朋友最容易忽略的一个细节&#xff0c;就是图片的alt标签。我曾经帮一位做美食博客的朋友排查流量问题&#xff0c;文章写得扎实、配图也算精美&#xff0c;但搜索引擎图片搜索几乎不进流量。后来打开页面源码一看&#xff0c;好几篇…

作者头像 李华
网站建设 2026/10/21 3:08:40

排序算法对数器:大样本随机验证实战指南

写算法的人&#xff0c;心里基本都藏着同一个问题&#xff1a;这段代码&#xff0c;到底对不对&#xff1f;我用排序算法练手十年&#xff0c;也教过不少学生写排序&#xff0c;最头疼的不是写不出来&#xff0c;而是写出来了没人敢拍胸脯说它对。见过太多人盯着代码看了半天&a…

作者头像 李华
网站建设 2026/10/21 3:07:48

Matlab实现CNN-LSTM图像序列分类:原理与实战

做某模拟项目X时&#xff0c;我需要在Matlab里搭建一个CNN-LSTM网络&#xff0c;对一段段图像序列做分类。当时手头是一批设备运行监控视频&#xff0c;每段视频几十帧&#xff0c;目标是判断设备当前处于哪类运行状态。单张图的信息不够&#xff0c;必须让网络既看到空间特征&…

作者头像 李华