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

ESP32中FreeRTOS任务调用函数异常问题求助

ESP32 FreeRTOS添加步进电机微细分后程序无响应问题分析与解决

问题背景

在ESP32上运行FreeRTOS程序控制步进电机与LED,未引入微细分时两个任务运行正常;添加微细分功能后,move_routine任务调用move函数,程序完全无响应(LED不闪烁、电机不转动)。

核心原因

  1. LEDC通道未初始化
    代码中使用ledcWrite控制电机引脚,但未在setup中调用ledcSetup初始化LEDC通道的频率和分辨率,导致LEDC驱动无法正常工作,甚至引发系统异常。
  2. move_routine任务长期占用CPU
    move函数中的wait参数未被使用,move_routine的循环中没有任何延时操作,同优先级的led_task无法获得CPU时间片,导致LED无法闪烁;同时电机控制逻辑也因LEDC未初始化完全失效。
  3. 无用资源占用
    代码中初始化了Stepper库实例myStepper但未实际使用,浪费系统资源。

解决方案

1. 初始化LEDC通道

在setup函数中为所有用到的LEDC通道配置参数,并绑定对应引脚:

// 初始化LEDC通道,频率1000Hz,12位分辨率(对应0-4095)
ledcSetup(LEDC_CHANNEL_0, 1000, 12);
ledcSetup(LEDC_CHANNEL_1, 1000, 12);
ledcSetup(LEDC_CHANNEL_2, 1000, 12);
ledcSetup(LEDC_CHANNEL_3, 1000, 12);

// 将引脚绑定到对应LEDC通道
ledcAttachPin(A1A, LEDC_CHANNEL_0);
ledcAttachPin(A1B, LEDC_CHANNEL_1);
ledcAttachPin(B1A, LEDC_CHANNEL_2);
ledcAttachPin(B2A, LEDC_CHANNEL_3);

2. 在move函数中添加延时

使用vTaskDelayMicroseconds处理wait参数,让任务主动释放CPU,给其他任务执行机会:

void move(int stepnumber, int MAXpower, int wait) {
    // 原有的计算和引脚控制逻辑...
    
    // 添加延时,释放CPU给其他任务
    vTaskDelayMicroseconds(wait);
}

3. 清理无用代码

删除未使用的Stepper库相关代码,减少资源占用:

// 移除以下无用代码
// #include <Stepper.h>
// const int stepsPerRev = 200;
// Stepper myStepper(stepsPerRev, 14,27,26,25);
// myStepper.setSpeed(60);

4. 优化变量作用域

将全局变量Pa、Pb改为move函数的局部变量,避免全局变量的潜在冲突:

void move(int stepnumber, int MAXpower, int wait) {
    int Pa = (sin(stepnumber*0.098174)*MAXpower);
    int Pb = (cos(stepnumber*0.098174)*MAXpower);
    
    // 原有的引脚控制逻辑...
}

修改后的完整代码

#include <Arduino.h>

/*================PIN DEFINITIONS================*/
#define LEDC_CHANNEL_0  0
#define LEDC_CHANNEL_1  1
#define LEDC_CHANNEL_2  2
#define LEDC_CHANNEL_3  3

const int A1A =  14;
const int A1B = 27;
const int B1A = 26;
const int B2A = 25;
const int ledPin = 33;

/*================VARIABLE DEFINITIONS================*/
int stepnumber = 0;

/*================Function Definitions================*/
  
//Analogwrite using LEDC capabilities
void ledcAnalogWrite(uint8_t channel, uint32_t value, uint32_t valueMax = 255) {
    //calculation of duty cycle
    uint32_t duty = (4095/valueMax)*min(value, valueMax); 
    ledcWrite(channel,duty);
}

void move(int stepnumber, int MAXpower, int wait) {
    int Pa = (sin(stepnumber*0.098174)*MAXpower);
    int Pb = (cos(stepnumber*0.098174)*MAXpower);

    if (Pa>0)
    { 
      ledcAnalogWrite(LEDC_CHANNEL_0,Pa);
      ledcAnalogWrite(LEDC_CHANNEL_1,0);
    }
    else
    {
      ledcAnalogWrite(LEDC_CHANNEL_0,0);
      ledcAnalogWrite(LEDC_CHANNEL_1,abs(Pa));
    }
    
    if (Pb>0)
    {
      ledcAnalogWrite(LEDC_CHANNEL_2,Pb);
      ledcAnalogWrite(LEDC_CHANNEL_3,0);
    }
    else
    {
      ledcAnalogWrite(LEDC_CHANNEL_2,0);
      ledcAnalogWrite(LEDC_CHANNEL_3,abs(Pb));
    }
    // 添加延时释放CPU
    vTaskDelayMicroseconds(wait);
}

void move_routine(void *parameters) {
  while(1) {
    for (int i=0; i<3199; i++)
    {
      stepnumber++;
      move(stepnumber,255,250);
    }

    vTaskDelay(3000/portTICK_PERIOD_MS);
    for (int i=0; i<1599; i++)
    { 
      stepnumber--;
      move(stepnumber,255,1000);
    }

    vTaskDelay(3000/portTICK_PERIOD_MS);
  }
}

void led_task(void * parameters){
  while(1){
    digitalWrite(ledPin, HIGH); 
    vTaskDelay(500/portTICK_PERIOD_MS); 
    digitalWrite(ledPin, LOW); 
    vTaskDelay(500/portTICK_PERIOD_MS);
  }
}

void setup(){
  pinMode(ledPin, OUTPUT);
  Serial.begin(115200);

  // 初始化LEDC通道
  ledcSetup(LEDC_CHANNEL_0, 1000, 12);
  ledcSetup(LEDC_CHANNEL_1, 1000, 12);
  ledcSetup(LEDC_CHANNEL_2, 1000, 12);
  ledcSetup(LEDC_CHANNEL_3, 1000, 12);

  // 绑定引脚到LEDC通道
  ledcAttachPin(A1A, LEDC_CHANNEL_0);
  ledcAttachPin(A1B, LEDC_CHANNEL_1);
  ledcAttachPin(B1A, LEDC_CHANNEL_2);
  ledcAttachPin(B2A, LEDC_CHANNEL_3);

  xTaskCreatePinnedToCore(
    move_routine, 
    "Move Routine",
    8192,
    NULL,
    1,
    NULL, 
    1
  );

  xTaskCreatePinnedToCore(
    led_task, 
    "LED Task", 
    1024, 
    NULL, 
    1, 
    NULL, 
    1
  );
}

void loop(){

}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 15:01:05