You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

STM32F469开发板While循环内电机无法停止的解决方法求助

问题

在STM32F469 DISCO开发板上使用SmartDrive库控制电机:

  • 原库默认电机运行5秒,点击停止按钮可正常提前停止,超时自动停。
  • 需求电机运行超5秒时,将smd.Run_Unlimited(SmartDrive_Motor_ID_1, SmartDrive_Dir_Reverse, 90);放入while循环后,停止按钮完全失效,无法停止电机。

有问题的代码如下:

#include <Arduino.h>
#include "ui.h"
#include <SmartDrive.h>

SmartDrive smd = SmartDrive(SmartDrive_DefaultAddress);

bool STOP01 =  true;
#define STOP02  0

void run01right(lv_event_t * e)
{
    // Your code here
    while (STOP01)
    {
    smd.Run_Unlimited(SmartDrive_Motor_ID_1, SmartDrive_Dir_Reverse, 90);
    }
    STOP01 = true;
}


void stopmotor01(lv_event_t * e)
{
    // Your code here
    STOP01 = false;
    smd.StopMotor(SmartDrive_Motor_ID_1, SmartDrive_Action_Brake);
    STOP01 = true;

}

void run01left(lv_event_t * e)
{
    // Your code here
    while (STOP01)
    {
    smd.Run_Unlimited(SmartDrive_Motor_ID_1, SmartDrive_Dir_Forward, 90);
    }
    STOP01 = true;
}

原因分析

问题核心是事件回调里的while循环阻塞了LVGL的主线程:LVGL的UI事件(比如按钮点击)都在同一个线程处理,run01right/run01left里的while循环会持续占用CPU,导致stopmotor01的回调根本得不到执行机会,自然无法停止电机。

解决方案:利用Arduino的loop()实现非阻塞控制

不需要中断或者额外任务,直接用全局变量标记电机运行状态,把电机控制逻辑放到loop()里执行,事件回调只负责修改状态变量。

实现代码示例

#include <Arduino.h>
#include "ui.h"
#include <SmartDrive.h>

SmartDrive smd = SmartDrive(SmartDrive_DefaultAddress);

// 定义电机状态:0=停止,1=正转,2=反转
int motor_state = 0;

void run01right(lv_event_t * e)
{
    motor_state = 2; // 设置为反转状态
}

void stopmotor01(lv_event_t * e)
{
    motor_state = 0; // 设置为停止状态
    smd.StopMotor(SmartDrive_Motor_ID_1, SmartDrive_Action_Brake);
}

void run01left(lv_event_t * e)
{
    motor_state = 1; // 设置为正转状态
}

void setup()
{
    // 初始化代码(如果有)
}

void loop()
{
    // 处理LVGL事件循环(必须保留,确保UI响应)
    lv_timer_handler();
    
    // 根据状态控制电机
    switch(motor_state)
    {
        case 1:
            smd.Run_Unlimited(SmartDrive_Motor_ID_1, SmartDrive_Dir_Forward, 90);
            break;
        case 2:
            smd.Run_Unlimited(SmartDrive_Motor_ID_1, SmartDrive_Dir_Reverse, 90);
            break;
        default:
            // 停止状态无需重复调用StopMotor,除非需要
            break;
    }
    
    // 可选短延时,避免CPU占用过高
    delay(10);
}

关键说明

  1. 事件回调只做状态标记,不执行阻塞逻辑,保证LVGL主线程能及时处理按钮点击事件。
  2. loop()里的lv_timer_handler()必须调用,这是LVGL处理UI更新和事件的核心函数。
  3. 用状态变量替代原有的STOP01标志,逻辑更清晰,也彻底避免了循环阻塞问题。

内容的提问来源于stack exchange,提问作者neuberfran

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 13:54:21