可替代bmc sol(serial over lan)的serial over wlan,无线网络串口传输方案

发布时间:2026/9/11 0:47:19

可替代bmc sol(serial over lan)的serial over wlan,无线网络串口传输方案 sol serial over lan非常方便的实现了通过有线网络来访问串行数据由此我们可以设计一款通过无线网络来访问串口数据实现方法有两种1. 第一种是被测机器通过CPU上的TTL串口输出数据然后通过无线网络传输客户端通过APP抓取对应的数据2.第二种是被测机器通过USB接口输入串口数据然后通过无线网络传输客户端通过APP抓取对应的数据如此选择了芯片ESP32S3 兼容两个设计方案。分为如下几个模块1. 网络配置模块通过手机App发送Wifi的名称 跟 密码给到芯片配置Wifi 自动连接2. 显示模块自动连接Wifi后显示本地IP地址方便远程App读取数据3. 网络数据传输模块网络接收数据直接转发到USB模块/CPU TTL串口4. USB2TTL模块直连被测机器USB端口接收USB端口传输过来的串口数据并转发到Wifi网络5. UART TTL模块直连被测机器UART TTL端口接收TTL数据并转发到Wifi网络网络配置模块 static void initialise_wifi(void) { ESP_ERROR_CHECK(esp_netif_init()); s_wifi_event_group xEventGroupCreate(); ESP_ERROR_CHECK(esp_event_loop_create_default()); esp_netif_t *sta_netif esp_netif_create_default_wifi_sta(); assert(sta_netif); wifi_init_config_t cfg WIFI_INIT_CONFIG_DEFAULT(); ESP_ERROR_CHECK( esp_wifi_init(cfg) ); esp_err_t err nvs_ssid_password(); if (err ! ESP_OK) { ESP_LOGE(TAG, Failed to connect to WiFi: %s, esp_err_to_name(err)); ESP_ERROR_CHECK( esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, event_handler, NULL) ); ESP_ERROR_CHECK( esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, event_handler, NULL) ); ESP_ERROR_CHECK( esp_event_handler_register(SC_EVENT, ESP_EVENT_ANY_ID, event_handler, NULL) ); ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) ); ESP_ERROR_CHECK( esp_wifi_start() ); }else{ // 尝试读取保存的IP信息 esp_netif_ip_info_t ip_info; if (nvs_get_ip_info(ip_info) ESP_OK) { // 设置静态IP esp_netif_dhcpc_stop(sta_netif); esp_netif_set_ip_info(sta_netif, ip_info); ESP_LOGI(TAG, Static IP set from NVS); } ESP_ERROR_CHECK( esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, event_handler, NULL) ); ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) ); ESP_ERROR_CHECK( esp_wifi_start() ); ESP_ERROR_CHECK( esp_wifi_disconnect() ); ESP_ERROR_CHECK( esp_wifi_set_config(WIFI_IF_STA, wifi_config) ); esp_wifi_connect(); } }网络配置模块第一步是读取保存的Wifi名称以及密码如果有保存尝试连接Wifi如果没有读取到保存的Wifi则进入smartconfig 模式可以通过手机app发送对应的Wifi SSID 以及密码显示模块 static void lvgl_ui_update_task(void *arg) { esp_netif_ip_info_t labelmsg; while (1) { if (xQueueReceive(ip_update_queue, labelmsg, portMAX_DELAY) pdTRUE) { ESP_LOGI(TAG, Updating LVGL UI with new IP info); //lvgl_port_lock(0); char ip_full[32], mask_full[32], gw_full[32]; snprintf(ip_full, sizeof(ip_full), %d . %d . %d . %d, IP2STR(labelmsg.ip)); snprintf(mask_full, sizeof(mask_full), %d . %d . %d . %d, IP2STR(labelmsg.netmask)); snprintf(gw_full, sizeof(gw_full), %d . %d . %d . %d, IP2STR(labelmsg.gw)); ESP_LOGI(TAG, IP: %s, Mask: %s, Gateway: %s, ip_full, mask_full, gw_full); _lock_acquire(lvgl_api_lock); lv_label_set_text(ip_label, ip_full); lv_label_set_text(netmask_label, mask_full); lv_label_set_text(gw_label, gw_full); _lock_release(lvgl_api_lock); //lv_refr_now(NULL); //lvgl_port_unlock(); } } }显示模块选择的是lvgl添加了IP/NetMask/GateWay显示只要网络连接上显示屏会显示对应的IP地址网络传输模块 static void do_retransmit(const int sock) { int len; char rx_buffer[128]; do { len recv(sock, rx_buffer, sizeof(rx_buffer) - 1, 0); if (len 0) { ESP_LOGE(TAG, Error occurred during receiving: errno %d, errno); } else if (len 0) { ESP_LOGW(TAG, Connection closed); } else { rx_buffer[len] 0; // Null-terminate whatever is received and treat it like a string ESP_LOGI(TAG, Received %d bytes: %s, len, rx_buffer); // send() can return less bytes than supplied length. // Walk-around for robust implementation. //int to_write len; //while (to_write 0) { // int written send(sock, rx_buffer (len - to_write), to_write, 0); // if (written 0) { // ESP_LOGE(TAG, Error occurred during sending: errno %d, errno); // Failed to retransmit, giving up // return; // } // to_write - written; //} /* write back */ if (tud_cdc_n_connected(msg.itf)) { memcpy(msg.buf, rx_buffer, len); tinyusb_cdcacm_write_queue(msg.itf, msg.buf, len); esp_err_t err tinyusb_cdcacm_write_flush(msg.itf, 0); if (err ! ESP_OK) { ESP_LOGE(TAG, CDC ACM write flush error: %s, esp_err_to_name(err)); } }else{ ESP_LOGI(TAG, CDC ACM not connected, cannot send data); } uart_data_msg_t *uartmsg (uart_data_msg_t*) malloc(sizeof(uart_data_msg_t)); if (uartmsg NULL) { ESP_LOGI(TAG, Failed to allocate message, data dropped!); continue; } memcpy(uartmsg-data, rx_buffer, len); uartmsg-length len; if (xQueueSend(uart_data_rx_queue, uartmsg, 0) ! pdPASS) { ESP_LOGW(TAG, Queue full! Data dropped (length: %d), len); free(uartmsg); // 释放未发送的消息 } else { // 数据成功入队可以继续读取下一批UART数据 ESP_LOGI(TAG, Data enqueued: %d bytes, len); } } } while (len 0); }网络传输模块接收到网络数据后发送到USB CDC以及 TTL UARTUSB TTL模块 static void cdc_task(void *pvParameters){ while (1) { if (xQueueReceive(app_queue, msg, portMAX_DELAY)) { if (msg.buf_len) { /* Print received data*/ ESP_LOGI(TAG, Data from channel %d:, msg.itf); ESP_LOG_BUFFER_HEXDUMP(TAG, msg.buf, msg.buf_len, ESP_LOG_INFO); if (sock 0) { ESP_LOGI(TAG, Unable to accept connection: errno %d, errno); continue; } /* write back */ //tinyusb_cdcacm_write_queue(msg.itf, msg.buf, msg.buf_len); //esp_err_t err tinyusb_cdcacm_write_flush(msg.itf, 0); //if (err ! ESP_OK) { // ESP_LOGE(TAG, CDC ACM write flush error: %s, esp_err_to_name(err)); //} int to_write msg.buf_len; while (to_write 0) { int written send(sock, msg.buf (msg.buf_len - to_write), to_write, 0); if (written 0) { ESP_LOGI(TAG, Error occurred during sending: errno %d, errno); // Failed to retransmit, giving up return; } to_write - written; } } } } }USB CDC TTL模块接收到USB数据之后转发到网络sockUART TTL模块 void tcp_send_task(void *pvParameters) { ESP_LOGI(TAG, TCP send task started, socket: %d, sock); uart_data_msg_t *msg NULL; while (1) { // 1. 从队列中取出消息阻塞等待 if (xQueueReceive(uart_data_queue, msg, portMAX_DELAY) pdPASS) { if (msg NULL) { continue; } ESP_LOGI(TAG, Dequeued message of length: %d, msg-length); if (sock 0) { ESP_LOGI(TAG, Unable to accept connection: errno %d, errno); free(msg); msg NULL; continue; } // 2. 发送数据到TCP可能会阻塞 int to_write msg-length; int offset 0; while (to_write 0) { int written send(sock, msg-data offset, to_write, 0); if (written 0) { ESP_LOGI(TAG, Send error: errno %d, socket may be closed, errno); free(msg); // 这里可以触发重连逻辑但不要退出任务 // 等待网络恢复 vTaskDelay(1000 / portTICK_PERIOD_MS); break; // 退出内层循环 } to_write - written; offset written; } // 3. 释放消息内存 free(msg); msg NULL; } } vTaskDelete(NULL); }UART TTL模块接收到UART TTL数据之后转发到sock无线网络抓取系统内核打印或者BIOS串口打印
延伸阅读

更多相关文章

2026/9/6 19:58:33

英语单词rip的多重含义与计算机领域应用

1. 单词解析:rip的多重含义在英语学习中,我们经常会遇到一些看似简单却含义丰富的单词,"rip"就是这样一个典型例子。这个由三个字母组成的单词,在日常交流中至少有五种常见用法,每种用法都对应着完全不同的语…

2026/9/10 18:10:00

Unity骑乘僵尸角色插件:从动画系统到AI集成的完整开发指南

1. 项目概述:一个专为骑乘场景设计的僵尸角色解决方案 在Unity项目开发中,尤其是涉及动作冒险、生存恐怖或者开放世界探索等类型时,一个高质量、动画丰富的敌人角色往往是提升游戏沉浸感的关键。今天要拆解的这个插件——“Rider Zombie Anim…

2026/9/11 0:44:48

电机电磁场仿真核心:静磁场分析实操与避坑指南

做电机电磁场仿真这些年,我越来越觉得一个道理:如果你能把静磁场仿真做到位,电机的绝大多数设计问题都能在早期得到准确答案。静磁场仿真听起来像是电磁场分析里的“入门题型”,但在电机设计的真实场景中,它反而是用得…

2026/9/11 0:44:48

MongoDB安装与基础使用指南

1. MongoDB安装前的准备工作在开始安装MongoDB之前,我们需要先了解一些基本概念和准备工作。MongoDB是一个基于分布式文件存储的开源数据库系统,由C语言编写,旨在为WEB应用提供可扩展的高性能数据存储解决方案。1.1 系统环境检查首先确认你的…

2026/9/11 0:44:48

LoRA微调前必做的显存与训练时长估算指南

你有没有遇到过这种情况:项目启动前先被人问一句“这张卡能撑住这个模型的LoRA微调吗?大概要跑多久?”如果回答依赖的是“应该可以吧”和“先跑跑看”,那多半就要在几次OOM和漫长的等待中度过。反而是那些能按公式快速估算的人&am…

2026/9/11 0:39:47

论文降AIGC工具测评:原理、应用与避坑指南

1. 论文降AIGC工具测评背景与必要性 2023年ChatGPT的爆发式普及彻底改变了学术写作的生态格局。根据Nature最新调查显示,62%的研究者承认在日常学术工作中使用生成式AI工具辅助写作。但随之而来的学术诚信问题也引发全球教育界的广泛关注——全球TOP100高校中已有89…

2026/9/10 16:39:38

超人会飞不算本事:系统稳定依赖清晰规则与边界设计

开头先不绕弯子。“#斯坦李吐槽dc 所以超人是无缘无故会飞的嘛哈哈哈哈哈哈哈锤哥真是技术人才啊!#雷神 #复联”这类调侃式短标题,第一波冲击力在于它把两个宇宙的角色塞进同一个吐槽箱里,但细想一下就能发现,它真正碰到的根本不是…

2026/9/10 11:16:38

超人VS蜘蛛侠:拆解超级IP的影响力与传播方法论

把“蜘蛛侠 vs 超人”放在 CSDN 上聊,可能很多人第一反应是走错片场了。但如果把这两个角色看成“两个持续运营了 80 多年的文化产品”,你会发现,这场比较本质上是两个不同 IP 策略的长期结果对比:超人赢在定义了整个超级英雄题材…

2026/9/9 16:31:09

基于CNN的调制信号识别:MATLAB实现时频图分类实战

简介:本资源是一套面向通信工程与信号处理方向学习者、研究者的深度学习实践方案,聚焦调制信号自动检测与识别这一典型无线通信任务,解决传统方法依赖人工特征、低信噪比下性能下降等痛点。压缩包共12个文件(10.73MB)&…

2026/9/10 12:32:02

USB Type-C PCB布局分区设计:电源、高速信号与PD协议全攻略

做硬件这行,Type-C接口算是典型的“看着简单,做起来全坑”的东西。光引脚就24个,高低速信号、电源、控制线全部塞在一个小小的连接器里,如果PCB布局不做规划,打样回来基本就是“插上没反应”、“高速掉线”、“静电一打…

2026/9/10 15:19:50

系统编程学习原型如何补齐稳定性边界

系统编程学习原型如何补齐稳定性边界预算有限时&#xff0c;我先优化明显多余的复制&#xff0c;而不是猜测性地换容器。用借用传递只读数据通常就能减少分配&#xff1a; fn parse(line: &str) -> Result<Item, Error> { /* ... */ }用基准确认热点确实在分配&am…

2026/9/10 15:49:53

雨花区哪家财务公司代理记账比较好?

在雨花区&#xff0c;企业处理财税事务常常面临诸多挑战&#xff0c;选择一家靠谱的财务公司至关重要。湖南巨勤财务管理咨询有限公司就是本地正规实体财税服务机构&#xff0c;深耕本地工商财税行业多年&#xff0c;熟悉当地工商局、税务局最新政策与申报流程。主营公司注册、…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
咨询二维码