简介:基于MSP430G2553的温度与光照强度监测及无线传输项目资源,面向物联网环境监测、嵌入式数据采集等应用场景,适合相关方向的学生、开发者与硬件爱好者参考。资源围绕DS18B20数字温度传感器、光照检测以及12864液晶显示,构建了无线发送(wirless_send)与无线接收(wirless_recieve)两个独立CCS工程,从传感器数据采集、LCD实时显示到无线收发,形成完整的现场监测与远程传输链路。压缩包共43个文件,以C源码、头文件、CCS工程配置文件(.cproject/.ccsproject)、链接脚本(.cmd)及makefile为主,另含编译生成的映射、目标文件与调试输出,整体仅78KB,结构紧凑,两个工程分目录存放,便于直接导入IDE进行编译和调试对比。已有319人学习浏览。通过该资源可快速掌握MSP430G2553的GPIO、定时器及外设驱动写法,理解单总线温度传感器时序、LCD12864显示控制以及nRF24L01等无线模块的收发流程,对完成课程设计或入门低功耗物联网开发很有实用价值。
1. 从整条链路切入:MSP430G2553 温度与光照强度无线测试方案
MSP430G2553 做温度与光照强度测试并不复杂,复杂的是把无线传输一起做稳。很多同学做毕设时先调传感器,等温度光照都准了,回头才发现无线模块供电、组包、校验全是坑,现场演示时数据乱跳、距离一远就丢包。这套方案把“采集、滤波、组包、无线发送、接收、上位机”当成一条完整链路来设计:发送节点用 MSP430G2553 挂 DS18B20 温度传感器和 BH1750 光照传感器,nRF24L01 无线传回接收端,再经 USB 转串口在电脑上画出温度与光照强度双曲线。方案给出完整硬件接口、C 固件、上位机代码和验收清单,适合需要交课设/毕设的学生,也适合想快速搭环境监测样机的开发者。
2. 硬件总体设计:主控选型、传感器接口与无线模块
2.1 为什么选 MSP430G2553 而不是 STM32
这套系统最关心的不是算力,而是功耗、体积和 ADC 外设。MSP430G2553 自带 ADC10 模块,10 位分辨率虽然不高,但配合 DS18B20 数字温度和 BH1750 I2C 光照传感器,足够完成 ±0.5°C 和 lx 级光照测量;它支持 LPM3 低功耗模式,休眠电流能到 1μA 以下,非常适合做电池供电的无线采集节点。
STM32 当然也能做,但一颗最小系统板的价格、启动复杂度都比 MSP430G2553 高,而且对“传感器加无线发送”这种轻负载来说性能严重过剩。下面是本方案的对比考虑:
| 对比项 | MSP430G2553 方案 | STM32 方案 |
|---|---|---|
| 典型功耗 | LPM3 下 1μA 级 | 低功耗模式配置复杂 |
| ADC | 内置 10 位,够用 | 12 位,需要额外配置 |
| 逻辑电平 | 3.3V,与 nRF24L01 直连 | 3.3V,但部分板载 5V 电平需跳线 |
| 开发成本 | 几元一片,开发板便宜 | 入门板偏贵,仿真器要求高 |
| 学习负担 | 外设寄存器少,容易读懂 | 时钟树和 HAL 库概念多 |
如果你是为了交一份能完整演示的方案,MSP430G2553 的学习成本和故障率都更低。我一般会告诉学生:能用一颗 MCU 解决的,就不要上两颗。
2.2 温度传感器选型:DS18B20 单总线方案
温度部分有两条路:NTC 热敏电阻加 ADC 采集,或者 DS18B20 单总线数字输出。NTC 成本低,但要自己做分压、查表、标定,温度一高非线性就明显;DS18B20 直接输出 12 位数字量,精度 ±0.5°C,驱动时序成熟,更适合作为毕设主方案。
本方案采用 DS18B20,数据线接到 P1.0,接线如下:
| DS18B20 引脚 | 连接到 | 说明 |
|---|---|---|
| VCC | 3.3V | 供电 |
| GND | GND | 地 |
| DQ | P1.0 | 数据线,需接 4.7kΩ 上拉到 VCC |
4.7kΩ 上拉电阻是重点。没有它,单总线默认状态拉不高,初始化经常失败;上拉阻值太小,DS18B20 拉低总线时会消耗过大电流,同样会导致时序畸变。实际调试中我习惯先用万用表量 DQ 引脚空闲电压,应该接近 3.3V,低于 2.5V 就优先检查上拉。
2.3 光照传感器选型:BH1750 I2C 数字方案
光照强度这块同样有两种常见做法:光敏电阻分压接 ADC,或者 BH1750 I2C 数字传感器。光敏电阻方案便宜,但需要自己标定“电压到 lux”的关系,而且不同批次个体差异大,换一颗电阻就要重新标定。BH1750 直接输出 0 到 65535 的 lux 原始值,除以 1.2 就是标准照度,调试时拿手机光照计 App 做参考即可。
本方案选 BH1750,接口如下:
| BH1750 引脚 | 连接到 | 说明 |
|---|---|---|
| VCC | 3.3V | 供电,模块带稳压时可接 5V,这里统一 3.3V |
| GND | GND | 地 |
| SCL | P1.6 | 时钟线 |
| SDA | P1.7 | 数据线 |
BH1750 模块多数带 4.7kΩ 上拉,但自己搭最小系统时,SCL 和 SDA 都需要外接上拉到 3.3V,否则 I2C 读出来的数据全是 0xFF。模块上的 ADDR 引脚接地时 I2C 地址为 0x23,接高时变 0x5C,代码里要留成宏定义,方便现场切换。
2.4 无线模块选型:nRF24L01 与 HC-12 的取舍
无线传输是本方案最容易翻车的环节。nRF24L01 工作在 2.4GHz 频段,支持 250kbps 到 2Mbps 空中速率,带自动应答和重发机制,价格低、资料多;HC-12 是串口透传模块,433MHz 穿透性更好,但体积大、功耗高,做双节点演示时组包逻辑基本被模块吃掉,答辩解释空间小。
因此发送和接收两端都选 nRF24L01。引脚分配如下,特别注意与 UART、传感器引脚错开:
| nRF24L01 引脚 | 发送端/接收端 MCU 引脚 | 说明 |
|---|---|---|
| CE | P2.0 | 片选使能 |
| CSN | P2.1 | SPI 片选 |
| SCK | P2.2 | SPI 时钟 |
| MOSI | P2.3 | SPI 数据输出 |
| MISO | P2.4 | SPI 数据输入 |
| IRQ | P2.5 | 状态中断,低有效 |
| VCC | 3.3V | 严禁接 5V |
| GND | GND | 与 MCU 共地 |
这里要强调电平匹配:nRF24L01 最高电压 3.6V,接 5V 会直接烧模块。MSP430G2553 本身是 3.3V 供电,所以不用做电平转换;但如果你用的是 5V 单片机板,需要额外加逻辑电平转换芯片,这也是我选 MSP430G2553 的原因之一。
2.5 电源与最小系统设计
供电结构推荐“USB 5V 进,3.3V 出”。AMS1117-3.3 稳压到 3.3V 供给 MCU、传感器和无线模块。如果用锂电池,3.7V 到 3.3V 的压差比较小,AMS1117 也能工作,但要注意电池没电时压差不足,输出电压会跟着掉,导致 nRF24L01 发送功率不稳。
最小系统部分,VCC 和 GND 之间至少放 0.1μF 和 10μF 两个电容。10μF 电容不是可有可无,nRF24L01 发送瞬间会有十几毫安的脉冲电流,如果电源储能不足,MCU 会跟着掉电复位,表现就是每次无线发送后数据变成 0。复位电路用 10kΩ 上拉到 VCC、0.1μF 对地即可。晶振可以不接,直接用 MSP430G2553 内部 DCO 校准到 8MHz,省掉两个负载电容的调试工作。
2.6 硬件分板:发送节点与接收节点的职责划分
整个系统分成两块独立的板子,避免“一块板又采集又无线又串口”互相干扰。发送节点由 MCU、DS18B20、BH1750、nRF24L01 组成,负责采集和发送;接收节点由 MCU、nRF24L01、USB 转串口组成,负责接收并转发到电脑。两块板分别供电、分别调试。
这样做的好处是定位问题非常直接:温度光照不对就查发送节点,电脑上没数据就查接收节点和串口。传感器用排针或杜邦线连接,现场答辩时可以快速拔插替换,也方便后期把光敏电阻方案并进来做对比演示。
3. 固件实现:DS18B20 采集、光照 I2C 读取与无线组包
3.1 开发环境与工程结构
开发环境用 CCS 或 IAR 都可以,这项目不需要图形化配置工具,直接建空工程写 C。工程文件建议按功能拆分,而不是把所有代码堆在 main.c 里,否则调无线时连温度代码都找不到。最小工程结构如下:
project/ main.c // 主循环、初始化、低功耗调度 ds18b20.c // 单总线驱动与温度读取 bh1750.c // I2C 驱动与光照读取 nrf24l01.c // SPI 驱动、寄存器配置、收发函数 packet.c // 数据包组包、校验和恢复主循环的思路是:系统初始化完成后,采集温度,采集光照,各自做滤波,组包,发送,然后进低功耗。每隔约 2 秒由定时器唤醒一次执行完整流程。这样结构简单,出问题时按函数单步就能定位。
3.2 时钟、看门狗与 GPIO 初始化
MSP430G2553 使用内部 DCO 时钟,通过校准常量精确到 8MHz。代码开头必须关看门狗,否则程序一跑长就自动复位:
WDTCTL = WDTPW | WDTHOLD; // 关看门狗 BCSCTL1 = CALBC1_8MHZ; // 校准 DCO 到 8MHz DCOCTL = CALDCO_8MHZ; P1DIR = 0; // P1 默认输入 P1SEL = 0; // 关闭第二功能,避免 JTAG 引脚干扰 P1REN = BIT6 | BIT7; // P1.6/P1.7 I2C 上拉使能 P2DIR = 0; P2SEL = 0; // 传感器引脚 P1DIR &= ~BIT0; // DS18B20 DQ 先设为输入 P1OUT &= ~BIT0; // nRF24L01 控制引脚 P2DIR |= BIT0 | BIT1 | BIT2 | BIT3; // CE/CSN/SCK/MOSI 输出 P2DIR &= ~BIT4; // MISO 输入 P2DIR &= ~BIT5; // IRQ 输入逻辑说明:内部 DCO 校准常量存放在信息段,直接引用即可。P1REN 使能 P1.6/P1.7 内部上拉,可省掉外部上拉电阻,但如果你选了外部 4.7kΩ,建议不要同时开内部上拉,否则等效上拉电阻偏小,I2C 低电平时间可能不够。参数上,8MHz 下做 DS18B20 时序要精确到微秒级,用__delay_cycles(8000)实现 1ms 延时,比空循环可靠。
3.3 DS18B20 温度读取:复位、跳过 ROM 与读取暂存器
DS18B20 的核心操作是复位、写命令、读数据。每次读取温度前都要复位一次,否则传感器状态不确定。下面是核心读取函数:
float read_temperature(void) { if (ds18b20_reset() == 1) { return -999.0f; // 传感器不在线 } ds18b20_write_byte(0xCC); // 跳过 ROM,单设备场景 ds18b20_write_byte(0x44); // 启动温度转换 delay_ms(100); // 12 位分辨率需 750ms,这里留 100ms 给循环调度 ds18b20_reset(); ds18b20_write_byte(0xCC); ds18b20_write_byte(0xBE); // 读暂存器 uint8_t lo = ds18b20_read_byte(); uint8_t hi = ds18b20_read_byte(); int16_t raw = (hi << 8) | lo; return raw * 0.0625f; // 12 位分辨率,1 LSB = 0.0625°C }逻辑说明:如果系统只有一个 DS18B20,0xCC 跳过 ROM 没问题;如果以后挂多个传感器,需要改成读取序列号后精确匹配。转换时间根据分辨率不同,9 位只需 93.75ms,12 位需要 750ms,这里为了演示流畅故意只等 100ms,但真实项目建议等待 750ms 或读取忙标志再继续,不然可能采到上一次的旧值。返回 -999.0f 是为了让上位机显示“传感器异常”,而不是把异常数据画成温度曲线。
延时函数的精度直接影响单总线时序。我习惯用__delay_cycles()而不是delay(),因为它在关中断和低功耗模式下也能保证精确。
3.4 BH1750 光照读取:模拟 I2C 与命令解析
BH1750 的 I2C 可以用硬件 USCI,也可以模拟。考虑到 MSP430G2553 的引脚复用问题,这里用模拟 I2C 最省事,两根线用普通 GPIO 翻转即可:
#define BH1750_ADDR 0x23 // 模块 ADDR 接地时地址 uint16_t read_light(void) { i2c_start(); i2c_write(BH1750_ADDR << 1 | 0); // 地址 + 写 i2c_write(0x10); // 连续 H 分辨率模式 i2c_stop(); delay_ms(180); // 典型转换时间 120ms,留余量 i2c_start(); i2c_write(BH1750_ADDR << 1 | 1); // 地址 + 读 uint8_t msb = i2c_read(1); // 读高字节,发送应答 uint8_t lsb = i2c_read(0); // 读低字节,发送非应答 i2c_stop(); return (msb << 8) | lsb; // 原始码 }逻辑说明:0x10 对应连续高分辨率模式,实际光照值lux = 原始值 / 1.2。比如原始值 1200,光照强度就是 1000 lux。I2C 读时序中,倒数第二个字节要回 ACK,最后一个字节要回 NACK,否则设备会一直误以为主机还要读数据。模拟 I2C 没有硬件模块自动处理,所以i2c_read(1)和i2c_read(0)的区别必须写清楚。
如果读回来的数据一直是 0xFF,先查 ADDR 脚电平,再查上拉电阻。很多同学在这卡半小时,最后发现是模块地址写成了 0x5C,而实际模块 ADDR 接的是高电平,两个地址来回换一下就好。
3.5 滑动平均滤波与异常值剔除
传感器原始数据直接发出去,温度曲线和光照曲线会有明显毛刺。DS18B20 长时间使用后偶尔会蹦出一个错误的边界值,BH1750 受光源频闪影响也会波动。我用 8 点滑动平均做处理:
#define FILTER_N 8 uint16_t filter_push(uint16_t *samples, uint8_t *index, uint32_t *sum, uint16_t new_value) { if (*index < FILTER_N) { *sum += new_value; samples[(*index)++] = new_value; return *sum / (*index); // 窗口未满时返回已采集均值 } uint8_t old_pos = *index % FILTER_N; *sum -= samples[old_pos]; // 去掉最旧值 *sum += new_value; // 加入新值 samples[old_pos] = new_value; *index = old_pos + 1; return *sum / FILTER_N; }逻辑说明:窗口未满时直接返回当前均值,避免系统刚上电时前几秒曲线从 0 开始跳。窗口大小 8 对应 2 秒采集周期,约 16 秒的平滑窗口,既能压住毛刺,又不会让真实温度变化显得迟钝。如果你发现现场数据还是有跳变,可以先把窗口加到 16,但对应延迟也会加大,答辩时要能说清这个取舍。
3.6 无线数据包格式与校验
采集到的温度原始码和光照原始码都要组包发送。数据包必须包含帧头、设备 ID、数据、校验,否则接收端无法区分“真正的一包数据”和“垃圾字节”。本方案用固定 8 字节包:
| 偏移 | 含义 | 说明 |
|---|---|---|
| 0 | 帧头 | 固定 0xAA |
| 1 | 设备 ID | 0x01,预留多节点 |
| 2 | 温度高字节 | int16 高 8 位 |
| 3 | 温度低字节 | int16 低 8 位 |
| 4 | 光照高字节 | uint16 高 8 位 |
| 5 | 光照低字节 | uint16 低 8 位 |
| 6 | 状态字节 | 电量或错误标志 |
| 7 | 校验和 | 0-6 字节累加和取反 |
组包和校验函数如下:
uint8_t make_packet(uint8_t *buf, int16_t temp_raw, uint16_t lux_raw, uint8_t status) { buf[0] = 0xAA; buf[1] = 0x01; buf[2] = (uint8_t)((uint16_t)temp_raw >> 8); buf[3] = (uint8_t)(temp_raw & 0xFF); buf[4] = (uint8_t)(lux_raw >> 8); buf[5] = (uint8_t)(lux_raw & 0xFF); buf[6] = status; uint8_t sum = 0; for (int i = 0; i < 7; i++) sum += buf[i]; buf[7] = ~sum; return 8; }校验和不用 CRC,因为数据长度只有 8 字节,CRC 的表会占用额外 ROM,淡季简单累加和足够满足答辩要求。接收端校验失败直接丢弃整包,避免错误数据进入上位机曲线。
3.7 nRF24L01 寄存器配置与发送流程
nRF24L01 的配置比较繁琐,很多现成驱动把寄存器写成黑匣子。实际最影响距离和稳定性的三个参数是通道、空中速率和发射功率:
nrf24_config(40, 8); // RF_CH=40,载荷宽度 8 字节 nrf24_set_pipe(0, 8); // 使能管道 0,用于自动应答 nrf24_set_power(3); // 0dBm 发射功率 nrf24_set_rate(250); // 250kbps 空中速率参数说明:空中速率选 250kbps 而不是 2Mbps,距离能提升不少。速率越低,接收灵敏度越高,在室内隔一堵墙时尤其明显。2Mbps 模式下数据看起来传得快,但丢包率会成倍上升。发射功率默认 0dBm 足够,不要调最高档,否则电源纹波会把 ADC 读数拖乱。
发送端发送循环:
void nrf_send_packet(uint8_t *buf, uint8_t len) { P2OUT |= BIT0; // CE 拉高 delay_us(10); P2OUT &= ~BIT0; // CE 拉低,进入发送状态 while (!(nrf24_status() & 0x20)) { } // 等待 TX_DS 位置位 nrf24_clear_irq(); // 清中断,否则下次发送会误判 }这里的常见问题是没有清 TX_DS 中断。第一次发送成功后,状态寄存器里的发送完成位始终是 1,第二次进入 while 循环会直接跳过,结果数据根本没发出去但代码以为发送成功。写驱动时务必在每次发送后读 STATUS、写 1 清中断。
3.8 低功耗调度:2 秒采集一次
发送节点并不需要一直运行,2 秒采一次足够演示环境温光变化。采用 WDT 定时唤醒 + LPM3 休眠:
// 主循环 while (1) { float temp = read_temperature(); uint16_t lux = read_light(); // 滤波、组包、发送 __bis_SR_register(LPM3_bits | GIE); // 进入 LPM3 // 唤醒后从这里继续 }WDT 配置为间隔模式:
WDTCTL = WDTPW | WDT_MDLY_32MS; // 32ms 间隔 #pragma vector=WDT_VECTOR __interrupt void wdt_isr(void) { wdt_count++; if (wdt_count >= 62) { // 约 2 秒 wdt_count = 0; __bic_SR_register_on_exit(LPM3_bits); // 退出低功耗 } }进入 LPM3 前要把 ADC10 使能位清零,nRF24L01 的 CE 拉低,所有不用的 GPIO 设为输出低电平,否则光是浮空引脚的漏电就能让休眠电流从 1μA 涨到 5mA。唤醒后 DCO 会有一点起振时间,所以在读取传感器前加一个短暂延时,避免首次 I2C 读取失败。
4. 接收端与上位机:串口解析、校验与实时曲线
4.1 接收节点硬件与串口接线
接收节点同样用 MSP430G2553,nRF24L01 的引脚映射和发送端保持一致:CE P2.0、CSN P2.1、SCK P2.2、MOSI P2.3、MISO P2.4、IRQ P2.5。UART 使用 P1.1 接收、P1.2 发送,通过 USB 转 TTL 模块连接到电脑。
串口接线注意交叉连接:接收节点 TX 接 USB 转 TTL 的 RX,接收节点 RX 接 USB 转 TTL 的 TX,GND 必须共地。如果不共地,串口电平参考点不一致,上位机只能收到乱码。波特率选择 9600,因为 8 字节数据包按 2 秒一帧传,9600 完全够用,而且长距离 USB 转 TTL 下更稳定。
4.2 无线接收与校验判断
接收端主循环持续监听 nRF24L01。收到数据包后,先判断帧头 0xAA,再计算校验和,校验不通过直接丢弃:
void process_rf(void) { if (nrf24_irq_active()) { nrf24_read_payload(rx_buf, 8); if (rx_buf[0] == 0xAA && verify_checksum(rx_buf, 8)) { uart_send(rx_buf, 8); // 转发给上位机 } nrf24_clear_irq(); } }逻辑说明:verify_checksum对前 7 字节做累加和,补码后与第 8 字节比对。校验失败时什么都不做,也不计数。现场演示时可以人为在空中干扰一下,让数据停下来,然后说明“校验失败直接丢弃,所以上位机不会出现乱码”。这种细节在答辩时很加分。
4.3 上位机串口协议与 Python 解析
上位机用 Python 写最简单,pyserial 读串口,matplotlib 画图。解析逻辑要和 3.6 节的数据包格式严格对应:
import serial import struct ser = serial.Serial('COM3', 9600, timeout=1) def parse_packet(data): if len(data) < 8 or data[0] != 0xAA: return None checksum = (~sum(data[:7])) & 0xFF if checksum != data[7]: return None temp_raw = struct.unpack('>h', data[2:4])[0] lux_raw = struct.unpack('>H', data[4:6])[0] return temp_raw * 0.0625, lux_raw / 1.2代码说明:struct.unpack('>h')是有符号大端温度原始值,>H是无符号大端光照原始值。换算关系和发送端完全一致。如果上位机显示的温度符号不对,优先检查字节序,而不是怀疑传感器坏了。
串口打开参数里timeout=1很关键,没有它线程会阻塞在读取上,绘图界面容易假死。实际项目里我还会把串口读取放到独立线程,避免 UI 卡顿。
4.4 实时曲线显示与 CSV 日志
实时绘图用 matplotlib 的FuncAnimation:
import matplotlib.pyplot as plt from matplotlib.animation import FuncAnimation times = [] temps = [] lights = [] def update(frame): data = ser.read(8) parsed = parse_packet(data) if parsed: temp, lux = parsed times.append(len(times)) temps.append(temp) lights.append(lux) ax1.clear() ax1.plot(times, temps, label='温度 °C') ax2.clear() ax2.plot(times, lights, label='光照 lx')逻辑说明:两个子图画在同一窗口,左轴温度、右轴光照,或者上下排列更清晰。光照强度范围大,温度范围主要集中在 0 到 50°C,共用一条坐标轴会把温度曲线压平,所以分开画。真实答辩时,曲线随手指捏住温度传感器和手电筒照射光伏传感器变化,现场效果非常直观。
数据日志我建议同步写 CSV,每收到一帧就追加一行:
时间,温度,光照 1,26.3,450 2,26.5,1200这样验收时除了现场看曲线,还能拿日志文件做丢包率统计,给评委一个可量化的数据表。
5. 避坑指南:采样跳变、无线距离不足与低功耗翻车点
5.1 现象:光照读数像心率一样跳
现象:BH1750 或光敏电阻采到的光照值在 300、500、1200 之间来回跳,曲线看起来像锯齿。原因可能是 I2C 读取时序不稳定,也可能是传感器电源被 nRF24L01 发射瞬间拉低,造成转换结果异常。解决方法是先给传感器供电脚并一个 100nF 电容,再把读取函数改成连续读两次取均值;如果用的是光敏电阻方案,检查分压电阻到 ADC 引脚的引线长度,尽量控制在 10cm 以内。
5.2 现象:DS18B20 上电后第一次读总返回 85°C
现象:系统一上电,上位机温度立刻显示 85°C,过几秒才正常。原因是 DS18B20 上电后暂存器默认值是 85,转换命令发出后需要等待转换完成,而你代码里只延时 10ms 就去读。解决方法是上电后先做一次完整转换并丢弃第一帧数据,发送端等 750ms 再进入主循环。我一般还会在代码里加一个“预热标志”,前 3 次温度读取结果只滤波不发送,保证演示时曲线从真实温度开始。
5.3 现象:I2C 读 BH1750 卡死在等待应答
现象:程序跑到 I2C 发送地址后一直停在 ACK 等待,看门狗没关就整板复位。原因通常是引脚上拉未使能、模块 ADDR 地址电平不对,或者 P1.6/P1.7 被复用成 JTAG 功能。解决方法是先查 P1SEL 是否置 0,再确认上拉电阻,最后把 BH1750 地址从 0x23 换到 0x5C 测试。如果仍然卡死,用示波器看 SDA 线空闲电平,空闲电平不是 3.3V 就说明上拉没生效。
5.4 现象:无线传输距离只有几米
现象:现场测试走到三五米数据就断了,回到开发板旁边又恢复。原因通常是空中速率设成了 2Mbps、天线周围有铺铜或杜邦线缠绕、发送功率调到了最大导致电源跌落。解决方法是把速率降到 250kbps,天线区域净空,电源端加 10μF 电容;同时检查 nRF24L01 和 MCU 是否真正共地。很多模块插在杜邦线上,地线电阻偏大,收发瞬间地电位跳动,距离会直接减半。
5.5 现象:进入 LPM3 后功耗还有 6mA
现象:万用表串在电池端,发现休眠电流高达 6mA,和理论值差了几千倍。原因是没有把未用 GPIO 固定电平、nRF24L01 的 CE 还拉高着、ADC10 没有关闭、以及仿真器仍在供电。解决方法是把所有未用的 P1、P2 引脚设为输出低,P2.0 CE 拉低,ADC10CTL0 &= ~ENC关闭转换,烧录后拔掉 LaunchPad 仿真器部分再测量。测功耗最怕的是仿真器通过调试接口偷偷供电,测出来的数据全是假的。
6. 验收与答辩:功能清单、指标测试与现场演示方法
6.1 功能验收清单
验收不能只看“能出数据”。我建议做一张表格,逐项打钩:
| 验收项 | 测试方法 | 通过标准 |
|---|---|---|
| 温度测量 | 与标准温度计对比 | 0 到 50°C 误差 ±0.5°C |
| 光照测量 | 与手机照度计对比 | 0 到 2000 lx 误差 10% 内 |
| 无线传输 | 空旷场地拉距 | 250kbps 下稳定 30 米 |
| 丢包率 | 持续运行 1 小时 | 丢包率低于 1% |
| 低功耗 | 万用表测休眠电流 | 低于 5μA |
| 上位机显示 | 温度变动手捏传感器 | 曲线实时刷新且无异常跳点 |
温度测量的标准很简单:把 DS18B20 和水银温度计放同一杯温水里,读数稳定后记录差值。光照用手机 App 对比即可,不需要专业照度计。
6.2 现场答辩演示顺序
演示顺序我总结为“四步走”:先上电打开上位机,看到两路曲线缓慢波动;然后用手指捏住 DS18B20,温度曲线在几秒内从 26°C 涨到 31°C;接着打开手机手电筒照 BH1750,光照曲线从 200 lx 跳到 1500 lx;最后把发送节点拿到 20 米外,数据依然稳定刷新,证明无线传输有效。每一步对应一个验收指标,依次验证温度采集、光照采集、无线传输和上位机,逻辑非常清晰。
6.3 评委常见提问与应对
评委最常问“为什么不用蓝牙”“数据丢了怎么办”“误差是多少”。应对时有几个固定说法:不用蓝牙是因为蓝牙从机连接过程复杂,不适合设备断电重连;丢包靠帧头加校验和,校验失败直接丢弃,统计丢包率;误差来源是 DS18B20 本身的 ±0.5°C 和 BH1750 的分辨率,而非 MCU 处理引入误差。预先背熟这几个答案,比临场思考稳得多。
这次项目里我最后悔的是把无线模块放在天线区旁边的地线上,导致第一次拉距测试只有 8 米,当场翻车。从那以后我每次做无线采集项目,都会先画一遍“电源到天线”的路径,再把校验和塞进每一帧数据,确认这两点之后才敢去答辩现场。希望帮到你。
本文还有配套的精品资源,点击获取