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

ESP32双核Core0执行程序时串口设置的频率变量被复位为0问题求助

问题根因
  • 非法栈访问篡改全局变量:你当前的逻辑是每次loop循环无论是否收到新串口数据,都会执行变长数组charBuf的创建、字符串转换和报文判断。当无新报文时incomSting为空,栈上分配的charBuf内存残留旧脏数据,大概率会误触发if(charBuf[0]=='S')的判断。后续strtok返回空指针时sscanf触发未定义行为,直接把频率变量、flag变量改写为0,严重时栈溢出直接覆盖全局变量内存。
  • 串口接收逻辑错误:while(Serial.available() > 1)的判断多余且不合理,Serial.readStringUntil('?')本身会读取直到遇到终止符或超时,你没有判断读取到的报文是否有效。
  • 变量修饰缺失:全局变量StepNr在Core0中持续修改,但未加volatile修饰,可能被编译器错误优化导致逻辑异常。
  • 无容错机制:未处理报文格式错误、strtok返回空的异常场景,一旦收到非法报文就会写坏变量。
修复方案
  1. 把报文解析逻辑完全移到串口读取成功的分支内,仅当收到有效报文时才执行解析,避免无意义的栈操作。
  2. 给StepNr添加volatile修饰,保证跨核访问的正确性。
  3. 增加报文合法性校验,确认strtok返回值非空再执行sscanf。
  4. 可选优化:使用FreeRTOS互斥锁保护共享变量,或者用队列传递参数,彻底避免跨核直接读写全局变量的风险。
修复后代码示例
// STEPPER 
int delaytime = 100;
volatile int StepNr = 0; // 加volatile修饰
String incomSting = "";

int Stepper1Pin = 12;
int Stepper2Pin = 14;
int Stepper3Pin = 27;

volatile int percentStp1 = 0;
volatile int percentStp2 = 0;
volatile int percentStp3 = 0;
volatile int flag = 0;

TaskHandle_t Task1;
void Task1code(void * parameter) 
{
  for(;;) 
  {
    while (flag == 1){
      //Run Steppers
      if(percentStp1 > StepNr)
      {
        digitalWrite(Stepper1Pin, HIGH);
      }
      if(percentStp2 > StepNr)
      {
        digitalWrite(Stepper2Pin, HIGH);
      }
      if(percentStp3 > StepNr)
      {
       digitalWrite(Stepper3Pin, HIGH);
      }  
     
      StepNr++; 
      delayMicroseconds(delaytime);
      digitalWrite(Stepper1Pin, LOW);
      digitalWrite(Stepper2Pin, LOW);
      digitalWrite(Stepper3Pin, LOW);
      delayMicroseconds(delaytime);

      Serial.println(percentStp1);
       
      if(StepNr > 100)
      { 
        StepNr = 0;
      }
    }
    // 空转加延时避免Core0占用过高
    delay(1);
  }
}
void setup()
{
  Serial.begin(9600);
  Serial.println("Start"); 

  //STEPPER
  xTaskCreatePinnedToCore(Task1code, "Task1", 10000, NULL, 0 , &Task1, 0); 
  pinMode(Stepper1Pin, OUTPUT); 
  pinMode(Stepper2Pin, OUTPUT); 
  pinMode(Stepper3Pin, OUTPUT); 
}

void loop() 
{
  // 仅当有串口数据时才读取
  if(Serial.available())
  {
    incomSting = Serial.readStringUntil('?');
    // 校验报文有效性
    if(incomSting.length() > 0 && incomSting[0] == 'S')
    {
      char charBuf[incomSting.length() + 1];
      incomSting.toCharArray(charBuf, incomSting.length() + 1);
      charBuf[0]='0';
      Serial.println("Stepper");   
      char *pch = strtok(charBuf,";");
      if(pch != NULL) sscanf(pch, "%d", &percentStp1);
      pch = strtok (NULL, ";");
      if(pch != NULL) sscanf(pch, "%d", &percentStp2);
      pch = strtok (NULL, ";");
      if(pch != NULL) sscanf(pch, "%d", &percentStp3);
      Serial.print("S1:"); 
      Serial.println(percentStp1); 
      Serial.print("S2:"); 
      Serial.println(percentStp2); 
      Serial.print("S3:"); 
      Serial.println(percentStp3); 
      incomSting = "";
      flag = 1;
    }
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 21:39:04