STM32F4_HAL_LWIP_RAM接口UDP实验

目录

RAW 的 UDP 接口简介

RAW 的 UDP 实验

硬件设计

例程功能

软件设计

UDP 配置步骤

软件设计流程图


RAW 的 UDP 接口简介

        UDP 协议的 RAW 的 API 功能函数,我们使用这些函数来完成 UDP 的数据发送和接收功能。

 (1) udp_new 函数

此函数用来创建一个 UDP 控制块,这个控制块用来描述 IP 地址、端口号和状态等信息,该函数实现源码如下所示:

struct udp_pcb *
udp_new(void)
{
struct udp_pcb *pcb;
/* 申请一个 UDP 内存池 */
pcb = (struct udp_pcb *)memp_malloc(MEMP_UDP_PCB);
/* 申请成功*/
if (pcb != NULL)
{
/* 初始化 PCB 控制块所有零 */
memset(pcb, 0, sizeof(struct udp_pcb));
/* pcb->ttl = 255 */
pcb->ttl = UDP_TTL;
}
return pcb;
}

        可以看到,该控制块的内存由内存池申请,申请成功之后设置该控制块的生存时间。

(2) udp_remove 函数

        从 PCB 控制块链表中移除一个控制块,并且把移除的控制块释放内存,该函数实现源码如下所示:

void
udp_remove(struct udp_pcb *pcb)
{
struct udp_pcb *pcb2;
mib2_udp_unbind(pcb);
/* 判断 pcb 被删除在列表的第一个 */
if (udp_pcbs == pcb)
{
/* 从第二 pcb 开始制作列表 */
udp_pcbs = udp_pcbs->next;
}
else/* pcb 不在列表的第一个 */
{
/* 遍历 pcb 列表 */
for (pcb2 = udp_pcbs; pcb2 != NULL; pcb2 = pcb2->next)
{
/* 在 udp_pcbs 列表中查找 pcb */
if (pcb2->next != NULL && pcb2->next == pcb)
{
/* 从列表中删除 pcb */
pcb2->next = pcb->next;
break;
}
}
}
memp_free(MEMP_UDP_PCB, pcb);
}

        以传入的控制块为条件,遍历 PCB 控制块链表,若链表中的控制块等于要移除的控制块,则该控制块移除 PCB 控制块链表,移除完成之后释放该控制块的内存。

(3) udp_recv 函数

        此函数用来设置接收回调函数及函数参数,若用户使用 RAW 接口实现 UDP,则用户必须调用此函数设置接收回调函数,该函数的源码如下所示:

void
udp_recv(struct udp_pcb *pcb, udp_recv_fn recv, void *recv_arg)
{
/* 调用 recv()回调和用户数据 */
pcb->recv = recv;
pcb->recv_arg = recv_arg;
}

        可以看出,设置的函数和形参都是由 UDP 控制块的字段指向。

RAW 的 UDP 实验

硬件设计

例程功能

        PC 端和开发板通过 UDP 协议连接起来, PC 端使用网络调试助手向开发板发送数据,开发板接收到以后在 LCD 上显示接收到的数据,我们也可以通过开发板上的按键发送数据给 PC。

 * 硬件资源及引脚分配
 * 1 LED灯
     DS0(RED)     : LED0 - PE0
 * 2 串口1 (PA9/PA10连接在板载USB转串口芯片CH340上面)
 * 3 正点原子 2.8/3.5/4.3/7/10寸TFTLCD模块(仅限MCU屏,16位8080并口驱动)
 * 4 ETH,YT8521网络芯片
        ETH_MDIO -------------------------> PA2
        ETH_MDC --------------------------> PC1
        ETH_RMII_REF_CLK------------------> PA1
        ETH_RMII_CRS_DV ------------------> PA7
        ETH_RMII_RXD0 --------------------> PC4
        ETH_RMII_RXD1 --------------------> PC5
        ETH_RMII_TX_EN -------------------> PG11
        ETH_RMII_TXD0 --------------------> PG13
        ETH_RMII_TXD1 --------------------> PG14
        ETH_RESET-------------------------> PD3
 * 2 独立按键
     KEY0    - PE2
     KEY1    - PE3
     KEY2    - PE4

相关硬件驱动参考正点原子探索者开发指南HAL库版本

软件设计

UDP 配置步骤

1) 创建 UDP 控制块

调用函数 udp_new 创建 UDP 控制块。

2) 连接指定的 IP 地址和端口号

调用函数 udp_connect 绑定远程 IP 地址和远程端口号。

3) 绑定本地 IP 地址与端口号

调用函数 udp_bind 绑定本地 IP 地址和本地端口号。

4) 注册接收回调函数

udp_recv 是注册接收回调函数,该函数需要自己编写。

5) 发送数据

调用函数 udp_send 发送数据。

软件设计流程图

lwip_demo.h

#ifndef _LWIP_DEMO_H
#define _LWIP_DEMO_H
#include "./SYSTEM/sys/sys.h"#define LWIP_SEND_DATA              0X80    /* 定义有数据发送 */
extern uint8_t lwip_send_flag;              /* UDP数据发送标志位 */void lwip_demo(void);#endif /* _CLIENT_H */

 lwip_demo.c

#include <stdint.h>
#include <stdio.h>
#include "./BSP/LCD/lcd.h"
#include "./MALLOC/malloc.h"
#include "./BSP/KEY/key.h"
#include "./SYSTEM/delay/delay.h"
#include "./BSP/LED/led.h"
#include "lwip/pbuf.h"
#include "lwip/udp.h"
#include "lwip/tcp.h"
#include "lwip_demo.h"
#include "lwip_comm.h"
#include "stdio.h"
#include "string.h"#define LWIP_DEMO_RX_BUFSIZE         2000  /* 定义udp最大接收数据长度 */
#define LWIP_DEMO_PORT               8080  /* 定义udp连接的本地端口号 *//* 接收数据缓冲区 */
uint8_t g_lwip_demo_recvbuf[LWIP_DEMO_RX_BUFSIZE]; 
/* 发送数据内容 */
char *g_lwip_demo_sendbuf = "ALIENTEK DATA\r\n";
/* 数据发送标志位 */
uint8_t g_lwip_send_flag;static void lwip_udp_callback(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port);
void lwip_udp_senddata(struct udp_pcb *upcb);
void lwip_udp_connection_close(struct udp_pcb *upcb);/*** @brief       设置远端IP地址* @param       无* @retval      无*/
void lwip_udp_set_remoteip(void)
{char *tbuf;uint16_t xoff;uint8_t key;lcd_clear(WHITE);g_point_color = RED;lcd_show_string(5, 30, 200, 16, 16, "STM32", g_point_color);lcd_show_string(5, 50, 200, 16, 16, "UDP Test", g_point_color);lcd_show_string(5, 70, 200, 16, 16, "Remote IP Set", g_point_color);lcd_show_string(5, 90, 200, 16, 16, "KEY0:+  KEY2:-", g_point_color);lcd_show_string(5, 110, 200, 16, 16, "KEY1:OK", g_point_color);tbuf = mymalloc(SRAMIN, 100); /* 申请内存 */if (tbuf == NULL)return;/* 前三个IP保持和DHCP得到的IP一致 */g_lwipdev.remoteip[0] = g_lwipdev.ip[0];g_lwipdev.remoteip[1] = g_lwipdev.ip[1];g_lwipdev.remoteip[2] = g_lwipdev.ip[2];sprintf((char *)tbuf, "Remote IP:%d.%d.%d.", g_lwipdev.remoteip[0], g_lwipdev.remoteip[1], g_lwipdev.remoteip[2]); /* 远端IP */lcd_show_string(5, 150, 210, 16, 16, tbuf, g_point_color);g_point_color = BLUE;xoff = strlen((char *)tbuf) * 8 + 5;lcd_show_xnum(xoff, 150, g_lwipdev.remoteip[3], 3, 16, 0, g_point_color);while (1){key = key_scan(0);if (key == KEY1_PRES)break;else if (key){if (key == KEY0_PRES)g_lwipdev.remoteip[3] ++; /* IP增加 */if (key == KEY2_PRES)g_lwipdev.remoteip[3] --; /* IP减少 */lcd_show_xnum(xoff, 150, g_lwipdev.remoteip[3], 3, 16, 0X80, g_point_color); /* 显示新IP */}}myfree(SRAMIN, tbuf);
}/*** @brief       UDP服务器回调函数* @param       arg :传入参数* @param       upcb:UDP控制块* @param       p   : 网络数据包* @param       addr:IP地址* @param       port:端口号* @retval      无*/
static void lwip_udp_callback(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port)
{uint32_t data_len = 0;struct pbuf *q;if (p != NULL) /* 接收到不为空的数据时 */{memset(g_lwip_demo_recvbuf, 0, LWIP_DEMO_RX_BUFSIZE); /* 数据接收缓冲区清零 */for (q = p; q != NULL; q = q->next) /* 遍历完整个pbuf链表 */{/* 判断要拷贝到LWIP_DEMO_RX_BUFSIZE中的数据是否大于LWIP_DEMO_RX_BUFSIZE的剩余空间,如果大于 *//* 的话就只拷贝LWIP_DEMO_RX_BUFSIZE中剩余长度的数据,否则的话就拷贝所有的数据 */if (q->len > (LWIP_DEMO_RX_BUFSIZE - data_len)) memcpy(g_lwip_demo_recvbuf + data_len, q->payload, (LWIP_DEMO_RX_BUFSIZE - data_len)); /* 拷贝数据 */else memcpy(g_lwip_demo_recvbuf + data_len, q->payload, q->len);data_len += q->len;if (data_len > LWIP_DEMO_RX_BUFSIZE) break; /* 超出UDP客户端接收数组,跳出 */}upcb->remote_ip = *addr;                                        /* 记录远程主机的IP地址 */upcb->remote_port = port;                                       /* 记录远程主机的端口号 */g_lwipdev.remoteip[0] = upcb->remote_ip.addr & 0xff;              /* IADDR4 */g_lwipdev.remoteip[1] = (upcb->remote_ip.addr >> 8) & 0xff;       /* IADDR3 */g_lwipdev.remoteip[2] = (upcb->remote_ip.addr >> 16) & 0xff;      /* IADDR2 */g_lwipdev.remoteip[3] = (upcb->remote_ip.addr >> 24) & 0xff;      /* IADDR1 */g_lwip_send_flag |= 1 << 6;                                       /* 标记接收到数据了 */pbuf_free(p);                                                   /* 释放内存 */}else{udp_disconnect(upcb);lcd_clear(WHITE);           /* 清屏 */lcd_show_string(30, 30, 200, 16, 16, "STM32", g_point_color);lcd_show_string(30, 50, 200, 16, 16, "UDP Test", g_point_color);lcd_show_string(30, 70, 200, 16, 16, "ATOM@ALIENTEK", g_point_color);lcd_show_string(30, 90, 200, 16, 16, "KEY1:Connect", g_point_color);lcd_show_string(30, 190, 210, 16, 16, "Connect break!", g_point_color);}
}/*** @brief       lwip_democ程序入口* @param       无* @retval      无*/
void lwip_demo(void)
{err_t err;struct udp_pcb *udppcb;      /* 定义一个UDP服务器控制块 */ip_addr_t rmtipaddr;         /* 远端ip地址 */char *tbuf;uint8_t key;uint8_t res = 0;uint8_t t = 0;lwip_udp_set_remoteip();/* 先选择IP */lcd_clear(WHITE);    /* 清屏 */g_point_color = RED;lcd_show_string(5, 30, 200, 16, 16, "STM32", g_point_color);lcd_show_string(5, 50, 200, 16, 16, "UDP Test", g_point_color);lcd_show_string(5, 70, 200, 16, 16, "ATOM@ALIENTEK", g_point_color);lcd_show_string(5, 90, 200, 16, 16, "KEY0:Send data", g_point_color);lcd_show_string(5, 110, 200, 16, 16, "KEY1:Exit", g_point_color);tbuf = mymalloc(SRAMIN, 200); /* 申请内存 */if (tbuf == NULL)return ;     /* 内存申请失败了,直接退出 */sprintf((char *)tbuf, "Local IP:%d.%d.%d.%d", g_lwipdev.ip[0], g_lwipdev.ip[1], g_lwipdev.ip[2], g_lwipdev.ip[3]); /* 服务器IP */lcd_show_string(5, 130, 210, 16, 16, tbuf, g_point_color);sprintf((char *)tbuf, "Remote IP:%d.%d.%d.%d", g_lwipdev.remoteip[0], g_lwipdev.remoteip[1], g_lwipdev.remoteip[2], g_lwipdev.remoteip[3]); /* 远端IP */lcd_show_string(5, 150, 210, 16, 16, tbuf, g_point_color);sprintf((char *)tbuf, "Remote Port:%d", LWIP_DEMO_PORT); /* 客户端端口号 */lcd_show_string(5, 170, 210, 16, 16, tbuf, g_point_color);g_point_color = BLUE;udppcb = udp_new();if (udppcb) /* 创建成功 */{IP4_ADDR(&rmtipaddr, g_lwipdev.remoteip[0], g_lwipdev.remoteip[1], g_lwipdev.remoteip[2], g_lwipdev.remoteip[3]);err = udp_connect(udppcb, &rmtipaddr, LWIP_DEMO_PORT);      /* UDP客户端连接到指定IP地址和端口号的服务器 */if (err == ERR_OK){err = udp_bind(udppcb, IP_ADDR_ANY, LWIP_DEMO_PORT);    /* 绑定本地IP地址与端口号 */if (err == ERR_OK)  /* 绑定完成 */{udp_recv(udppcb,lwip_udp_callback, NULL);           /* 注册接收回调函数 */g_point_color = BLUE;lcd_show_string(5, 190, lcddev.width - 30, lcddev.height - 190, 16, "Receive Data:", g_point_color); /* 提示消息 */g_point_color = MAGENTA;}else res = 1;}else res = 1;}else res = 1;while (res == 0){key = key_scan(0);if (key == KEY1_PRES)break;if (key == KEY0_PRES) /* KEY0按下了,发送数据 */{lwip_udp_senddata(udppcb);}if (g_lwip_send_flag & 1 << 6) /* 是否收到数据 */{lcd_fill(5, 230, lcddev.width - 1, lcddev.height - 1, WHITE); /* 清上一次数据 *//* 显示接收到的数据 */lcd_show_string(6, 230, lcddev.width - 2, lcddev.height - 230, 16, (char *)g_lwip_demo_recvbuf, g_point_color); g_lwip_send_flag &= ~(1 << 6); /* 标记数据已经被处理了 */}lwip_periodic_handle(); /* LWIP轮询任务 */delay_ms(2);t++;if (t == 200){t = 0;LED0_TOGGLE();}}g_point_color = DARKBLUE;lwip_udp_connection_close(udppcb);myfree(SRAMIN, tbuf);
}/*** @brief       UDP服务器发送数据* @param       upcb: UDP控制块* @retval      无*/
void lwip_udp_senddata(struct udp_pcb *upcb)
{struct pbuf *ptr;ptr = pbuf_alloc(PBUF_TRANSPORT, strlen((char *)g_lwip_demo_sendbuf), PBUF_POOL); /* 申请内存 */if (ptr){pbuf_take(ptr, (char *)g_lwip_demo_sendbuf, strlen((char *)g_lwip_demo_sendbuf)); /* 将g_lwip_demo_sendbuf中的数据打包进pbuf结构中 */udp_send(upcb, ptr);    /* udp发送数据 */pbuf_free(ptr);         /* 释放内存 */}
}/*** @brief       关闭tcp连接* @param       upcb: UDP控制块* @retval      无*/
void lwip_udp_connection_close(struct udp_pcb *upcb)
{udp_disconnect(upcb);udp_remove(upcb);               /* 断开UDP连接 */g_lwip_send_flag &= ~(1 << 5);    /* 标记连接断开 */lcd_clear(WHITE);               /* 清屏 */lcd_show_string(5, 30, 200, 16, 16, "STM32", g_point_color);lcd_show_string(5, 50, 200, 16, 16, "UDP Test", g_point_color);lcd_show_string(5, 70, 200, 16, 16, "ATOM@ALIENTEK", g_point_color);lcd_show_string(5, 90, 200, 16, 16, "KEY1:Connect", g_point_color);lcd_show_string(5, 190, 210, 16, 16, "STATUS:Disconnected", g_point_color);
}

主函数

#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/usart/usart.h"
#include "./SYSTEM/delay/delay.h"
#include "./BSP/LED/led.h"
#include "./BSP/LCD/lcd.h"
#include "./USMART/usmart.h"
#include "./BSP/KEY/key.h"
#include "./BSP/SRAM/sram.h"
#include "./MALLOC/malloc.h"
#include "lwip_comm.h"
#include "lwipopts.h"
#include "lwip_demo.h"/*** @breif       加载UI* @param       mode :  bit0:0,不加载;1,加载前半部分UI*                      bit1:0,不加载;1,加载后半部分UI* @retval      无*/
void lwip_test_ui(uint8_t mode)
{uint8_t speed;uint8_t buf[30];if(mode & 1<< 0){lcd_show_string(6, 10, 200, 32, 32, "STM32", DARKBLUE);lcd_show_string(6, 40, lcddev.width, 24, 24, "lwIP UDP Test", DARKBLUE);lcd_show_string(6, 70, 200, 16, 16, "ATOM@ALIENTEK", DARKBLUE);}if(mode & 1 << 1){lcd_show_string(6, 110, 200, 16, 16, "lwIP Init Successed", MAGENTA);if(g_lwipdev.dhcpstatus == 2){sprintf((char*)buf,"DHCP IP:%d.%d.%d.%d",g_lwipdev.ip[0],g_lwipdev.ip[1],g_lwipdev.ip[2],g_lwipdev.ip[3]);      /* 显示动态IP地址 */}else{sprintf((char*)buf,"Static IP:%d.%d.%d.%d",g_lwipdev.ip[0],g_lwipdev.ip[1],g_lwipdev.ip[2],g_lwipdev.ip[3]);    /* 打印静态IP地址 */}lcd_show_string(6, 130, 200, 16, 16, (char*)buf, MAGENTA);speed = ethernet_chip_get_speed();                                                                                  /* 得到网速 */if(speed){lcd_show_string(6, 150, 200, 16, 16, "Ethernet Speed:100M", MAGENTA);}else{lcd_show_string(6, 150, 200, 16, 16, "Ethernet Speed:10M", MAGENTA);}}
}int main(void)
{uint8_t t = 0;HAL_Init();                         /* 初始化HAL库 */sys_stm32_clock_init(336, 8, 2, 7); /* 设置时钟,168Mhz */delay_init(168);                    /* 延时初始化 */usart_init(115200);                 /* 串口初始化为115200 */usmart_dev.init(84);                /* 初始化USMART */led_init();                         /* 初始化LED */lcd_init();                         /* 初始化LCD */key_init();                         /* 初始化按键 */sram_init();                        /* SRAM初始化 */my_mem_init(SRAMIN);                /* 初始化内部SRAM内存池 */my_mem_init(SRAMEX);                /* 初始化外部SRAM内存池 */my_mem_init(SRAMCCM);               /* 初始化内部CCM内存池 */lwip_test_ui(1);                    /* 加载前半部分UI */lcd_show_string(6, 110, 200, 16, 16, "lwIP Init !!", BLUE);while (lwip_comm_init() != 0){lcd_show_string(6, 110, 200, 16, 16, "lwIP Init failed!!", BLUE);delay_ms(500);lcd_fill(6, 50, 200 + 30, 50 + 16, WHITE);lcd_show_string(6, 110, 200, 16, 16, "Retrying...       ", BLUE);delay_ms(500);LED1_TOGGLE();}while (!ethernet_read_phy(PHY_SR))  /* 检查MCU与PHY芯片是否通信成功 */{printf("MCU与PHY芯片通信失败,请检查电路或者源码!!!!\r\n");}#if LWIP_DHCPlcd_show_string(6, 130, 200, 16, 16, "DHCP IP configing... ", BLUE);    /* 开始DHCP */while ((g_lwipdev.dhcpstatus != 2) && (g_lwipdev.dhcpstatus != 0XFF))          /* 等待DHCP获取成功/超时溢出 */{lwip_periodic_handle();delay_ms(1000);}
#endiflwip_demo();                /* lwIP程序入口 */lwip_test_ui(2);            /* 加载后半部分UI */while (1){lwip_periodic_handle(); /* LWIP轮询任务 */delay_ms(2);t ++;if (t >= 200){t = 0;LED0_TOGGLE();}}
}

完整工程参考正点原子lwip源码RAW_UDP实验

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/18651.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何用俄语预定酒店,柯桥外贸俄语培训

-Привет, Алекс! Как твои дела? 你好&#xff0c;阿列克斯&#xff01;你最近好吗&#xff1f; -Отлично! Я скоро уезжаю на 10 дней в Санкт-Петербург, но никак не могу найти там…

如何查询Windows 10电脑的IP地址

如何查询Windows 10电脑的IP地址 引言 在Windows 10操作系统中&#xff0c;查询电脑的IP地址是一项基本而重要的任务&#xff0c;无论是为了配置网络、解决连接问题&#xff0c;还是进行远程访问。 基础知识 IP地址&#xff1a;互联网协议地址&#xff0c;用于标识网络中的…

帆软报表点击表格给数据集传递参数案例

一、效果 有四个模块&#xff0c;分别是采购总金额&#xff0c;采购总数量&#xff0c;采购合同数量&#xff0c;采购合同申请数量通过点击单元格上的月份&#xff0c;展示不同的月份数据&#xff0c;进行单元格和表格之间的联动 二、准备好数据库表和展示数据内容 2.1 建表 …

私人健身与教练预约|基于SprinBoot+vue的私人健身与教练预约管理系统(源码+数据库+文档)

私人健身与教练预约管理系统 目录 基于SprinBootvue的私人健身与教练预约管理系统 一、前言 二、系统设计 三、系统功能设计 1系统功能模块 2后台功能模块 5.2.1管理员功能 5.2.2用户功能 5.2.3教练功能 四、数据库设计 五、核心代码 六、论文参考 七、最新计算…

CentOS8搭载正反向解析dns服务器

1.介绍&#xff08;是什么&#xff09; DNS&#xff08;Domain Name System&#xff09;&#xff0c;即域名系统&#xff0c;是一个将域名和 IP 地址相互映射的分布式数据库&#xff0c;它可以将用户输入的域名转换成对应的 IP 地址。DNS 由多个服务器组成&#xff0c;分为多个…

Creo模型按一定的比例放大或缩小(实际尺寸)

原来&#xff0c;距离是100mm 缩放操作 放大3倍&#xff0c;距离变为300mm

使用QtCreator C++编写串口调试助手

100编程书屋_孔夫子旧书网 1.首先看一下我设计的界面&#xff08;我这里比较简单&#xff0c;大家可根据自己的需求进行设计&#xff09; &#xff08;界面设计的过程中&#xff0c;每一个控件的名称最好进行修改&#xff0c;便于后续控件太多不好区分&#xff0c;给控件命名的…

6.1 Go 数组

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:「stormsha的主页」…

深入分析 Android Activity (十一)

文章目录 深入分析 Android Activity (十一)1. Activity 的内存管理和优化1.1 内存泄漏的常见原因1.2 避免内存泄漏的方法1.3 内存泄漏检测工具 2. Activity 的配置变更处理2.1 处理配置变更2.2 保存和恢复状态2.3 使用 ViewModel 3. Activity 的测试3.1 单元测试3.2 UI 测试 4…

质量工具系列之Dependency-Track

项目开发中依赖了很多第三方开源工具&#xff0c;对于其版本&#xff0c;漏洞等因为时间或者是数量太多而无法关注到&#xff0c;Dependency-Track解决这些问题。 Dependency-Track 是一个开源组件分析平台&#xff0c;是开放网络应用安全项目&#xff08;OWASP&#xff09;的一…

web自动化-数据驱动与失败用例截图、失败重新运行

因为只有失败的用例需要截图&#xff0c;那么问题就是&#xff1a; 什么时候用例会失败&#xff1f; 数据驱动测试 我们前面覆盖到的用例都是正常的用例&#xff0c;如果要测试异常的用例呢&#xff1f; 我们来写一下登录的异常 场景&#xff1a;【login_page】 # 用户输入框…

LAMP集群分布式实验报告

前景&#xff1a; 1.技术成熟度和稳定性&#xff1a; LAMP架构&#xff08;Linux、Apache、MySQL、PHP&#xff09;自1998年提出以来&#xff0c;经过长时间的发展和完善&#xff0c;已经成为非常成熟和稳定的Web开发平台。其中&#xff0c;Linux操作系统因其高度的灵活性和稳…

【XR806开发板试用】基础篇,从零开始搭建一个LCD彩屏时钟(ST7735S驱动)

本文从搭建环境开始&#xff0c;step by step教大家使用XR806实现驱动SPI屏幕&#xff08;ST7735S驱动&#xff09;&#xff0c;并连接WiFi实现ntp对时&#xff0c;最终实现把时间显示到屏幕上。 #1. 搭建开发环境 1. 安装编译环境所需的依赖包 基于ubuntu 20.04&#xff0c;按…

UI自动化测试最佳设计模式POM

当使用Selenium进行UI自动化测试时&#xff0c;Page Object Model&#xff08;POM&#xff09;是一种最佳实践的设计模式。POM的核心思想是通过将页面封装成对象&#xff0c;使得测试代码更加清晰、可维护和可重用。 POM的主要组成部分包括页面对象类、元素定位方式和操作方法…

LabVIEW车轮动平衡检测系统

LabVIEW车轮动平衡检测系统 随着汽车行业的快速发展&#xff0c;车轮动平衡问题对乘坐舒适性、操控稳定性及安全性的影响日益凸显&#xff0c;成为了提高汽车性能的一个关键环节。传统的检测系统因精度低、成本高、操作复杂等问题&#xff0c;难以满足现代汽车行业的需求。开发…

行车安全:UWB模块的智能化在车辆安全系统中的作用

随着交通车辆数量的不断增加和道路交通拥堵的加剧&#xff0c;车辆安全问题日益引起人们的关注。在这种背景下&#xff0c;超宽带&#xff08;UWB&#xff09;技术作为一种新兴的定位技术&#xff0c;正逐渐应用于车辆安全系统中&#xff0c;为提高车辆行车安全性提供了新的解决…

Django配置

后端开发&#xff1a; python 解释器、 pycharm 社区版、 navicate 、 mysql(phpstudy) 前段开发&#xff1a; vs code 、 google 浏览器 django 项目配置 配置项目启动方式 创建模型 创建一个应用 在应用中创建模型类 根据模型类生成数据表 创建应用 创建模型类 …

智能除螨—wtn6040-8s语音芯片方案引领除螨仪新时代

语音螨仪开发背景&#xff1a; 随着物联网技术的快速发展&#xff0c;除螨仪作为家庭清洁的重要工具&#xff0c;其智能化、人性化的设计成为提升市场竞争力的关键。置入语音芯片的除螨仪&#xff0c;通过开机提示、工作状态反馈、操作指引、故障提醒等内容。用户可以更加直观…

邦注科技三机一体除湿干燥机在工业中的应用

三机一体除湿干燥机在工业中的应用广泛且重要&#xff0c;其结合了传统除湿机、冷凝器和加热器的功能&#xff0c;具有节能、环保、方便等特点。以下是关于三机一体除湿干燥机在工业中应用的详细解析&#xff1a; 一、应用领域 电子制造行业&#xff1a;在半导体、集成电路和…

大模型中的Tokenizer

在使用GPT 、BERT模型输入词语常常会先进行tokenize 。 tokenize的目标是把输入的文本流&#xff0c;切分成一个个子串&#xff0c;每个子串相对有完整的语义&#xff0c;便于学习embedding表达和后续模型的使用。 一、粒度 三种粒度&#xff1a;word/subword/char word词&a…