Arduino双任务运行问题:downLinkDataHandle阻塞prepareTxFrame执行
问题描述
我使用Heltec AD-02设备,希望同时运行void downLinkDataHandle与prepareTxFrame(appPort);。其中downLinkDataHandle包含delay()语句,用于根据下行数据(字节0、1、2)设置LED点亮时长,但执行该函数时,delay()会阻塞prepareTxFrame(appPort);的执行。
修改后的代码
prepareTxFrame函数
/* Prepares the payload of the frame */ static void prepareTxFrame( uint8_t port ) { float battV = round((getBatteryVoltage() / 10) / 100); // 测量电池电压 appDataSize = 1; battV = battV * 10; // 准备编码 appData[0] = battV; // 存储电池电压对应字节 }
downLinkDataHandle函数
void downLinkDataHandle(McpsIndication_t *mcpsIndication) { int port = mcpsIndication->Port; if (port ==100) { int color = 255; uint32_t delay1=mcpsIndication->Buffer[0]<<16|mcpsIndication->Buffer[1]<<8|mcpsIndication->Buffer[2]; // LED点亮时长 Serial.print("Delay:"); Serial.println(delay1); uint32_t control = mcpsIndication->Buffer[3]; if (control == 1) { turnOnRGB(color, delay1); turnOffRGB(); delay(delay1); }; }; }
解决方案
要解决delay()阻塞问题,必须用非阻塞式延时替代阻塞式delay(),核心是利用millis()记录时间戳,在主循环中轮询判断延时是否结束,不占用CPU阻塞其他代码。
1. 添加全局状态变量
在代码顶部声明全局变量,用于跟踪LED状态和时间:
bool ledActive = false; // 标记LED是否处于点亮状态 unsigned long ledStartTime = 0; // LED点亮起始时间戳 uint32_t ledTargetDelay = 0; // 目标点亮时长 int ledColor = 255; // LED颜色参数
2. 修改downLinkDataHandle函数
移除阻塞式delay(),仅设置LED参数并启动计时:
void downLinkDataHandle(McpsIndication_t *mcpsIndication) { int port = mcpsIndication->Port; if (port == 100) { ledColor = 255; ledTargetDelay = mcpsIndication->Buffer[0]<<16 | mcpsIndication->Buffer[1]<<8 | mcpsIndication->Buffer[2]; Serial.print("Delay:"); Serial.println(ledTargetDelay); uint32_t control = mcpsIndication->Buffer[3]; if (control == 1) { // 启动LED点亮流程 ledActive = true; ledStartTime = millis(); turnOnRGB(ledColor, ledTargetDelay); } else { // 强制关闭LED ledActive = false; turnOffRGB(); } } }
3. 在主循环中添加非阻塞控制逻辑
在loop()函数中加入以下代码,实时检查并处理LED状态:
void loop() { // 保留原有LoRaWAN流程、prepareTxFrame调用等代码 // 非阻塞LED延时控制 if (ledActive) { if (millis() - ledStartTime >= ledTargetDelay) { ledActive = false; turnOffRGB(); } } }
关键说明
- 该方案下
downLinkDataHandle仅负责触发LED动作,不会阻塞后续代码,prepareTxFrame可正常执行。 - 确保
loop()函数中无其他阻塞式操作,保证轮询逻辑能及时响应。
内容的提问来源于stack exchange,提问作者Johan Scheepers
相关产品推荐
相关产品推荐

