STM32CubeIDE中toggleButton1无法退出while循环问题求助
核心问题
你的代码存在两个致命问题:
- 阻塞式延迟占用CPU:
HAL_Delay()是阻塞函数,进入while循环后,CPU会被持续占用在GPIO切换和延迟等待上,导致UI框架(比如TouchGFX)的事件处理线程无法运行,按钮的点击事件得不到响应,toggleButton1.getState()的返回值自然不会更新。 - 状态检查时机不合理:即使UI能更新状态,你只在四次延迟(总计4秒)后才检查一次按钮状态,用户点击后最多要等4秒才可能触发退出逻辑,体验极差,甚至因为阻塞根本无法更新状态。
解决方案
方案1:非阻塞式逻辑(推荐)
放弃阻塞延迟,用系统滴答定时器记录时间戳,实现非阻塞的GPIO切换,让UI线程能正常处理事件。
// 在Screen1View类中添加成员变量 uint32_t lastToggleTime = 0; bool isRelayRunning = false; uint8_t relayStep = 0; void Screen1View::relay_1() { if(toggleButton1.getState()){ isRelayRunning = true; lastToggleTime = HAL_GetTick(); relayStep = 0; } else { isRelayRunning = false; // 退出时重置GPIO状态 HAL_GPIO_WritePin(GPIOD, GPIO_PIN_3, GPIO_PIN_RESET); HAL_GPIO_WritePin(GPIOJ, GPIO_PIN_2, GPIO_PIN_RESET); } } // 在Screen1View的tick函数中添加逻辑(TouchGFX会定时调用此函数) void Screen1View::tick() { if(isRelayRunning){ uint32_t currentTime = HAL_GetTick(); // 每1秒执行一步GPIO操作 if(currentTime - lastToggleTime >= 1000){ lastToggleTime = currentTime; switch(relayStep){ case 0: HAL_GPIO_WritePin(GPIOD, GPIO_PIN_3, GPIO_PIN_SET); break; case 1: HAL_GPIO_WritePin(GPIOD, GPIO_PIN_3, GPIO_PIN_RESET); break; case 2: HAL_GPIO_WritePin(GPIOJ, GPIO_PIN_2, GPIO_PIN_SET); break; case 3: HAL_GPIO_WritePin(GPIOJ, GPIO_PIN_2, GPIO_PIN_RESET); break; } relayStep = (relayStep + 1) % 4; // 实时检查按钮状态,触发退出 if(!toggleButton1.getState()){ isRelayRunning = false; HAL_GPIO_WritePin(GPIOD, GPIO_PIN_3, GPIO_PIN_RESET); HAL_GPIO_WritePin(GPIOJ, GPIO_PIN_2, GPIO_PIN_RESET); } } } }
方案2:阻塞循环中主动处理UI事件(临时调试用)
如果一定要保留阻塞逻辑,可在每次延迟后主动调用UI框架的事件处理函数,让按钮状态及时更新:
void Screen1View::relay_1() { if(toggleButton1.getState()){ while(1){ HAL_GPIO_WritePin(GPIOD, GPIO_PIN_3, GPIO_PIN_SET); HAL_Delay(1000); // 主动触发TouchGFX事件处理 touchgfx::HAL::getInstance()->task(); HAL_GPIO_WritePin(GPIOD, GPIO_PIN_3, GPIO_PIN_RESET); HAL_Delay(1000); touchgfx::HAL::getInstance()->task(); HAL_GPIO_WritePin(GPIOJ, GPIO_PIN_2, GPIO_PIN_SET); HAL_Delay(1000); touchgfx::HAL::getInstance()->task(); HAL_GPIO_WritePin(GPIOJ, GPIO_PIN_2, GPIO_PIN_RESET); HAL_Delay(1000); touchgfx::HAL::getInstance()->task(); if(toggleButton1.getState() == 0){ break; } } } else { HAL_GPIO_WritePin(GPIOD, GPIO_PIN_3, GPIO_PIN_RESET); } }
注意:此方法会导致UI响应卡顿,仅适合临时验证问题,长期使用优先选择方案1。
内容的提问来源于stack exchange,提问作者Amadej
相关产品推荐
相关产品推荐

