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

Arduino如何将串口输入存入char数组并提取指定字符间内容?

嗨,我来帮你搞定这个串口适配的问题!你的原代码能正确提取静态字符串里的目标内容,但要适配串口输入,核心是要先解决串口流式数据的缓存问题——毕竟串口是逐字节接收的,不能直接像处理静态char*那样直接用strstr。另外先提一句原代码里的内存管理小bug,避免后续运行出问题。

先修复原代码的内存错误

你原代码里的target = ""; free(target);是有问题的:把target指向了常量字符串后再free,会触发未定义行为。正确的内存释放逻辑应该是:

if (target != NULL) {
  free(target);
  target = NULL; // 释放后置空,避免野指针
}

串口适配的核心思路

串口是逐字节接收数据,我们需要先把接收到的字节缓存到一个缓冲区里,直到确认收到了完整的数据包(比如可以通过超时判断、或者指定结束符,比如你示例里的#,或者约定数据包长度),再对缓冲区的完整字符串执行提取逻辑。

完整的适配代码示例

下面是适配串口的完整代码,我加了详细注释:

// 定义串口缓冲区,大小根据你的需求调整,这里设256字节
#define SERIAL_BUFFER_SIZE 256
char serialBuffer[SERIAL_BUFFER_SIZE];
int bufferIndex = 0;
const char *CHAR1 = "!";
const char *CHAR2 = "#";
char *target = NULL;

void setup() {
  Serial.begin(9600);
  // 初始化缓冲区
  memset(serialBuffer, 0, SERIAL_BUFFER_SIZE);
}

void loop() {
  // 读取串口数据,直到缓冲区满或者没有数据
  while (Serial.available() > 0 && bufferIndex < SERIAL_BUFFER_SIZE - 1) {
    char receivedChar = Serial.read();
    serialBuffer[bufferIndex++] = receivedChar;
    
    // 可选:如果我们知道数据包以某个字符结尾(比如#),可以在这里判断提前结束接收
    if (receivedChar == '#') {
      break;
    }
  }

  // 只有当缓冲区有数据时,才执行提取逻辑
  if (bufferIndex > 0) {
    // 给缓冲区加上字符串终止符,变成合法的C字符串
    serialBuffer[bufferIndex] = '\0';
    
    char *start, *end;
    if ((start = strstr(serialBuffer, CHAR1)) != NULL) {
      start += strlen(CHAR1);
      if ((end = strstr(start, CHAR2)) != NULL) {
        // 分配内存存储目标内容
        if (target != NULL) {
          free(target); // 先释放之前的内存,避免泄漏
          target = NULL;
        }
        target = (char*)malloc(end - start + 1);
        if (target != NULL) { // 检查malloc是否成功
          memcpy(target, start, end - start);
          target[end - start] = '\0';
          
          // 输出目标内容
          Serial.print("提取到的内容:");
          Serial.println(target);
        }
      }
    }
    
    // 重置缓冲区,准备接收下一包数据
    bufferIndex = 0;
    memset(serialBuffer, 0, SERIAL_BUFFER_SIZE);
  }

  // 程序空闲时的延迟,避免占用过多资源
  delay(10);
}

代码说明

  • 串口缓存:用serialBuffer存储接收到的所有字节,bufferIndex记录当前存储的位置,确保不会溢出缓冲区。
  • 结束判断:我加了一个判断,如果收到#就停止接收,这样能更快处理完整数据包;如果你的数据包没有固定结束符,可以改成超时判断(比如超过100ms没收到新数据就认为是完整数据包)。
  • 内存管理:每次提取前先释放之前的target内存,避免内存泄漏;并且检查malloc是否成功,防止内存分配失败导致的问题。
  • 兼容性:这个代码既可以处理串口输入,也可以轻松改回处理静态char*(只需要把serialBuffer换成你的静态字符串即可)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 08:52:32