ESP32蓝牙接收转义字符串转可识别Hex格式并通过RS232发送问题
问题分析
你遇到的核心问题是:蓝牙接收到的是包含转义序列的文本字符串,而非编译器解析后的实际字节流。
- 当你在代码中直接写
Serial2.write("\e\x34\x54\x45\x53\x54\r")时,C++编译器会自动把转义序列(比如\e、\x34、\r)转换成对应的ASCII字节:0x1B(ESC)、0x34、0x54、0x45、0x53、0x54、0x0D(CR),这正是接收器需要的命令格式。 - 但蓝牙接收到的
"\e\x34\x54\x45\x53\x54\r"是一串普通字符:\、e、\、x、3、4、\、x、5、4...,直接用message.c_str()发送的是这些字符本身,接收器自然无法识别。
解决方案
需要实现一个转义序列解析函数,把蓝牙收到的文本字符串转换成实际的字节数组,再通过Serial2发送。以下是完整的实现代码:
// 解析转义字符串为字节数组 size_t parseEscapedString(const String& input, uint8_t* output, size_t maxOutputSize) { size_t outputIndex = 0; size_t inputLength = input.length(); for (size_t i = 0; i < inputLength; i++) { if (input[i] == '\\' && i + 1 < inputLength) { // 识别转义字符 switch (input[i+1]) { case 'e': // ESC字符,对应0x1B if (outputIndex < maxOutputSize) { output[outputIndex++] = 0x1B; } i++; // 跳过下一个字符 break; case 'r': // 回车符,对应0x0D if (outputIndex < maxOutputSize) { output[outputIndex++] = 0x0D; } i++; break; case 'n': // 换行符,对应0x0A(如果需要的话) if (outputIndex < maxOutputSize) { output[outputIndex++] = 0x0A; } i++; break; case 'x': // 十六进制字节,格式\xXX if (i + 3 <= inputLength) { // 提取两位十六进制字符 String hexStr = input.substring(i+2, i+4); uint8_t byteVal = strtol(hexStr.c_str(), nullptr, 16); if (outputIndex < maxOutputSize) { output[outputIndex++] = byteVal; } i += 3; // 跳过\xXX的三个字符 } break; default: // 未知转义,直接保留原字符 if (outputIndex < maxOutputSize) { output[outputIndex++] = input[i]; } break; } } else { // 普通字符,直接复制 if (outputIndex < maxOutputSize) { output[outputIndex++] = input[i]; } } } return outputIndex; } // 蓝牙消息处理代码 void handleBTMessage() { if (SerialBT.available()) { String message = SerialBT.readStringUntil('\n'); // 去掉字符串末尾可能的换行符或空格 message.trim(); uint8_t commandBuffer[64]; // 足够存储你的命令,可按需调整大小 size_t commandLength = parseEscapedString(message, commandBuffer, sizeof(commandBuffer)); // 发送解析后的字节到RS232 Serial2.write(commandBuffer, commandLength); // 调试输出(可选) Serial.print("BT Message received: "); Serial.println(message); Serial.print("Parsed command length: "); Serial.println(commandLength); Serial.print("Parsed bytes (hex): "); for (size_t i = 0; i < commandLength; i++) { Serial.printf("%02X ", commandBuffer[i]); } Serial.println(); } } // 在loop函数中调用 void loop() { handleBTMessage(); // 其他代码... }
使用说明
- 把上述代码加入你的ESP32项目中,替换原有的蓝牙消息处理逻辑。
parseEscapedString函数会处理常见的转义序列:\e→ 0x1B(ESC)\r→ 0x0D(回车)\xXX→ 两位十六进制对应的字节(比如\x34→0x34)- 如果需要支持其他转义序列(比如
\n、\t),可以在switch中添加对应的case。
- 解析后的字节会存入
commandBuffer,然后通过Serial2.write(commandBuffer, commandLength)发送,这和你直接在代码中写硬编码命令的效果完全一致。
验证
使用上述代码后,蓝牙收到的"\e\x34\x54\x45\x53\x54\r"会被解析成:0x1B 0x34 0x54 0x45 0x53 0x54 0x0D,和你硬编码发送的字节完全相同,接收器应该会返回Test4的正确响应。
内容的提问来源于stack exchange,提问作者Captain Allergy
相关产品推荐
相关产品推荐

