找回密码
 立即注册
首页 业界区 安全 D133物联网电子秤项目

D133物联网电子秤项目

汤昕昕 2025-6-1 21:13:25
D133物联网电子秤项目

项目开始日期:2025,2,28
需求
硬件采购需求:
3.5寸RGB屏幕(目前已适配4.3寸(480x272)RGB565屏幕)
语音播报(语音模块+喇叭)
软件需求:

  • lvgl用户交互界面
  • 处理电子称串口数据
  • 语音播报消息
  • wifi上传到服务器
作用:
RGB屏幕实现电子秤输入,同时语音播报。
数据上传服务器
技术细节疑惑:
电子秤菜单串口是否输出计算结果,还是由D133计算?
等待中流程:
采购:屏幕,语音播报模块+喇叭
技术:串口包数据包格式,WiFi上传格式
拆分任务:

  • 实现串口收发(解析)
  • 移植RGB屏幕
  • 移植LVGL
  • 初步实现UI界面交互
  • 实现wifi上传数据到服务器
  • 增加语音播报
目前加急任务:

  • 移植屏幕+lvgl
  • 串口处理数据包
  • WiFi上传数据
期限:三月末
要求:需要有初步结果:lvgl+屏幕+WiFi上传数据包到服务器
拉取SDK
  1.     git clone  --depth=1 https://gitee.com/lcsc/luban-lite.git
复制代码
git代码管理
  1. git remote add origin https://gitee.com/sword-level_0/digital-scale-d133.git
  2. git push -u origin "master"
复制代码
移植UART
串口0为Debug调试打印接口
1.png
使用
在user_uart3.c文件中将函数导出为命令,可以在终端开启串口
  1. // 导出函数为命令
  2. MSH_CMD_EXPORT(uart3_test_on, Test transmission and reception using UART3 serial port);
复制代码
在终端开启
  1. uart3_test_on
复制代码
2.png

发送
  1. send_demoData
复制代码
接受串口数据
3.png

移植外设

外设框架
  1. [/code][size=4]移植0.96IIC[/size]
  2. 复制驱动文件夹至路径
  3. [indent][b]application\rt-thread\helloworld\user_bsp\0-96-iic-single-screen[/b]
  4. [/indent]在上层路径Kconfig添加
  5. 在配置中,配置开启
  6. 需要将冲突配置取消:
  7. LVGL相关和数字视频接口
  8. [code]Application options  --->
  9.       [*] LVGL (official): powerful and easy-to-use embedded GUI library  ----
  10.       [*] ArtInChip LVGL demo  ----
  11. Board options  --->
  12.       [*] Using DVP
复制代码
4.png

外设路径
5.png

外设上层路径
6.png
  1. test_0_96_iic_single_screen
复制代码
进程间通信(消息队列)
消息队列的使用
发送
  1. /* 格式化时间字符串 */
  2. snprintf(msg_buf, sizeof(msg_buf), "time=%d", time); // 使用snprintf函数将时间变量格式化为字符串,存储在msg_buf中
  3.         
  4. /* 发送消息到队列 */
  5. result = rt_mq_send(mq, msg_buf, sizeof(msg_buf)); // 调用rt_mq_send函数将msg_buf中的消息发送到队列mq中
  6. if (result != RT_EOK) // 如果发送失败
  7. {
  8.      rt_kprintf("Failed to send message\n"); // 打印错误信息
  9. }
复制代码
接收
  1.     char msg_buf[16]; //  定义一个字符数组,用于存储接收到的消息,数组大小为16字节
  2.     rt_err_t result; // 定义一个变量result,用于存储函数返回的错误码
  3.     while (1) // 无限循环,程序将一直执行这个循环体
  4.     {
  5.         /* 阻塞等待消息 */
  6.         result = rt_mq_recv(mq, msg_buf, sizeof(msg_buf), RT_WAITING_FOREVER); // 调用rt_mq_recv函数从消息队列mq中接收消息
  7.         if (result == RT_EOK)
  8.             rt_kprintf("Received: %s\n", msg_buf);
  9.         else
  10.             rt_kprintf("Recv failed: %d\n", result);
  11.     }
复制代码
同一文件
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <string.h>
  4. #include <getopt.h>
  5. #include <sys/time.h>
  6. #include <rtthread.h>
  7. #include "rtdevice.h"
  8. #include "aic_core.h"
  9. #include "aic_hal_gpio.h"
  10. #define RT_USING_OVERFLOW_CHECK
  11. static rt_mq_t mq = RT_NULL; // 消息队列句柄
  12. /* 消息队列初始化 */
  13. static int msg_queue_init(void)
  14. {
  15.     /* 创建消息队列:名称、消息大小、队列容量、队列模式 */
  16.     mq = rt_mq_create("time_mq", 20, 10, RT_IPC_FLAG_FIFO);
  17.     if (mq == RT_NULL)
  18.     {
  19.         rt_kprintf("Failed to create message queue\n");
  20.         return -1;
  21.     }
  22.     return 0;
  23. }
  24. INIT_APP_EXPORT(msg_queue_init); // 系统启动时自动初始化
  25. /* 线程1:发送时间信息 */
  26. static rt_thread_t user_app_thread = RT_NULL;
  27. static void user_APP_thread_entry(void *param)
  28. {
  29.     int time = 0;
  30.     int count = 0;
  31.     char msg_buf[20];
  32.     rt_err_t result;
  33.     while (1)
  34.     {
  35.         /* 格式化时间字符串 */
  36.         snprintf(msg_buf, sizeof(msg_buf), "time=%d", time);
  37.         
  38.         /* 发送消息到队列 */
  39.         result = rt_mq_send(mq, msg_buf, sizeof(msg_buf));
  40.         if (result != RT_EOK)
  41.         {
  42.             rt_kprintf("Failed to send message\n");
  43.         }
  44.         /* 每两次发送(1秒)增加时间 */
  45.         if (++count % 2 == 0)
  46.             time++;
  47.         rt_thread_mdelay(500); // 500ms间隔
  48.     }
  49. }
  50. /* 启动线程1的命令 */
  51. static void usr_APP_run(int argc, char **argv)
  52. {
  53. // 修改线程创建时的栈大小参数(原512改为2048)
  54.     user_app_thread = rt_thread_create(
  55.     "user_app_thread",
  56.     user_APP_thread_entry, RT_NULL,
  57.     2048,  // 修改点:栈大小增加到2048字节
  58.     25, 5);
  59.     if (user_app_thread)
  60.         rt_thread_startup(user_app_thread);
  61.     else
  62.         rt_kprintf("Create thread1 failed\n");
  63. }
  64. MSH_CMD_EXPORT(usr_APP_run, "Start time sender thread");
  65. /* 线程2:接收并打印信息 */
  66. static rt_thread_t user_app2_thread = RT_NULL;
  67. static void user_APP2_thread_entry(void *param)
  68. {
  69.     char msg_buf[16]; // 原20改为16("time=2147483647"仅需14字节)
  70.     rt_err_t result;
  71.     while (1)
  72.     {
  73.         /* 阻塞等待消息 */
  74.         result = rt_mq_recv(mq, msg_buf, sizeof(msg_buf), RT_WAITING_FOREVER);
  75.         if (result == RT_EOK)
  76.             rt_kprintf("Received: %s\n", msg_buf);
  77.         else
  78.             rt_kprintf("Recv failed: %d\n", result);
  79.     }
  80. }
  81. /* 启动线程2的命令 */
  82. static void usr_APP2_run(int argc, char **argv)
  83. {
  84.     // 修改线程创建时的栈大小参数(原512改为2048)
  85.     user_app2_thread = rt_thread_create(
  86.     "user_app2_thread",
  87.     user_APP2_thread_entry, RT_NULL,
  88.     2048,  // 修改点:栈大小增加到2048字节
  89.     25, 5);
  90.     if (user_app2_thread)
  91.         rt_thread_startup(user_app2_thread);
  92.     else
  93.         rt_kprintf("Create thread2 failed\n");
  94. }
  95. MSH_CMD_EXPORT(usr_APP2_run, "Start message receiver thread");
复制代码
不同文件
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <string.h>
  4. #include <getopt.h>
  5. #include <sys/time.h>
  6. #include <rtthread.h>
  7. #include "rtdevice.h"
  8. #include "aic_core.h"
  9. #include "aic_hal_gpio.h"
  10. extern rt_mq_t mq; // 消息队列句柄
  11. /* 外部线程:接收并打印信息 */
  12. static rt_thread_t user_External_app_thread = RT_NULL;
  13. static void user_External_app_thread_entry(void *param)
  14. {
  15.     char msg_buf[16]; // 原20改为16("time=2147483647"仅需14字节)
  16.     rt_err_t result;
  17.     while (1)
  18.     {
  19.         /* 阻塞等待消息 */
  20.         result = rt_mq_recv(mq, msg_buf, sizeof(msg_buf), RT_WAITING_FOREVER);
  21.         if (result == RT_EOK)
  22.             rt_kprintf("Received: %s\n", msg_buf);
  23.         else
  24.             rt_kprintf("Recv failed: %d\n", result);
  25.     }
  26. }
  27. /* 启动线程的命令 */
  28. static void usr_External_app_run(int argc, char **argv)
  29. {
  30.     // 修改线程创建时的栈大小参数(原512改为2048)
  31.     user_External_app_thread = rt_thread_create(
  32.     "usr_External_app_thread",  // 线程名
  33.     user_External_app_thread_entry, RT_NULL,
  34.     2048,  // 修改点:栈大小增加到2048字节
  35.     25, 5);
  36.     if (user_External_app_thread)
  37.         rt_thread_startup(user_External_app_thread);
  38.     else
  39.         rt_kprintf("Create _External——thread failed\n");
  40. }
  41. MSH_CMD_EXPORT(usr_External_app_run, "Start message receiver thread");
复制代码
改动
在声明句柄的文件中:
  1. static rt_mq_t mq = RT_NULL; // 消息队列句柄
复制代码
去掉
  1. static //静态修饰
复制代码
改成
  1. rt_mq_t mq = RT_NULL; // 消息队列句柄
复制代码
在外部文件中
  1. extern rt_mq_t mq; // 声明引用外部消息队列句柄
复制代码
终端命令
  1. 发送消息队列
  2. usr_APP_run
  3. 接收消息队列,打印
  4. usr_APP2_run
  5. oled显示+接收消息队列
  6. test_0_96_iic_single_screen
复制代码
网路(2.4GWIFI)
终端
扫描WIFI
  1. wlan wifi_scan
复制代码
连接wifi:
输入名称,密码
  1. wlan wifi_connect SSID PASSWORD
复制代码
  1. wlan wifi_connect jianzhiji 8765432111
复制代码
开启网卡
  1. dhcpc WL0 start
复制代码
查看ip
  1. ifconfig
复制代码
7.png

例程分析
例程结构
网络概念解析

LwIP(Light Weight IP)是一个小型开源的TCP/IP协议栈,由瑞典计算机科学院(SICS)的Adam Dunkels开发。它的设计初衷是用少量的资源消耗(尤其是RAM)实现一个较为完整的TCP/IP协议栈,其中“完整”主要指的是TCP协议的完整性。
DNS域名解析

当在浏览器中输入 www.baidu.com 并解析时,整个过程涉及多个步骤和技术协议,最终目的是将域名转换为服务器IP地址并完成网页加载。以下是解析的主要流程及相关技术细节:
1. DNS域名解析

DNS(Domain Name System)负责将域名转换为对应的IP地址,具体步骤如下:

  • 本地缓存查询

    • 浏览器首先检查自身缓存(如Chrome的DNS缓存)中是否有该域名的IP记录214。
    • 若无,则查询操作系统缓存(如Windows的hosts文件)和本地DNS缓存14。

  • 本地DNS服务器查询

    • 若本地缓存未命中,请求会发送至用户配置的本地DNS服务器(如运营商提供的114.114.114.114)414。
    • 本地DNS服务器若缓存了域名记录,直接返回IP;否则进入递归查询流程14。

  • 递归查询与根域名服务器

    • 本地DNS服务器依次向根域名服务器、顶级域名服务器(.com)、权威域名服务器(百度注册的DNS服务器)发起迭代查询,最终获取www.baidu.com的IP地址714。

  • 返回IP地址

    • 查询结果逐级返回至浏览器,例如常见的百度IP地址可能为 220.181.111.147 或 202.108.22.5(实际IP可能因负载均衡而变化)27。

相关命令

  • 使用 nslookup www.baidu.com 或 ping www.baidu.com 可直接查看解析后的IP地址3。
2. 建立TCP连接

获取IP地址后,浏览器通过TCP协议与服务器建立连接:

  • 三次握手

    • 客户端发送SYN包,服务器返回SYN-ACK包,客户端再发送ACK包确认,完成可靠连接的建立27。

  • 端口与协议

    • 服务器默认监听80端口(HTTP)或443端口(HTTPS)212。

3. 发起HTTP请求与响应


  • HTTP请求

    • 浏览器发送HTTP GET请求,包含请求头(如User-Agent、Cookie等)和请求路径(如/表示首页)712。

  • 服务器处理

    • 百度服务器根据请求生成响应,可能涉及负载均衡、动态内容生成或静态资源返回1213。

  • HTTP响应

    • 服务器返回状态码(如200 OK)、响应头(如Content-Type)及HTML内容27。

4. 浏览器渲染页面


  • 解析HTML与资源加载

    • 浏览器解析HTML代码,并加载其中的CSS、JavaScript、图片等资源,可能触发多次HTTP请求212。

  • 渲染引擎处理

    • 构建DOM树、CSSOM树,合并为渲染树,最终布局和绘制页面712。

5. 连接释放


  • 数据传输完成后,通过TCP四次挥手释放连接27。
技术协议总结

协议层级协议与作用应用层HTTP(传输网页)、DNS(域名解析)2传输层TCP(可靠连接)、UDP(DNS查询)27网络层IP(路由选择)、ARP(IP转MAC地址)47链路层以太网帧(物理传输)4以下是关于 lwIP 的线程堆栈大小、MQTT/HTTP 协议使用、DHCP 服务器配置以及调试选项的详细说明:
1. lwIP 线程堆栈大小

作用
lwIP 在多线程环境下运行时,每个网络线程(如 TCP/IP 主线程、协议处理线程等)需要分配足够的堆栈空间。堆栈大小不足会导致栈溢出、系统崩溃或数据损坏。
配置方法

  • 默认值
    lwIP 默认堆栈大小取决于移植的平台(如 FreeRTOS、裸机等),通常在 lwipopts.h 或平台配置文件中定义。
    例如,在 FreeRTOS 中,TCP/IP 线程堆栈可能默认为 1KB~4KB。
  • 调整堆栈
    根据协议复杂度和数据量调整。例如:

    • 简单应用(如 UDP Echo):1KB~2KB
    • 复杂应用(如 HTTP 文件传输):4KB~8KB
    • MQTT/HTTP + TLS:可能需要 8KB~16KB(加密算法占用更多栈空间)
    在 FreeRTOS 中修改示例:
    1. // FreeRTOS 任务创建时指定堆栈大小
    2. xTaskCreate(tcpip_thread, "lwIP", 4096, NULL, 2, NULL);
    复制代码
  • 检测方法
    使用工具(如 FreeRTOS 的堆栈溢出检测钩子函数 vApplicationStackOverflowHook)或手动填充魔法值检查溢出。
2. 使用 MQTT 协议

实现步骤

  • 启用 lwIP MQTT 模块
    在 lwipopts.h 中启用 MQTT 支持:
    1. #define LWIP_MQTT 1
    复制代码
  • 集成 MQTT 客户端
    lwIP 提供轻量级 MQTT 客户端,需包含头文件:
    1. #include "mqtt.h"
    复制代码
  • 连接与通信示例
    1. // MQTT 连接配置
    2. struct mqtt_connect_client_info_t ci;
    3. memset(&ci, 0, sizeof(ci));
    4. ci.client_id = "client_id";
    5. // 连接到 Broker
    6. mqtt_client_t *client = mqtt_client_new();
    7. mqtt_connect(client, &ip_addr, 1883, mqtt_connection_cb, NULL, &ci);
    8. // 发布消息
    9. const char *message = "Hello MQTT";
    10. mqtt_publish(client, "topic", message, strlen(message), MQTT_QOS_0, 0, NULL);
    复制代码
3. 使用 HTTP 协议

实现步骤

  • 启用 HTTP 服务器
    在 lwipopts.h 中启用 HTTP 支持:
    1. #define LWIP_HTTPD 1
    2. #define LWIP_HTTPD_SSI 1   // 可选:支持 SSI
    3. #define LWIP_HTTPD_CGI 1   // 可选:支持 CGI
    复制代码
  • 实现 HTTP 回调函数
    定义页面处理和 CGI 函数:
    1. // 处理 HTTP 请求
    2. const char *http_response = "<html><body>Hello HTTP</body></html>";
    3. err_t http_req_handler(struct pbuf *p, struct tcp_pcb *pcb) {
    4.     tcp_write(pcb, http_response, strlen(http_response), TCP_WRITE_FLAG_COPY);
    5.     tcp_close(pcb);
    6.     return ERR_OK;
    7. }
    8. // 注册 HTTP 路径
    9. http_set_cgi_handlers(http_cgi_handlers, LWIP_ARRAYSIZE(http_cgi_handlers));
    复制代码
  • 启动 HTTP 服务器
    1. httpd_init();
    复制代码
4. 使用 DHCP 服务器

配置方法

  • 启用 DHCP 服务器功能
    在 lwipopts.h 中启用:
    1. #define LWIP_DHCP 1         // 启用 DHCP 客户端
    2. #define LWIP_DHCPS 1        // 启用 DHCP 服务器
    复制代码
  • 设置地址池
    在代码中配置 DHCP 地址池:
    1. ip4_addr_t dhcp_start, dhcp_end;
    2. IP4_ADDR(&dhcp_start, 192, 168, 1, 100);
    3. IP4_ADDR(&dhcp_end, 192, 168, 1, 200);
    4. dhcp_server_init(netif_default, &dhcp_start, &dhcp_end);
    复制代码
  • 处理 DHCP 请求
    lwIP 自动处理客户端请求,分配 IP 并管理租期。
5. 启用 lwIP 调试选项

作用
调试选项用于输出网络状态、协议解析细节和错误信息,帮助定位连接问题、内存泄漏或协议错误。
启用方法

  • 全局调试开关
    在 lwipopts.h 中设置:
    1. #define LWIP_DEBUG 1                // 启用调试
    2. #define LWIP_DBG_MIN_LEVEL LWIP_DBG_LEVEL_ALL  // 输出所有级别日志
    复制代码
  • 模块级调试
    按需启用特定模块的调试:
    1. #define DHCP_DEBUG LWIP_DBG_ON      // DHCP 调试
    2. #define TCP_DEBUG LWIP_DBG_ON       // TCP 调试
    3. #define HTTP_DEBUG LWIP_DBG_ON      // HTTP 调试
    复制代码
  • 输出调试信息
    实现 lwip_log 函数或重定向到串口:
    1. void lwip_log(const char *fmt, ...) {
    2.     va_list args;
    3.     va_start(args, fmt);
    4.     vprintf(fmt, args);  // 输出到控制台或串口
    5.     va_end(args);
    6. }
    复制代码
典型调试场景

  • 内存泄漏:启用 MEM_DEBUG 和 MEMP_DEBUG。
  • TCP 重传:启用 TCP_CWND_DEBUG 查看拥塞窗口变化。
  • HTTP 请求解析:启用 HTTP_DEBUG 跟踪请求处理。
总结


  • 堆栈大小:根据协议复杂度和线程任务调整,避免溢出。
  • 协议支持:通过 lwipopts.h 启用 MQTT/HTTP/DHCP,并实现回调函数。
  • 调试:启用调试宏并实现日志输出,快速定位问题。
建议结合具体平台(如 FreeRTOS、Linux 等)和硬件资源(内存、CPU)进行参数调优。
开启网络
8.png

9.png

10.png

11.png

12.png

13.png

14.png

15.png

16.png

help

以下是 RT-Thread Shell 命令的中文翻译:
RT-Thread Shell 命令列表

命令功能描述list_fd列出文件描述符sensor传感器测试功能sensor_polling传感器轮询模式测试功能sensor_int传感器中断模式测试功能sensor_fifo传感器 FIFO 模式测试功能free显示系统内存使用情况ps列出系统中的线程help显示 RT-Thread Shell 帮助list列出系统对象list_device列出系统中的设备list_timer列出系统中的定时器list_mempool列出内存池list_memheap列出内存堆list_msgqueue列出消息队列list_mailbox列出邮箱list_mutex列出互斥锁list_event列出事件list_sem列出信号量list_thread列出线程version显示 RT-Thread 版本信息clear清空终端屏幕tail输出文件的最后 N 行数据echo将字符串写入文件df显示磁盘剩余空间umount从文件系统卸载设备mount挂载设备到文件系统:mount   mkfs格式化磁盘为指定文件系统mkdir创建目录pwd显示当前工作目录路径cd切换工作目录rm删除文件cat查看文件内容mv重命名文件或移动文件cp复制文件ls列出目录或文件信息ulog_filter显示 ulog 日志过滤设置ulog_kw设置 ulog 全局关键字过滤ulog_tag设置 ulog 全局标签过滤ulog_lvl设置 ulog 全局日志级别过滤ulog_tag_lvl按标签设置 ulog 日志级别过滤ulog_be_lvl按后端设置 ulog 日志级别过滤f运行一个函数m修改内存值p打印内存值meminfo显示内存信息run_in_loop_thre在循环线程中运行命令run_in_thread在线程中运行命令reboot重启系统reset重置设备模块list_pinmux列出引脚功能配置arecord录制音频为 WAV 文件aplay播放 WAV 文件test_clock测试时钟模块(CMU CLK)test_dma_memset测试 DMA 内存填充(参数:值 长度)test_dma_memcpy测试 DMA 内存复制(参数:长度)test_dvp测试 DVP 和摄像头模块test_gpai测试 GPAI 设备test_gpio测试 GPIO 设备test_eth网络回环测试iperf网络性能测试(-s 为服务端/-c 为客户端)sfSPI Flash 操作falFAL(Flash 抽象层)操作test_tsen温度传感器(TSen)测试top显示 CPU 使用率dhcpc启动/停止 DHCP 客户端(动态主机配置协议),自动分配IP、子网掩码、网关和DNS,这样用户就不用手动配置了ifconfig显示或配置网络信息ping网络连通性测试(输入 ping help 查看帮助)test_0_96_iic_si测试 0.96 英寸 IIC 屏幕usr_APP2_run启动消息接收线程usr_APP_run启动时间发送线程usr_External_app启动外部应用线程(消息接收)send_demoData发送测试数据dma_dump显示 DMA 寄存器(参数:通道号)efuse操作 EFUSEepwm_status显示 EPWM 状态mtop测试 mtop 功能pwm_set_tb设置 PWM 时基pwm_status显示 PWM 状态tsen_status显示温度传感器状态wdt_status显示看门狗状态list_irq列出系统中断canstat显示 CAN 设备状态adcADC 操作(输入 adc help 查看选项)pin引脚操作(输入 pin help 查看选项)pwmPWM 操作(输入 pwm help 查看选项)lptimer_dump显示低功耗定时器(LPTimer)信息pm_dump显示电源管理状态pm_run切换电源管理模式pm_module_delay设置模块延迟休眠请求pm_module_reques请求模块电源管理模式pm_module_releas释放模块电源管理模式计数pm_module_releas释放模块电源模式pm_request请求电源管理模式pm_release_all释放所有电源管理模式计数pm_release释放电源管理模式list_alarm列出闹钟信息date获取/设置日期和时间(本地时区):date [年 月 日 时 分 秒]player_demo播放器演示audio_player_dem音频播放器演示wlanWiFi 操作(输入 wlan help 查看子命令)使用说明


  • 格式:命令 [参数],例如 ping 192.168.1.1。
  • 帮助:输入 命令 help 查看详细用法(如 ping help)。
  • 硬件相关命令(如 test_gpio, pwm)需确保硬件支持。
网络相关概念

DHCP

''(Dynamic Host Configuration Protocol,动态主机配置协议)是一种网络协议,用于自动分配和管理网络设备的IP地址及相关配置参数,从而简化网络配置并避免手动操作带来的错误。
一、核心功能


  • IP地址自动分配

    • 动态分配:从地址池中临时分配IP(有租期限制)
    • 静态绑定:为特定设备(如服务器)固定分配IP

lwIP

(Lightweight IP) 是一个轻量化的开源 TCP/IP 协议栈,专为资源受限的嵌入式系统设计。它由瑞典计算机科学研究院的 Adam Dunkels 开发,广泛应用于物联网设备、工业控制、传感器网络等场景。

  • 模块化架构

    • 支持按需裁剪功能模块(如 DHCP、DNS、IPv6),开发者可灵活配置协议栈功能。

  • 多协议支持

    • 包含完整的 TCP/IP 协议族:

      • 网络层:IPv4、IPv6、ICMP、IGMP
      • 传输层:TCP、UDP
      • 应用层:HTTP、SNMP、MQTT(需扩展实现)


lwIP 的典型应用场景

场景说明物联网设备智能家居设备(如 Wi-Fi 插座、传感器)通过 lwIP 实现网络通信。工业控制PLC、工业网关使用 lwIP 接入以太网,支持 Modbus TCP 等协议。嵌入式 Web 服务器通过 lwIP 的 HTTP 模块,在设备上运行轻量级 Web 页面(如配置界面)。低功耗设备结合低功耗无线技术(如 LoRa、BLE),实现电池供电设备的间歇性网络通信。
17.png

18.png

iperf

iperf 是一款开源的网络性能测试工具,主要用于测量 TCP/UDP 带宽、延迟、抖动和丢包率等网络性能指标。它通过在客户端和服务器之间发送数据流,评估网络的吞吐量和稳定性,是网络工程师和开发者的常用工具。
一、核心功能

功能说明带宽测试测量网络最大传输速率(如测出实际带宽是否达标)协议支持支持 TCP、UDP、SCTP 协议多线程测试可并行多连接测试(模拟多用户场景)数据方向控制支持上行(客户端→服务器)、下行(服务器→客户端)、双向测试统计报告实时输出带宽、抖动(Jitter)、丢包率(Loss%)等详细指标SDMC

通常指 同步数字主控制器(Synchronous Digital Master Controller),是一种用于协调多设备同步操作的高精度时序控制核心模块,尤其在高速数字系统、通信设备和复杂嵌入式系统中广泛应用。
WLAN连接

wifi(RTL8189FTV-WIFI模块2.4GHz,SDIO接口)

扫描wifi
  1. wlan wifi_scan
复制代码
连接wifi  (输入名称,密码)
  1. wlan  wifi_connect SSID PASSWORD
复制代码
  1. wlan wifi_connect jianzhiji 8765432111
复制代码
  1. wlan wifi_connect jianzhiji 8765432111
复制代码
  1. ifconfig
复制代码
19.png
需出现IP地址才算链接成功
可以 通过ping ip来再次确认是否连接到互联网还是内网:
  1. ping www.baidu.com
  2. //DNS解码的百度ip地址
  3. ping 183.2.172.177
复制代码
20.png

无线网络

本章节讲解如何在 Luban-Lite 系统中配置 SDIO 接口的无线网络,需要配置的主要有以下几部分:

  • 配置 SDMC 接口;
  • 配置 WiFi 模组;
  • 配置 lwIP 协议栈;
  • 配置内核;
配置 SDMC 接口和 WiFi 模组

使用 SDMC 接口前,需将对应 SDMC 接口选中,以 D133CBV-QFN88 开发板为例,使用 scons --menuconfig 命令进行配置:
  1. Board options
  2.     [ * ] Using SDMC0                                    # 硬件连接哪个 SDMC 接口,选择哪个SDMC
  3.     [ * ] Enable the interrupt of sdmc
  4.     [ * ] Using Wireless lan --->
  5.         [ * ] Using Realtek wlan driver --->
  6.             Select Realtek wlan0 modul (rtl8189)--- >    # 以 RTL8189 为例
  7.             Realtek wlan0 paramete --->
  8.                 (PC.7) realtek wlan0 power on gpio
  9.                 (192.168.3.20) wlan0 ip addr
  10.                 (192.168.3.1) wlan0 gateway addr
  11.                 (255.255.255.0) wlan0 netmask
  12.                 [*] Enable Realtek driver debug information
复制代码
使用RTL8189FTV--WIFI模块该选
21.png

22.png

例程地址:packages -> third-party -> webclient ->samples
23.png

配置 lwIP

使用 scons --menuconfig 命令进入配置页面,配置如下:
  1. Local packages options --->
  2.     Third-party packages options --->
  3.     LwIP: light weight TCP/IP stack
  4.         [*]   LwIP Examples  --->
  5.         [*]   Using net tools
  6.         [*]   Enable DNS for name resolution
  7.         [*]   Enable alloc ip address through DHCP
  8.         [*]   Enable ping features  --->
复制代码
配置内核
  1. Rt-Thread options --->
  2.     RT-Thread Kernel --->
  3.         (4)    The priority level value of timer thread
  4.         (4096) The stack size of timer thread
  5.     RT-Thread Components --->
  6.         Device Drivers --->
  7.             (4096) The stack size for sdio irq thread
  8.             (5)   The priority level value of sdio irq thread
复制代码
24.png

25.png

26.png

27.png

WLAN基础管理命令

以下是这些 wlan 相关命令的详细功能解析和用法说明(按用途分类整理):
一、WiFi基础管理命令

1. 网络开关

命令功能示例wifi_on启动WiFi模块wifi_onwifi_off关闭WiFi模块wifi_off2. 连接管理

命令功能参数说明示例wifi_connect通过SSID和密码连接网络 wifi_connect MyWiFi 12345678wifi_connect_bssid指定BSSID连接(防AP同名欺骗)  wifi_connect_bssid MyWiFi 1234 AA:BB:CCD:EE:FFwifi_disconnect断开当前连接无wifi_disconnect二、网络扫描与诊断

1. 扫描相关

命令功能参数说明示例wifi_scan执行全频段WiFi扫描无wifi_scanwifi_reoder_scan按信号强度排序扫描结果无wifi_reoder_scanwifi_scan_with_ssid扫描指定SSID是否存在wifi_scan_with_ssid MyWiFiwifi_scan_with_multissid批量扫描多个SSID ...wifi_scan_with_multissid Home Office2. 诊断工具

命令功能参数说明示例ping网络连通性测试 [-t] [-n count]ping 192.168.1.1 -n 5get_auto_chl获取自动信道选择结果无get_auto_chl三、高级调试与监控

1. 混杂模式(抓包)

命令功能参数说明示例wifi_promisc开启混杂模式监听原始数据包wifi_promisc enablerawdata_enable启用原始数据捕获无rawdata_enablerawdata_disable禁用原始数据捕获无rawdata_disablerawdata_send发送原始数据帧(需指定格式)rawdata_send 00AAFF...2. 调试接口

命令功能参数说明示例iwpriv设置/读取私有驱动参数 [值]iwpriv set_power 10wifi_debug开启调试日志(级别可调)wifi_debug 3四、AP模式操作

命令功能参数说明示例wifi_ap启动SoftAP热点模式  [channel]wifi_ap MyHotspot 12345678 6五、系统信息与退出

命令功能参数说明示例wifi_info显示当前连接状态(IP/RSSI/BSSID等)无wifi_infoexit退出命令行界面无exithelp显示命令帮助无help常见问题处理指南

1. 连接失败
  1. # 检查驱动状态
  2. wifi_info
  3. # 扫描确认AP存在
  4. wifi_scan_with_ssid MyWiFi
  5. # 尝试指定BSSID连接
  6. wifi_connect_bssid MyWiFi password AA:BB:CC:DD:EE:FF
复制代码
2. 网络延迟高
  1. # 持续ping测试
  2. ping 192.168.1.1 -t
  3. # 查看当前信道质量
  4. iwpriv get_rssi
复制代码
3. 抓包分析
  1. wifi_promisc enable
  2. rawdata_enable
  3. # 此时数据会输出到指定接口(需配合tcpdump或wireshark)
复制代码
参数顺序规则(重要!)


  • 对于ping命令,选项顺序影响参数有效性
    1. # 正确:发送5次请求
    2. ping 192.168.1.1 -n 5
    3. # 错误:-t出现在-n之后会被忽略
    4. ping 192.168.1.1 -n 5 -t  # 实际只执行5次
    复制代码
调试日志级别说明

级别日志详细程度0关闭所有调试输出1关键错误信息2基本连接状态变更3协议交互过程(推荐调试级别)4详细数据包跟踪5底层寄存器操作(开发者用)建议调试时先设置 wifi_debug 3 查看关键交互信息。
HTTP

[单片机] → (连接Wi-Fi) → [TCP握手] → [发送HTTP请求] → [接收响应] → [处理数据]
E:\D133EBS\WIFI\luban-lite\kernel\rt-thread\components\net\lwip\lwip-2.1.2\src\apps\http\http_client.c
E:\D133EBS\WIFI\luban-lite\packages\third-party\lwip\src\apps\http\http_client.c

    1. 1. 包含头文件**: 在你的源文件中包含 `http_client.h` 头文件,以便使用 HTTP 客户端的接口和数据结构。
    2.    \#include "lwip/apps/http_client.h"
    3. 2. **配置 HTTP 客户端连接**: 配置 `httpc_connection_t` 结构体,设置代理地址、端口和回调函数等。
    4.    *httpc_connection_t* settings;
    5.    *memset*(&*settings*, 0, sizeof(settings));
    6.    settings.result_fn = my_result_callback;
    7.    settings.headers_done_fn = my_headers_done_callback;
    8. 3. **定义回调函数**: 实现 HTTP 客户端的回调函数,用于处理 HTTP 请求的结果和接收的头部信息。
    9.    void *my_result_callback*(void **arg*, *httpc_result_t* *httpc_result*, *u32_t* *rx_content_len*, *u32_t* *srv_res*, *err_t* *err*) {
    10.      *// 处理 HTTP 请求结果*
    11.    }
    12.    *err_t* *my_headers_done_callback*(*httpc_state_t* **connection*, void **arg*, struct pbuf **hdr*, *u16_t* *hdr_len*, *u32_t* *content_len*) {
    13.      *// 处理接收到的 HTTP 头部信息*
    14.      return ERR_OK;
    15.    }
    16. 4. **发起 HTTP 请求**: 使用 `httpc_get_file` 或 `httpc_get_file_dns` 函数发起 HTTP 请求。
    17.    *ip_addr_t* server_addr;
    18.    *IP4_ADDR*(&*server_addr*, 192, 168, 1, 1); *// 设置服务器 IP 地址*
    19.    const char *uri = "/path/to/resource";
    20.    *httpc_state_t* *connection;
    21.    *err_t* err = *httpc_get_file*(&*server_addr*, HTTP_DEFAULT_PORT, uri, &*settings*, my_recv_callback, NULL, &*connection*);
    22.    if (err != ERR_OK) {
    23.      *// 处理错误*
    24.    }
    25. 5. **接收数据回调函数**: 实现数据接收回调函数,用于处理接收到的数据。
    26.    *err_t* *my_recv_callback*(void **arg*, struct altcp_pcb **pcb*, struct pbuf **p*, *err_t* *err*) {
    27.      if (p != NULL) {
    28.    ​    *// 处理接收到的数据*
    29.    ​    *altcp_recved*(pcb, p->tot_len);
    30.    ​    *pbuf_free*(p);
    31.      }
    32.      return ERR_OK;
    33.    }
    34. 通过上述步骤,你可以使用 [http_client.c](vscode-file://vscode-app/d:/VS Code/resources/app/out/vs/code/electron-sandbox/workbench/workbench.html) 文件中的 HTTP 客户端功能发起 HTTP 请求并处理响应。确保在你的项目中正确配置 lwIP 库,并根据需要调整回调函数的实现。
    复制代码
menuconig开启http

28.png

29.png

30.png

31.png

例程路径
  1. luban-lite\packages\third-party\webclient\samples
复制代码
例程运行逻辑:

32.png

终端执行:

tab提示命令:

33.png
使用例程:

先连接WIFI
  1. wlan  wifi_connect jianzhiji 8765432111       
复制代码
检查是否分配ip地址
  1. ifconfig
复制代码
  1. ping 183.2.172.177
复制代码
请求:webclient_get_sample:

运行命令:
  1. web_get_test
复制代码
请求网站并返回数据
作用:

演示如何使用 WebClient 软件包发送 HTTP GET 请求并接收响应数据。文件中的代码展示了如何创建 WebClient 会话、发送 GET 请求、接收响应数据并处理内存分配错误等操作。
例程实现的功能


  • HTTP GET请求发送

    • 支持向指定URI(如 http://www.rt-thread.com/service/rt-thread.txt)发送GET请求。
    • 可处理 普通请求(分块传输或固定长度)和 简化请求(短数据场景)。

  • 响应数据处理

    • 接收服务器返回的响应数据,并打印输出到终端。
    • 自动处理 分块传输编码(Chunked Transfer Encoding)固定内容长度(Content-Length) 两种HTTP响应格式。

  • 命令行交互支持

    • 通过RT-Thread的 FINSH/MSH 命令行接口,提供用户可配置的测试命令,支持自定义URI和请求模式。

终端输出结果:

34.png

使用函数命令,访问
  1. web_get_test url
复制代码
35.png

例如访问官方测试网站
  1. web_get_test http://www.rt-thread.com/service/rt-thread.txt
复制代码
终端返回的结果
36.png

网站内容:
37.png

内容可以对应上,证明成功请求网站并返回了内容
自定义URI——访问个人网站
  1. web_get_test https://www.cnblogs.com/tianwuyvlianshui
复制代码
该问题表示未启用https,确实如其言,我们只开启了http,后续开启https再尝试
38.png

测试其他http网站
  1. # 测试 GET 请求
  2. curl http://httpbin.org/get
  3. # 测试 POST 请求
  4. curl -X POST http://httpbin.org/post -d "key=value"
  5. # 返回指定状态码(如 404)
  6. curl http://httpbin.org/status/404
复制代码
1、测试 GET 请求
  1. web_get_test http://httpbin.org/get
复制代码
httpbin.org


  • 用途:最全面的 HTTP 测试服务,支持 GET/POST/PUT/DELETE 等方法,可返回请求头、IP、状态码等。
该网站是测试网站,用于测试 HTTP 请求的公共服务,它会将你的请求信息原样返回。
39.png

测试带参数请求
  1. web_get_test http://httpbin.org/get?name=RT-Thread&id=123
复制代码
40.png

成功添加访问参数
  1.   "name": "RT-Thread",
  2.   "id": "123"
复制代码
测试html网站
  1. web_get_test http://example.com
复制代码
41.png

成功返回该静态网站的html文件
将返回的html保存打开就是该网站
42.png

测试 返回指定状态码(如 404)
  1. web_get_test http://httpbin.org/status/404
复制代码
43.png

webclient_post_sample:

运行命令:
  1. web_post_test
复制代码
  1. web_post_test url
复制代码
  1. web_post_test http://www.rt-thread.com/service/echo
复制代码
作用:

演示如何使用 WebClient 软件包发送 HTTP POST 请求并接收响应数据。文件中的代码展示了如何创建 WebClient 会话、发送 POST 请求、接收响应数据并处理内存分配错误等操作。
实现了如何使用 WebClient 软件包发送 HTTP POST 请求并接收响应数据。具体实现了以下功能:

  • 定义常量和变量:定义了响应缓冲区大小、请求头缓冲区大小和默认的 POST 请求 URI。
  • 发送普通 POST 请求

    • 函数 webclient_post_comm 创建 WebClient 会话,构建请求头,发送 POST 请求,并接收和打印响应数据。

  • 发送简化 POST 请求

    • 函数 webclient_post_smpl 创建请求头,发送 POST 请求,并接收和打印响应数据。

  • 测试函数

    • 函数 webclient_post_test 根据命令行参数选择发送普通 POST 请求或简化 POST 请求,并处理 URI 内存分配和释放。

  • 命令行集成

    • 使用 FinSH 命令行系统集成测试命令 web_post_test,可以在命令行中执行 POST 请求测试。

终端输出结果:

44.png


webclient_shard_download_sample:

运行命令:
  1. web_shard_test
复制代码
作用:

演示如何使用 WebClient 软件包进行分片下载。文件中的代码展示了如何发送 HTTP GET 请求并分片接收响应数据,以及如何处理和打印接收到的数据。
终端输出结果:

45.png


测试http pose:

如果服务器是回显服务(如 http://www.rt-thread.com/service/echo),响应内容应与发送的 post_data 完全一致
终端测试命令:
  1. web_post_test http://www.rt-thread.com/service/echo
复制代码
pose发送内容:
46.png

终端打印pose响应
47.png

响应内容应与发送的 post_data 完全一致
D133 ping 电脑

电脑与板子同连手机热点
电脑ip
48.png

板卡ip
49.png

可以看到在同一局域网192.168.106.xxx
理论上可以ping通,实际则可能不行,原因是电脑防护墙阻挡
关闭则可以ping通(测试完记得重新开启)
50.png
51.png
抓包
52.png

53.png

54.png
  1. web_post_test http://192.168.106.31:8080
复制代码
带参数
  1. web_post_test http://192.168.106.31:8080?a=1&b=2&c=3
复制代码
测试单片机http pose请求
使用python搭建内网服务器
  1. from http.server import BaseHTTPRequestHandler, HTTPServer  # 从http.server模块导入BaseHTTPRequestHandler和HTTPServer类
  2. import time  # 导入time模块,用于处理时间相关功能
  3. host_ip = "0.0.0.0"  # 监听所有IP地址,表示服务器将接受来自任何IP的请求
  4. port = 8080          # 端口号
  5. class RequestHandler(BaseHTTPRequestHandler):
  6.     # 定义一个处理POST请求的方法
  7.     def do_POST(self):
  8.         # 从请求头中获取Content-Length字段,该字段表示请求体的长度
  9.         content_length = int(self.headers['Content-Length'])
  10.         # 读取请求体数据,长度为content_length,并将其解码为utf-8字符串
  11.         post_data = self.rfile.read(content_length).decode('utf-8')
  12.         # 打印接收到的POST数据
  13.         print(f"Received POST data: {post_data}")
  14.         # 发送HTTP响应状态码200,表示请求成功
  15.         self.send_response(200)
  16.         # 发送响应头,设置Content-type为text/plain,表示响应体是纯文本
  17.         self.send_header('Content-type', 'text/plain')
  18.         # 结束响应头
  19.         self.end_headers()
  20.         # 向客户端发送响应体数据"OK",表示处理成功
  21.         self.wfile.write(b"OK")
  22. server = HTTPServer((host_ip, port), RequestHandler)
  23. print(f"Server running at http://{host_ip}:{port}")
  24. server.serve_forever()
复制代码
D133端(客户端,发送端,发送HTTP POST请求到服务器(内网)):
请求的数据(默认POST请求数据)
55.png

将数据通过http post 发送到服务器
56.png

命令(命令+网址):
  1. web_post_test http://192.168.106.31:8080
复制代码
57.png

58.png

在PC
59.png

PC端(内网服务器,服务端,作接收端)
60.png



数据上报对接api

URL头部
  1. http://xxx
复制代码
URL头部+api
  1. web_post_test http://xxx/api/yyy
复制代码
Postman

Postman 是一款广泛应用于 API 开发与测试 的协作工具,旨在简化 API 的生命周期管理(设计、开发、测试、部署、监控等)。
主要功能


  • API 请求测试与调试

    • 支持发送 HTTP/HTTPS 请求(GET、POST、PUT、DELETE 等)。
    • 可自定义请求头(Headers)、参数(Params)、身份验证(OAuth、JWT 等)和请求体(Body)。
    • 直观的界面帮助快速调试 API,查看响应状态码、响应时间和返回数据(JSON、XML 等)。

  • 自动化测试

    • 使用 JavaScript 编写测试脚本,验证 API 响应是否符合预期。
    • 支持断言(Assertions)、动态变量和环境变量,提升测试灵活性。
    • 集成 CI/CD 工具(如 Jenkins、GitHub Actions)通过 Newman 命令行工具运行自动化测试。

  • 协作与文档

    • 团队可共享 API 集合(Collections) 和环境配置,提升协作效率。
    • 自动生成 API 文档,支持一键发布,便于前后端开发者或第三方调用者查阅。

  • Mock 服务器

    • 创建虚拟 API 端点,模拟真实响应,支持前端开发与后端 API 并行工作。

  • 监控与性能测试

    • 定期运行 API 测试,监控服务可用性与性能,生成报告分析潜在问题。

适用场景


  • 开发者:快速调试接口,验证功能逻辑。
  • 测试工程师:设计自动化测试用例,确保 API 稳定性。
  • 团队协作:统一管理 API 资产,减少沟通成本。
  • 文档编写:自动生成易读的 API 文档,替代手动维护。
版本与平台


  • 免费版:满足个人基础需求(请求测试、简单自动化)。
  • 付费版(Pro/Enterprise):解锁团队协作、高级监控、私有 API 文档等功能。
  • 跨平台支持:提供 Windows、macOS、Linux 客户端及网页版。
优势


  • 用户友好:图形化操作降低学习成本,替代命令行工具(如 cURL)。
  • 生态丰富:支持 OpenAPI 规范、WebSocket 测试、GraphQL 等扩展场景。
  • 云端同步:数据云端存储,多设备无缝切换。
简单示例


  • 在 Postman 中新建请求,输入 API 地址。
  • 设置请求方法(如 POST),添加 JSON 格式的请求体。
  • 添加测试脚本验证响应状态码是否为 200。
  • 保存到集合,分享给团队成员或生成文档。
无论是独立开发还是团队协作,Postman 都能显著提升 API 开发效率,是现代软件工程中不可或缺的工具之一。
API文档解析与使用

api接口网址
  1. http://xxx
复制代码
涉及实际产品,略
Postman测试应用

api接口网址
  1. http://xxx
复制代码
时间戳转换网站
  1. https://tool.lu/timestamp/
复制代码
网站头URL
  1. http://xxx
复制代码
使用方式:网站头URL+API尾部
例如
则使用该api的URL为
  1. http://xxx/api/yyy
复制代码
添加CJSON解析库

61.png

在串口终端控制HTTP_API访问服务器

[code]/*演示如何使用 WebClient 软件包发送 HTTP POST 请求并接收响应数据。文件中的代码展示了如何创建 WebClient 会话、发送 POST 请求、接收响应数据并处理内存分配错误等操作。*/#include #include #include #include // 定义POST请求响应缓冲区的大小为1024字节#define POST_RESP_BUFSZ                1024// 定义POST请求头部缓冲区的大小为1024字节#define POST_HEADER_BUFSZ              1024**涉及实际产品,略**typedef enum {    API_GET_BALANCE_NO,      // 远程编码    API_LOAD_KEY,            // 获取密钥    **涉及实际产品,略**} API_TYPE;// API地址映射表static const char* API_URI_MAP[] = {    [API_GET_BALANCE_NO]    = "**涉及实际产品,略**",    .......};// 获取API地址的宏#define GET_API_URI(api_type) (API_URI_MAP[(api_type)])/* 静态函数获取URI */static inline const char* get_api_uri(API_TYPE type) {    return API_URI_MAP[type];}// /* 函数调用初始化 */// const char* POST_LOCAL_URI = NULL;// void post_api_uris(char str) {//     POST_LOCAL_URI = get_api_uri(str);// }// 获取时间戳函数(get)// 定义一个静态函数get_timestamp,用于获取时间戳并存储在buffer中static int get_timestamp(char *buffer, size_t buffer_size){    // 定义一个指向webclient_session结构体的指针session,并初始化为RT_NULL    struct webclient_session *session = RT_NULL;    // 定义一个指向字符数组的指针response_buf,用于存储HTTP响应,并初始化为RT_NULL    char *response_buf = RT_NULL;    // 定义一个整型变量ret,用于存储函数返回值,并初始化为RT_EOK(表示成功)    int ret = RT_EOK;    // 定义一个常量字符串url,指向获取时间戳的URL    const char *url = "http://acs.m.taobao.com/gw/mtop.common.getTimestamp/";    // 创建一个webclient会话,缓冲区大小为512字节    session = webclient_session_create(512);    // 如果会话创建失败,打印错误信息并返回内存不足错误码    if (!session) {        rt_kprintf("[ERROR] Create session failed\n");        return -RT_ENOMEM;    }    // 使用webclient发送GET请求,如果返回值不是200(HTTP OK),打印错误信息并设置返回值为错误码    if ((ret = webclient_get(session, url)) != 200) {        rt_kprintf("[ERROR] GET failed (%d)\n", ret);        ret = -RT_ERROR;        // 跳转到退出标签,进行资源释放        goto __exit;    }    // 分配256字节的内存用于存储HTTP响应    response_buf = web_malloc(256);    // 如果内存分配失败,设置返回值为内存不足错误码并跳转到退出标签    if (!response_buf) {        ret = -RT_ENOMEM;        goto __exit;    }    // 从webclient会话中读取响应数据到response_buf,最多读取256字节    int total_read = webclient_read(session, response_buf, 256);    // 如果读取失败或没有读取到数据,设置返回值为错误码并跳转到退出标签    if (total_read
您需要登录后才可以回帖 登录 | 立即注册