ESP32 RS232桥接WiFi:如何解决串口随机数据异常问题?
RS232通信问题求助
感谢各位帮助,本人非专业人士,欢迎任何建议与批评。本次通信的目标硬件并非ESP32,而是一块带接口的外部板卡,程序预期通过Socket接收字符串并写入串口,同时打印返回结果。
使用器材
- ESP32-E
- 带MAX232芯片的商用RS232转TTL模块
- 用于Putty和Python测试的USB-RS232适配器
- 母对母Null Modem适配器
已执行测试
- Putty连接测试
- Python脚本连接测试
- 逻辑分析仪观测通信流量
遇到的问题
- 使用USB适配器搭配Null Modem适配器,通过Putty或Python脚本连接时,一切符合预期。
- 使用ESP32脚本连接时,会收到发送内容的"回声",且串口会随机记录额外字符,经逻辑分析仪确认确实存在该现象,仅80%时间工作正常,可靠性不足。
- 若不逐字符写入并添加短延迟,外部硬件无法识别字符串。
观察结果
- 未使用DSR或RTS信号,Python脚本中已设置为False且工作正常。
- ESP32端使用Null Modem映射RX/Tx引脚,因未使用其他控制信号,认为无影响。
- 最初将读写分离为不同任务并使用互斥锁,性能下降,合并任务后效率更高。
Putty配置
配置参数:波特率9600,数据位8,奇偶校验无,停止位1,流控选项全部关闭,本地回显禁用。
Python代码
import serial import time import threading import sys port = '/dev/ttyUSB0' baudrate = 9600 byte_size = serial.EIGHTBITS parity = serial.PARITY_NONE stop_bits = serial.STOPBITS_ONE ser = serial.Serial(port, baudrate, bytesize=byte_size, parity=parity, stopbits=stop_bits, timeout=2,dsrdtr=False,rtscts=False) lock = threading.Lock() #write thread def sendBytes(): global lock with lock: ser.write(b'\x03') ser.flush() time.sleep(0.1) while True: user_input = input("\nInput the string to serial: \n") if user_input.lower() == 'exit': print("exit program.") sys.exit(0) with lock: if 'r'==user_input or user_input=='reset' : ser.write(b'\x03') ser.flush() else: ser.write((user_input + '\r').encode()) ser.flush() #read thread def printData(): global lock while True: data = ser.read_all() if data: cleaned_data = data.replace(b'\n', b'').replace(b'\r', b'') print(cleaned_data.decode('utf-8')) time.sleep(0.08) taskRead = threading.Thread(target=printData) taskWrite = threading.Thread(target=sendBytes) taskRead.start() taskWrite.start()
ESP32代码
// custom struct to manage messages to queue typedef struct { char str[100]; int length; }fixed_string_t; // initzialice the socketserver esp_err_t initServer(void) { ws.begin(); ws.onEvent(webSocketEvent); return ESP_OK; } // task for websocket loop void runWebSocketServer(void *pv) { for (;;) { ws.loop(); vTaskDelay(5 / portTICK_RATE_MS); } } esp_err_t pushToRs2Queue(fixed_string_t q) { BaseType_t result = xQueueSend(rs232_queue, &q, portMAX_DELAY); return result == ESP_OK ? ESP_OK : -1; } // manage websocket incoming messages void webSocketEvent(uint8_t client, WStype_t type, uint8_t *data, size_t len) { if (type == WStype_TEXT) { std::string data_str(reinterpret_cast<const char *>(data), len); fixed_string_t item; strncpy(item.str, data_str.c_str(), sizeof(item.str) - 1); //ensure null termination item.str[sizeof(item.str) - 1] = '\0'; item.length = data_str.length(); pushToRs2Queue(item); } } // Start o reset the connection with HW void resetConn(void) { Serial2.write(0x03); vTaskDelay(200 / portTICK_PERIOD_MS); Serial2.flush(); } // reader and writter task void readRs232(void *pvp) { QueueHandle_t rs232_queue = (QueueHandle_t)pvp; resetConn(); Serial2.setTimeout(100); for (;;) { fixed_string_t arr; if (xQueueReceive(rs232_queue, &arr, pdMS_TO_TICKS(50)) == pdTRUE) { string toWrite = arr.str; if (!toWrite.empty() && toWrite[0] == 'c') { resetConn(); } else { for (const char &c : toWrite) { Serial2.write(c); vTaskDelay(35 / portTICK_PERIOD_MS); } // line feeder Serial2.write(0x0D); } } int bufferLen = Serial2.available(); if (bufferLen) { Serial.println(Serial2.readString()); } } vTaskDelay(100 / portTICK_PERIOD_MS); } void setup() { Serial.begin(115200); while (!Serial) ; ConnectWiFi_STA(); if (initServer() == ESP_OK) { xTaskCreatePinnedToCore(&runWebSocketServer, "websocket_server", 5048, NULL, 5, NULL, 1); } Serial2.begin(9600, SERIAL_8N1, TXD2, RXD2); while (!Serial2); xTaskCreatePinnedToCore(&readRs232, "readRs2", 10048, rs232_queue, 10, &rs232ReadHandle, tskNO_AFFINITY); } void loop() {}
恳请各位帮忙解决该问题,谢谢!
内容的提问来源于stack exchange,提问作者WikiLift
相关产品推荐
相关产品推荐

