简介面向51单片机初学者与电子类专业学生的温度采集与NRF905无线传输实践方案配套Keil工程与C语言源码解决本地测温数据短距离无线上报的入门训练问题。压缩包共34个文件、约80KB以c与h源文件为核心辅以uvproj、uvopt等Keil工程配置、hex烧录文件以及lst、m51、obj、plg等编译中间与列表文件另含bak备份接收机与发射机两端程序分目录存放便于对照阅读。已有173人学习下载。代码中可看到DS18B20温度读取、LCD1602显示与NRF905收发配置的组织方式结合头文件可梳理引脚定义、时序处理和无线收发流程适合作为课设、毕设前期练手或DIY测温节点改造的参考。1. 一条 430MHz 的空口替掉了三十米长的探头线在大棚、粮仓、机房这类场景里做温度采集难的从来不是测温而是把温度值送回值班室。我见过一种很常见的做法每个探头拉一根三十米的双绞线回控制箱末端接一块 51 最小系统板几路探头就是几束线时间一长接头氧化读数开始飘排查一次耗掉半天。这套「51单片机 NRF905 无线模块」的温度采集程序干的就是把这段线换成空口采集端用 DS18B20 测温51 单片机把结果打包成定长帧NRF905 以 430MHz 附近的载频发出去接收端收下来还原成温度送 1602 液晶显示同时从串口丢给上位机。它适合两类人一类是刚接触无线、想找一条从传感器到时序、从 SPI 到空口的完整链路练手的人另一类是要做小批量无线测温节点、需要一个能跑通的底稿再往上加东西的人。下面按「系统怎么分、温度怎么采、无线怎么发、调不通看哪里、怎么改」的顺序拆。2. 系统拆解发射端、接收端与那条 7 字节的空中链路这套程序不是单工程是成对的两个一个烧进采集节点一个烧进接收节点。两边用的是同一颗 NRF905 驱动同一套帧定义区别只在主循环干什么——采集端定时测温发出去接收端一直守在接收模式里等着。搞清楚这条「谁发、谁收、发什么」的链路后面看代码才不会迷路。2.1 两个节点的硬件构成与引脚分配采集端的核心是 51 单片机STC89C52 或 AT89S52 都行代码不用改、一颗 DS18B20 数字温度传感器、一块 NRF905 模块供电用 3.3V LDO 加电池或者 5V 适配器。接收端把 DS18B20 换成 1602 液晶和一路串口其余不变。NRF905 是 3.3V 器件IO 耐压有限如果单片机跑 5VMOSI、SCK、CSN 这几根输出脚上最好串 1K 电阻限流这一点很多现成模块的说明里不写但真烧过就知道疼。引脚分配我沿用了最常见的接法一张表看完信号单片机引脚方向说明DS18B20 DQP3.3双向单总线必须外接 4.7K 上拉到 VCCNRF905 MISOP1.0输入SPI 数据入NRF905 MOSIP1.1输出SPI 数据出NRF905 SCKP1.2输出SPI 时钟软件模拟NRF905 CSNP1.3输出片选低有效NRF905 PWR_UPP1.4输出1 上电0 掉电NRF905 TRX_CEP1.5输出收发使能NRF905 TX_ENP1.6输出1 发送0 接收NRF905 DRP3.2输入数据就绪接 INT0 也可轮询NRF905 AM / CDP3.4 / P3.5输入地址匹配 / 载波检测调试时很有用1602 数据口P0输出必须外接 10K 排阻上拉1602 RS/RW/ENP2.5 / P2.6 / P2.7输出控制线串口 TXD/RXDP3.1 / P3.0—9600 8N1接 USB 转 TTLP3.2 接 DR 是个划算的设计接收端可以开外部中断DR 一拉高就进中断取包主循环该刷液晶刷液晶不用死等。如果你嫌中断麻烦轮询 DR 也完全够用一个 433MHz 的空口跑几十 kbps轮询周期根本不会漏包。2.2 帧格式为什么定 7 字节而不是直接发浮点数新手最容易犯的错是把float直接塞进空口。51 上跑浮点光库函数就吃掉一两 K Flash一个温度值占 4 字节字节序在收端还得对齐出了错很难看出来。我一般用定点DS18B20 原始值本身就是 12 位有符号数一个 LSB 等于 0.0625℃直接把这 16 位原样发走接收端再换算两个字节搞定精度一点不丢。帧结构定成 7 字节剩下的补齐到 NRF905 的 32 字节有效载荷偏移长度字段说明010xAA帧头 1110x55帧头 221node_id节点编号1~3231temp_h温度原始值高字节41temp_l温度原始值低字节51flagsbit0 传感器异常bit1 低电量61checksum前 6 字节累加和取低 8 位打包的代码就这么几行放在两端共用的frame.c里#include config.h /* 把一次采集结果打包成 7 字节帧返回帧长 */ unsigned char Frame_Pack(unsigned char *buf, unsigned char node, int temp_raw, unsigned char flags) { unsigned char i, sum 0; buf[0] 0xAA; /* 帧头用来在字节流里找起点 */ buf[1] 0x55; buf[2] node; /* 节点编号多节点时靠它区分 */ buf[3] (unsigned char)(temp_raw 8); /* 高字节在前收端好拼 */ buf[4] (unsigned char)(temp_raw 0xFF); buf[5] flags; for(i 0; i 6; i) sum buf[i]; buf[6] sum; /* 累加和校验比 CRC 省事够用 */ return 7; } /* 校验一帧是否完整合法返回 1 表示通过 */ unsigned char Frame_Check(const unsigned char *buf, unsigned char len) { unsigned char i, sum 0; if(len 7) return 0; /* 长度不够直接丢 */ if(buf[0] ! 0xAA) return 0; /* 帧头不对说明错位了 */ if(buf[1] ! 0x55) return 0; for(i 0; i 6; i) sum buf[i]; return (sum buf[6]) ? 1 : 0; }两个函数的分工很清楚Frame_Pack只负责拼Frame_Check只负责验中间不掺任何业务逻辑后面要换成 CRC16 或者加字段改这两处就行。参数temp_raw用的是int51 上就是 16 位有符号负温度的高字节最高位是 1右移的时候要注意别先转成unsigned否则零下温度会变成一个巨大的正数——这个坑我踩过显示出来是 40 多度查了半天才发现是类型提升。checksum用累加和而不是 CRC16是我权衡过的NRF905 硬件本身带 CRC 校验空口上错包的概率已经很低应用层再加一道累加和主要是防「帧头对上了但内容错位」这种软故障用不着上 CRC16 那套查表。2.3 Keil C51 工程的目录组织两个工程分开建公共文件用软链接或者直接复制一份别搞成一个工程里靠宏切换编译配置一多新人第一件事就是编不过。TempNode/ # 采集端工程烧进电池供电的节点 ├── main.c # 主循环定时采集 → 打包 → 发送 ├── ds18b20.c/.h # 单总线时序与温度换算 ├── nrf905.c/.h # SPI 读写、配置区、收发状态机 ├── frame.c/.h # 帧打包与校验与接收端一致 ├── delay.c/.h # 微秒/毫秒延时按晶振标定 └── config.h # 引脚定义、节点号、频道号集中在这里 TempHost/ # 接收端工程接 1602 和串口 ├── main.c # 主循环轮询 DR → 收包 → 显示 → 上传 ├── nrf905.c/.h ├── frame.c/.h ├── lcd1602.c/.h ├── uart.c/.h └── config.hconfig.h是这套工程里最该重视的文件。引脚、节点编号、无线频道号、目标地址全塞在里面两端的频道和地址必须一模一样改的时候只改这一个文件避免出现「发了新版采集端忘了重烧接收端」这种事。我见过太多人把地址写死在nrf905.c的两个不同位置改一处漏一处。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?