From b45a262027bf173aab9b1382d9df329c31c1b0d7 Mon Sep 17 00:00:00 2001 From: Kinchin Fong Date: Sun, 10 Sep 2023 14:55:29 +0800 Subject: [PATCH] add UpperSerial --- README.md | 6 ++ include/UpperSerial.h | 24 ++++++++ src/UpperSerial.cpp | 136 ++++++++++++++++++++++++++++++++++++++++++ src/main.cpp | 10 +++- 4 files changed, 174 insertions(+), 2 deletions(-) create mode 100644 include/UpperSerial.h create mode 100644 src/UpperSerial.cpp diff --git a/README.md b/README.md index f250d9f..fe95bf6 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,7 @@ - DataRecorder: 数据读写接口 - ConfigManager: 配置项接口 - InterSerial: 与 STM32 通讯的串口功能 +- UpperSerial: 与上位机通讯的串口功能 ## 固件烧录流程 @@ -24,3 +25,8 @@ 4. 点击侧边栏的 PlatformIO 工具,在 `PROJECT TASKS` 选项卡下,点击 `esp32-s2-sensor-recorder` -> `Platform` -> `Upload Filesystem Image` 等待文件系统上传完成 5. 编译并上传代码固件 6. 手动 reset + +## 注意 + +1. 文件系统和固件烧录后会报一个错, `WARNING: ESP32-S2 chip was placed into download mode using GPIO0.` 因为 USB 烧录无法自动 reset。直接忽略即可。 +2. 与上位机通讯的串口,请在上位机打开 DTR 和 RTS 流控 diff --git a/include/UpperSerial.h b/include/UpperSerial.h new file mode 100644 index 0000000..818ea76 --- /dev/null +++ b/include/UpperSerial.h @@ -0,0 +1,24 @@ +#pragma once + +#include +#include +#include "DataRecorder.h" +#include "ConfigManager.h" + + +class UpperSerial +{ +public: + void Init(DataRecorder* rec, ConfigManager* cfg); + void Process(); + +private: + void CmdHandler(String cmdLine); + void ParseCmd(String cmd); + +private: + RingBuf ringBuffer; + String cmdLine; + DataRecorder* rec; + ConfigManager* cfg; +}; diff --git a/src/UpperSerial.cpp b/src/UpperSerial.cpp new file mode 100644 index 0000000..2ef2594 --- /dev/null +++ b/src/UpperSerial.cpp @@ -0,0 +1,136 @@ +#include "UpperSerial.h" + +#define MAX_CMD_LEN 200 + +void UpperSerial::Init(DataRecorder* r, ConfigManager* c) +{ + Serial.begin(); + cmdLine = ""; + rec = r; + cfg = c; +} + +void UpperSerial::Process() +{ + while (Serial.available()) { + ringBuffer.push(Serial.read()); + } + + while (ringBuffer.size() > 0) { + if (cmdLine.endsWith("\r\n")) { + cmdLine.clear(); + } + + uint8_t readByte; + ringBuffer.pop(readByte); + if (cmdLine.isEmpty() && isspace(readByte)) { + continue; + } + cmdLine += (char)readByte; + + if (cmdLine.length() > MAX_CMD_LEN) { + Serial.printf("Command too long, max 200 bytes\r\n"); + cmdLine.clear(); + continue; + } + if (cmdLine.endsWith("\r\n")) { + if (cmdLine.startsWith("AT")) { + CmdHandler(cmdLine); + } else { + Serial.printf("Command should start with AT\r\n"); + cmdLine.clear(); + continue; + } + } + } +} + +void UpperSerial::CmdHandler(String cmdLine) +{ + if (cmdLine == "AT\r\n") { + Serial.printf("OK\r\n"); + } else if (cmdLine.length() <= 5) { + Serial.printf("Bad Command\r\n"); + } else if (cmdLine[strlen("AT")] != '+') { + Serial.printf("Bad Command\r\n"); + } else { + String realCmd = cmdLine.substring(3, cmdLine.length() - 2); + ParseCmd(realCmd); + } +} + +void UpperSerial::ParseCmd(String cmd) +{ + if (cmd == "DEVIDREAD") { + Serial.printf("No Implement\r\n"); + + } else if (cmd == "SYSCFGREAD") { + Serial.printf("No Implement\r\n"); + + } else if (cmd.startsWith("DEVIDSET") && cmd[strlen("DEVIDSET")] == '=') { + Serial.printf("No Implement\r\n"); + + } else if (cmd.startsWith("SYSCFGSET") && cmd[strlen("SYSCFGSET")] == '=') { + Serial.printf("No Implement\r\n"); + + } else if (cmd.startsWith("MSGSTORE") && cmd[strlen("MSGSTORE")] == '=') { + String value = cmd.substring(strlen("MSGSTORE") + 1); + int i; + for (i = 0; i < value.length(); i++) { + if (value[i] == ',') { + break; + } + } + if (i >= value.length() - 1) { + Serial.printf("ERROR\r\n"); + return; + } + String dataLenStr = value.substring(0, i); + String dataBufStr = value.substring(i + 1); + int dataLen = (int)dataLenStr.toInt(); + if (dataLen == 0 || dataLen > RECORD_DATA_SIZE) { + Serial.printf("ERROR\r\n"); + return; + } + if (dataLen * 2 != dataBufStr.length()) { + Serial.printf("ERROR\r\n"); + return; + } + uint8_t dataBuf[dataLen] = {0}; + for (i = 0; i < dataLen; i++) { + String tmp = dataBufStr.substring(i * 2, i * 2 + 2); + dataBuf[i] = strtol(tmp.c_str(), 0, 16); + } + if (rec->PushData(dataLen, dataBuf)) { + Serial.printf("ERROR\r\n"); + return; + } + Serial.printf("OK\r\n"); + + } else if (cmd == "MSGREAD=?") { + uint8_t dataBuf[RECORD_DATA_SIZE] = {0}; + uint8_t dataLen = 0; + int index = 0; + if (rec->PopData(index, dataLen, dataBuf)) { + Serial.printf("ERROR\r\n"); + return; + } + String result = ""; + result += String(index); + result += ","; + result += String(dataLen); + result += ","; + char tmpHex[2] = {0}; + for (int i = 0; i < dataLen; i++) { + sprintf(tmpHex, "%X", dataBuf[i]); + result += tmpHex[0]; + result += tmpHex[1]; + } + Serial.printf("%s\r\n", result.c_str()); + + } else if (cmd == "MSGDUMP") { + Serial.printf("No Implement\r\n"); + } else { + Serial.printf("Bad Command\r\n"); + } +} diff --git a/src/main.cpp b/src/main.cpp index c378088..ccd6c1b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -5,11 +5,14 @@ #include "ConfigManager.h" #include "DataRecorder.h" #include "InterSerial.h" +#include "UpperSerial.h" VFileSystem fs; ConfigManager cfg; DataRecorder dataRec; InterSerial interSerial; +UpperSerial upperSerial; + void setup() { @@ -23,10 +26,13 @@ void setup() return; } interSerial.Init(&dataRec, &cfg); + upperSerial.Init(&dataRec, &cfg); } void loop() { interSerial.Process(); - delay(10); -} \ No newline at end of file + delay(1); + upperSerial.Process(); + delay(1); +}