拆分TinyOS RadioCountToLeds为收发独立应用后无法运行的问题
拆分TinyOS RadioCountToLeds为收发独立应用后无法运行的问题排查与修复
我帮你梳理了拆分后代码的几个核心问题,这些问题导致了程序无法正常运行,下面逐个说明并给出修复方案:
核心问题点
1. 头文件名称不匹配
你的头文件实际命名为RadioCountToLed.h,但收发应用的代码中均使用#include "RadioCountToLeds.h"(多了末尾的s)。在C语言编译阶段,文件名必须完全匹配,这会直接导致编译器找不到radio_count_msg_t结构体和AM_RADIO_COUNT_MSG常量的定义,编译失败。
2. 接收应用配置文件接口绑定缺失
接收模块RadioCountToLedsC声明使用了Boot、Receive、Packet接口,但你的接收应用配置文件RadioCountToLedsAppC.nc中只绑定了Leds接口到LedsC,其他关键接口都没有绑定到对应的实现组件:
Boot接口需要绑定到MainC.Boot才能触发启动事件Receive接口需要绑定到AMReceiverC才能接收数据包Packet接口需要绑定到AMReceiverC才能获取数据包 payload
没有这些绑定,模块的接口没有实际的实现载体,程序无法完成初始化,也无法接收任何数据包。
3. 发送应用冗余组件与定时器重复启动
- 发送应用的配置中包含了
AMReceiverC,但发送逻辑不需要接收功能,属于冗余配置,会浪费节点资源。 - 发送模块的
Boot.booted和AMControl.startDone中都调用了MilliTimer.startPeriodic(250),重复启动定时器可能导致触发频率异常或逻辑冲突。
修复后的完整代码
第一步:统一头文件名称
将头文件重命名为RadioCountToLeds.h(保持和代码中include一致),内容不变:
#ifndef RADIO_COUNT_TO_LEDS_H #define RADIO_COUNT_TO_LEDS_H typedef nx_struct radio_count_msg { nx_uint16_t counter; } radio_count_msg_t; enum { AM_RADIO_COUNT_MSG = 6, }; #endif
修复后的接收应用
RadioCountToLedsC.nc(模块代码,仅修正头文件include)
#include "Timer.h" #include "RadioCountToLeds.h" module RadioCountToLedsC @safe() { uses { interface Leds; interface Boot; interface Receive; interface Packet; } } implementation { message_t packet; uint16_t counter = 0; event void Boot.booted() { } event message_t* Receive.receive(message_t* bufPtr, void* payload, uint8_t len) { dbg("RadioCountToLedsC", "Received packet of length %hhu.\n", len); if (len != sizeof(radio_count_msg_t)) { return bufPtr; } else { radio_count_msg_t* rcm = (radio_count_msg_t*)payload; call Leds.led0On(); if (rcm->counter%3 != 0) { call Leds.led0Off(); } call Leds.led1On(); if (rcm->counter%3 != 1) { call Leds.led1Off(); } call Leds.led2On(); if (rcm->counter%3 != 2) { call Leds.led2Off(); } return bufPtr; } } }
RadioCountToLedsAppC.nc(配置文件,补充接口绑定)
#include "RadioCountToLeds.h" configuration RadioCountToLedsAppC {} implementation { components MainC, RadioCountToLedsC as App, LedsC; components new AMReceiverC(AM_RADIO_COUNT_MSG); components ActiveMessageC; // 绑定所有使用的接口到对应实现组件 App.Boot -> MainC.Boot; App.Receive -> AMReceiverC; App.Packet -> AMReceiverC; App.Leds -> LedsC; }
修复后的发送应用
RadioCountToLedsC.nc(模块代码,修复定时器重复启动)
#include "Timer.h" #include "RadioCountToLeds.h" module RadioCountToLedsC @safe() { uses { interface Leds; interface Boot; interface AMSend; interface Timer<TMilli> as MilliTimer; interface SplitControl as AMControl; interface Packet; } } implementation { message_t packet; bool locked; uint16_t counter = 0; event void Boot.booted() { // 先启动ActiveMessage,成功后再启动定时器 call AMControl.start(); } event void AMControl.startDone(error_t err) { if (err == SUCCESS) { call MilliTimer.startPeriodic(250); } else { call AMControl.start(); } } event void AMControl.stopDone(error_t err) { // do nothing } event void MilliTimer.fired() { counter = (counter < 100) ? counter + 1 : 0; dbg("RadioCountToLedsC", "RadioCountToLedsC: timer fired, counter is %hu.\n", counter); if (locked) { return; } radio_count_msg_t* rcm = (radio_count_msg_t*)call Packet.getPayload(&packet, sizeof(radio_count_msg_t)); if (rcm == NULL) { return; } rcm->counter = counter; if (call AMSend.send(AM_BROADCAST_ADDR, &packet, sizeof(radio_count_msg_t)) == SUCCESS) { dbg("RadioCountToLedsC", "RadioCountToLedsC: packet sent.\n"); locked = TRUE; } } event void AMSend.sendDone(message_t* bufPtr, error_t error) { if (&packet == bufPtr) { locked = FALSE; } } }
RadioCountToLedsAppC.nc(配置文件,移除冗余组件)
#include "RadioCountToLeds.h" configuration RadioCountToLedsAppC {} implementation { components MainC, RadioCountToLedsC as App, LedsC; components new AMSenderC(AM_RADIO_COUNT_MSG); components new TimerMilliC(); components ActiveMessageC; App.Boot -> MainC.Boot; App.AMSend -> AMSenderC; App.AMControl -> ActiveMessageC; App.Leds -> LedsC; App.MilliTimer -> TimerMilliC; App.Packet -> AMSenderC; }
验证步骤
- 将修复后的接收应用编译烧录到一台TelosB节点,发送应用编译烧录到另一台节点。
- 通电后,发送节点会每隔250ms广播计数值,接收节点收到后会根据计数值模3的结果点亮对应LED:
- 模3余0:LED0亮
- 模3余1:LED1亮
- 模3余2:LED2亮
内容的提问来源于stack exchange,提问作者Qu峄慶 Chí Nguyện
相关产品推荐
相关产品推荐

