当前位置: 首页 > news >正文

NRF52832学习笔记(41)——添加串口库libuarte

一、背景

由于板子上不支持硬件流控,在使用 app_uart_fifo 库接收串口大数据时,频繁报 APP_UART_COMMUNICATION_ERROR 错误,多次重新初始化后,串口也不再产生中断了。查看官方论坛后决定使用串口异步库 libuarte

二、简介

Libuarte 是一个 UARTE 库,由以下层组成:

  • nrf_libuarte_drv:一个低级 UARTE 驱动程序,具有扩展功能,如连续计算接收的字节、双缓冲、启动和停止接收器的可选事件,以及可在接收器启动和停止时触发的可选任务。
  • nrf_libuarte_async:适用于接收和传输异步数据包的库。它管理接收缓冲区并实现接收器非活动超时。库正在使用 nrf_libuarte。它旨在用于典型的 UART 用例,其中交易对手异步发送可变长度的数据包。在这种情况下,用户会在数据包边界(即超时)和 DMA 缓冲区已满时收到事件。

2.1 nrf_libuarte_drv

nrf_libuarte_drv 使用 EasyDMA 双缓冲功能和 PPI 连接来确保可靠的接收。连续接收由 STARTRX 任务建立,连接到 ENDRX 事件。STARTRX 任务启动后,将生成 RXSTARTED 事件。

在 RXSTARTED 事件中:

  • EasyDMA 已配置为传输,并且可以配置为下一次传输。
  • Configuration registers 被锁存。

使用这种方法时,系统延迟取决于所使用的缓冲区的大小。如果缓冲区足够大,系统可以确保完全接收,而无需流控制,延迟为数毫秒。这个最小延迟可以覆盖 SoftDevice 或任何其他更高优先级的中断和 flash 操作(包括 flash 页面擦除)。

此外,计数器模式下的专用 TIMER 外设用于跟踪接收到的字节数。

nrf_libuarte_drv 可以配置硬件事件来启动和停止接收器。例如,此选项可用于构建具有请求和响应引脚的低功耗 UART 协议,该协议仅在传输期间启用接收器。所有硬件任务和事件都与 PPI 连接,这允许不依赖于中断处理时间的自主操作。

nrf_libuarte_drv 正在使用以下硬件资源:

  • UARTE 实例
  • TIMER 实例
  • PPI 通道:
    • 如果未使用可选任务和事件,则至少 2 个 PPI 通道(在最多 255 次 EasyDMA 传输的设备上为 3 个)。
    • 如果使用可选任务和事件,则最多 9 个 PPI 通道和 2 个 PPI 组。

2.2 nrf_libuarte_async

nrf_libuarte_async 库构建在 lib_libuarte_drv 驱动程序之上。它实现了接收器非活动超时,这会导致一个包含接收数据量的事件。

该库具有用于接收的专用缓冲区,并处理来自驱动程序 (NRF_LIBUARTE_DRV_EVT_RX_BUF_REQ) 的缓冲区请求事件。

您可以使用以下选项之一实现接收器不活动超时,具体取决于可用资源:

  • 专用的 TIMER 外围设备
  • 专用 RTC 外设
  • 一个 app_timer 实例

TIMER/RTC 外设
TIMER 或 RTC 外设与 TIMER/RTC 外设中的字节边界事件 (RXDRDY) 和任务 CLEAR 之间的 PPI 连接一起使用。

TIMER/RTC 的配置方式是在 compare 事件上触发中断。当任务 CLEAR 未按时触发时,将触发中断。

configurable 中的超时和 resolution 等于所用外设的 tick length。

app_timer实例
除了 TIMER/RTC 外设 之外,还可以使用 app_timer 实例进行超时实现。此方法需要按指定的时间间隔定期生成 app_timer 事件。

超时时,app_timer 事件处理程序检查收到的字节数是否已更改。根据此检查,处理程序报告数据包边界。

与 TIMER/RTC 外设相比,超时分辨率较低,等于可以设置的最短app_timer超时。

nrf_libuarte_async 正在使用以下硬件资源:

  • UARTE 实例
  • TIMER 实例
  • 2 或 3 个 PPI 通道
  • 如果 TIMER 或 RTC 外围设备用于接收器非活动超时,则使用以下附加资源:
    • RTC 或 TIMER 实例
    • 2 个 PPI 通道

三、参考工程

libuarte 在 SDK v16.0 中得到了改进,它也从 Experimental 中移出并取代了串行库。

SDK\examples\peripheral\libuarte 中找到示例工程

四、添加组件库

基于 ble_app_uart 的工程,在 nRF_Drivers 文件夹和 nRF_Libraries 文件夹确认以下组件库是否存在,不存在则添加。

在 ble_app_uart 的工程中后三个文件没有,需要添加:

  1. 添加 nrfx_ppi.cnrfx_rtc.cnrfx_timer.c
    位于 SDK\modules\nrfx\drivers\src

  2. 添加 nrfx_libuarte_async.cnrfx_libuarte_drv.c
    位于 SDK\components\libraries\libuarte

  3. 添加 nrfx_queue.c
    位于 SDK\components\libraries\queue

  4. 添加上述编译文件路径

五、SDK配置

点击 sdk_config.h 文件

选择 Configuration Wizard

nRF_Drivers 中勾选PPI、RTC、TIMER相关选项

修改时钟配置,由于要移植的工程是ble_app_uart,其中蓝牙协议栈SoftDevice使用了RTC0和TIMER0,app_timer模块使用了RTC1,所以我们用于串口超时的时钟有RTC2、TIMER1和TIMER2等等。

nRF_Libraries 中勾选QUEUE相关选项

添加 NRF_LIBUARTE_ASYNC_WITH_APP_TIMERnrf_libuarte_drv 并勾选

// <q> NRF_LIBUARTE_ASYNC_WITH_APP_TIMER  - nrf_libuarte_async - libUARTE_async library#ifndef NRF_LIBUARTE_ASYNC_WITH_APP_TIMER
#define NRF_LIBUARTE_ASYNC_WITH_APP_TIMER 1
#endif// <h> nrf_libuarte_drv - libUARTE library//==========================================================
// <q> NRF_LIBUARTE_DRV_HWFC_ENABLED  - Enable HWFC support in the driver#ifndef NRF_LIBUARTE_DRV_HWFC_ENABLED
#define NRF_LIBUARTE_DRV_HWFC_ENABLED 0
#endif// <q> NRF_LIBUARTE_DRV_UARTE0  - UARTE0 instance#ifndef NRF_LIBUARTE_DRV_UARTE0
#define NRF_LIBUARTE_DRV_UARTE0 1
#endif// <q> NRF_LIBUARTE_DRV_UARTE1  - UARTE1 instance#ifndef NRF_LIBUARTE_DRV_UARTE1
#define NRF_LIBUARTE_DRV_UARTE1 0
#endif// </h> 
//==========================================================

六、使用例子

1)添加头文件

#include "nrf_libuarte_async.h"

2)添加全局变量(SDK16.0以上 中 ble_peripheral 的 ble_app_uart 工程)

// 使用TIMER2作为计数,不使用RTC和TIMER用作超时(如果前两个都不使用,则使用app_timer作为超时)
NRF_LIBUARTE_ASYNC_DEFINE(libuarte, 0, 2, NRF_LIBUARTE_PERIPHERAL_NOT_USED, NRF_LIBUARTE_PERIPHERAL_NOT_USED, 255, 3);
// 使用TIMER2作为计数,使用RTC2用作超时
//NRF_LIBUARTE_ASYNC_DEFINE(libuarte, 0, 2, 2, NRF_LIBUARTE_PERIPHERAL_NOT_USED, 255, 3);static uint8_t text[] = "UART example started.\r\n Loopback:\r\n";
static uint8_t text_size = sizeof(text);
static volatile bool m_loopback_phase;typedef struct {uint8_t * p_data;uint32_t length;
} buffer_t;NRF_QUEUE_DEF(buffer_t, m_buf_queue, 10, NRF_QUEUE_MODE_NO_OVERFLOW);

第3,4,5参数分别是TIMER接口用作libuarte字节统计,RTC接口用作超时,TIMER接口用作超时,二者选其一即可,如果都不使用,则使用app_timer作为超时。

其中蓝牙协议栈SoftDevice使用了RTC0和TIMER0,app_timer模块使用了RTC1,所以我们用于串口超时的时钟有RTC2、TIMER1和TIMER2等等。

3)修改main函数
这里由于串口超时使用的是app_timer,而非RTC或TIMER,所以这里将uart_init()往后放。

/**@brief Application main function.*/
int main(void)
{bool erase_bonds;// Initialize.
//    uart_init();log_init();timers_init();uart_init();buttons_leds_init(&erase_bonds);power_management_init();ble_stack_init();gap_params_init();gatt_init();services_init();advertising_init();conn_params_init();// Start execution.
//    printf("\r\nUART started.\r\n");NRF_LOG_INFO("Debug logging for UART over RTT started.");advertising_start();// Enter main loop.for (;;){idle_state_handle();}
}

4)添加串口初始化函数
这里由于串口超时使用的是app_timer,而非RTC或TIMER,所以这里将串口中断优先级调整的app_timer优先级高,修改为 APP_IRQ_PRIORITY_LOW_MID 及以上。

/**@brief  Function for initializing the UART module.*/
/**@snippet [UART Initialization] */
static void uart_init(void)
{ret_code_t err_code;nrf_libuarte_async_config_t nrf_libuarte_async_config = {.tx_pin     = TX_PIN_NUMBER,.rx_pin     = RX_PIN_NUMBER,.baudrate   = NRF_UARTE_BAUDRATE_115200,.parity     = NRF_UARTE_PARITY_EXCLUDED,.hwfc       = NRF_UARTE_HWFC_DISABLED,.timeout_us = 100,.int_prio   = APP_IRQ_PRIORITY_LOW_MID};err_code = nrf_libuarte_async_init(&libuarte, &nrf_libuarte_async_config, uart_event_handler, (void *)&libuarte);APP_ERROR_CHECK(err_code);nrf_libuarte_async_enable(&libuarte);err_code = nrf_libuarte_async_tx(&libuarte, text, text_size);APP_ERROR_CHECK(err_code);
}
/**@snippet [UART Initialization] */

5)添加串口中断处理函数
每当 nrf_libuarte_drv 设置 EasyDMA 接收缓冲区时,都会生成缓冲区请求事件 (NRF_LIBUARTE_DRV_EVT_RX_BUF_REQ)。在这种情况下,请确保应用程序使用 nrf_libuarte_drv_rx_buf_rsp 进行响应并提供新的缓冲区。新的接收缓冲区必须在刚刚开始的传输结束之前提供,否则 UARTE 将开始覆盖活动缓冲区,因为接收会自主重新启动。

如果设备不支持 16 位长的 EasyDMA 传输,则使用 EasyDMA 双缓冲功能以及 ENDTX 事件和 STARTTX 任务之间的 PPI 连接来确保连续传输。传输完成后,将生成 NRF_LIBUARTE_DRV_EVT_TX_DONE 事件。

void uart_event_handler(void * context, nrf_libuarte_async_evt_t * p_evt)
{nrf_libuarte_async_t * p_libuarte = (nrf_libuarte_async_t *)context;ret_code_t ret;switch (p_evt->type){case NRF_LIBUARTE_ASYNC_EVT_ERROR:bsp_board_led_invert(0);break;case NRF_LIBUARTE_ASYNC_EVT_RX_DATA:ret = nrf_libuarte_async_tx(p_libuarte,p_evt->data.rxtx.p_data, p_evt->data.rxtx.length);if (ret == NRF_ERROR_BUSY){buffer_t buf = {.p_data = p_evt->data.rxtx.p_data,.length = p_evt->data.rxtx.length,};ret = nrf_queue_push(&m_buf_queue, &buf);APP_ERROR_CHECK(ret);}else{APP_ERROR_CHECK(ret);}bsp_board_led_invert(1);m_loopback_phase = true;break;case NRF_LIBUARTE_ASYNC_EVT_TX_DONE:if (m_loopback_phase){nrf_libuarte_async_rx_free(p_libuarte, p_evt->data.rxtx.p_data, p_evt->data.rxtx.length);if (!nrf_queue_is_empty(&m_buf_queue)){buffer_t buf;ret = nrf_queue_pop(&m_buf_queue, &buf);APP_ERROR_CHECK(ret);UNUSED_RETURN_VALUE(nrf_libuarte_async_tx(p_libuarte, buf.p_data, buf.length));}}bsp_board_led_invert(2);break;default:break;}
}

6)串口接收
每次完成 EasyDMA 传输时,都会生成 NRF_LIBUARTE_DRV_EVT_RX_DATA 事件。事件结构包含指向数据和接收的数据量的指针。处理数据时,必须通过调用 nrf_libuarte_async_rx_free 用于释放接收到的缓冲区数据的函数。

上面串口中断处理函数是为了串口回环打印测试,实际应用可改为以下逻辑:

    case NRF_LIBUARTE_ASYNC_EVT_RX_DATA: {在此自定义串口处理(event->data.rxtx.p_data, event->data.rxtx.length)nrf_libuarte_async_rx_free(libuarte, event->data.rxtx.p_data, event->data.rxtx.length);} break;

7)串口发送
nrf_libuarte_async_tx 用于启动传输。
在传输完成时调用具有 NRF_LIBUARTE_ASYNC_EVT_TX_DONE 事件的事件处理程序。

七、工程代码

基于 nRF5_SDK_17.1.0_ddde560,仅用于移植文件添加参考。
百度网盘: https://pan.baidu.com/s/1yu34SDNoBl7Uy-WV18UO8A?pwd=999m 提取码: 999m


• 由 Leung 写于 2024 年 11 月 4 日

• 参考:nRF5 SDK v17.1.0: Libuarte - advanced UARTE driver (nordicsemi.com)
    nrf52840蓝牙开发之Libuarte外设移植

相关文章:

NRF52832学习笔记(41)——添加串口库libuarte

一、背景 由于板子上不支持硬件流控&#xff0c;在使用 app_uart_fifo 库接收串口大数据时&#xff0c;频繁报 APP_UART_COMMUNICATION_ERROR 错误&#xff0c;多次重新初始化后&#xff0c;串口也不再产生中断了。查看官方论坛后决定使用串口异步库 libuarte。 二、简介 Li…...

Moore Perf System 1.1版本

Moore Perf System&#xff08;一款性能分析工具&#xff09; 提供可视化界面&#xff0c;在时间轴上按时间顺序显示 CPU 和 GPU 的事件、吞吐和性能指标&#xff0c;帮助开发人员方便、快速、准确的定位到系统级别的性能瓶颈&#xff0c;进而进行针对性分析和优化&#xff0c;…...

SpringBoot+Shirp的权限管理

目录 怎么实现动态菜单 1.html页面 2.获取动态菜单 Shiro权限刷新 1. 配置Shiro 2. 创建权限刷新服务 3. 调用权限刷新服务 注意事项 如何更新ShiroFilter初始权限 怎么实现动态菜单 1.html页面 <ul class"nav side-menu"><!--第一重循环&#xf…...

OpenCV图像基础

目录 显示窗口 创建空白图像 保存图片 图像裁剪 调整图片大小 图像绘制 绘制圆形 绘制矩形 绘制直线 绘制文本 中文乱码 控制鼠标 视频处理 显示窗口 cv2.namedWindow(winname, flagsNone) 创建一个命名窗口&#xff0c;以便在该窗口中显示图像或进行其他图形操作…...

基于MATLAB的图像拼接技术

实验名称&#xff1a;基于MATLAB的图像拼接技术实验目的&#xff1a;利用图像拼接技术得到超宽视角的图像&#xff0c;用来虚拟实际场景。实验原理&#xff1a; 基于相位相关的图像拼接技术是一种基于频域的方法&#xff0c;通过求得图像在频域上是相位相关特点来找到特征位置…...

ComfyUI 快速入门(环境搭建)

ComfyUI 是一个现代化、灵活的用户界面&#xff08;UI&#xff09;工具&#xff0c;专为 AI 模型和深度学习框架设计&#xff0c;能够快速实现可视化操作和定制化界面。在本教程中&#xff0c;我们将介绍如何在本地机器上快速搭建 ComfyUI 环境&#xff0c;帮助你开始使用这一工…...

将HTML项目上传至Gitee仓库(详细教程)

1.登录giett giett地址链接:Gitee - 基于 Git 的代码托管和研发协作平台 2.新建一个giett仓库 创建后得到远程仓库&#xff1a; 3、在本地项目文件夹右击鼠标点击 Open Git Bash Here 4、输入命令 命令:git init&#xff0c;这个目录变成git可以管理的仓库&#xff0c;会出…...

如何应对Oracle SQL语句的数据去重问题,应该考虑哪几个方面?

引言 在数据管理和数据库设计中,数据去重是一个重要的课题。随着信息技术的快速发展,数据的产生速度和数量都在急剧增加,如何有效地管理和维护这些数据成为了一个亟待解决的问题。 数据去重不仅可以减少存储空间的占用,还可以提高数据查询的效率,确保数据的准确性和一致…...

论负载均衡技术在Web系统中的应用论文

一、概要叙述软件项目及其主要工作 在2023年&#xff0c;我有幸参与了某公司电子商务平台的研发项目&#xff0c;担任系统架构设计师一职。该项目旨在构建一个高性能、高可用性的电子商务平台&#xff0c;以支撑公司日益增长的在线业务需求。作为系统架构设计的核心成员&#…...

NumPy 数据类型

1.常用 NumPy 基本类型 &#xff08;1&#xff09;bool_&#xff1a;布尔型数据类型&#xff08;True 或者 False&#xff09; &#xff08;2&#xff09;int_&#xff1a;默认的整数类型&#xff08;类似C 语言long&#xff0c;int32 或 int64&#xff09; &#xff08;3&a…...

JavaScript——(4)

【DOM】 一、DOM基本概念 DOM&#xff08;Document Object Model&#xff0c;文档对象模型&#xff09;是 JavaScript 操作 HTML 文档的接口&#xff0c;使文档操作变得非常优雅、简便。 DOM 最大的特点就是将 HTML 文档表示为 “节点树”。 DOM 元素/节点&#xff1a;就是…...

每日一练 | DHCP Relay(DHCP 中继)

01 真题题目 DHCP Relay 又称为 DHCP 中继&#xff0c;下列关于 DHCP Relay 的说法正确的是&#xff08;多选&#xff09;&#xff1a; A. DHCP 协议多采用广播报文&#xff0c;如果出现多个子网则无法穿越&#xff0c;所以需要 DHCP Relay 设备。 B. DHCP Relay 一定是一台交…...

`psdparse`:解锁Photoshop PSD文件的Python密钥

文章目录 psdparse&#xff1a;解锁Photoshop PSD文件的Python密钥背景&#xff1a;为何选择psdparse&#xff1f;psdparse是什么&#xff1f;如何安装psdparse&#xff1f;简单函数使用方法应用场景常见Bug及解决方案总结 psdparse&#xff1a;解锁Photoshop PSD文件的Python密…...

考研要求掌握的C语言程度(插入排序)

插入排序是啥类型的排序 插入类型的 插入排序经常用在啥类型场景下 用在有序序列下的基础上插入新数据 时间复杂度分析 如果是有序的基础下&#xff0c;最好的时间复杂度是O&#xff08;n&#xff09;; 普通情况下是O&#xff08;n^2&#xff09; 插入排序的原理是啥&am…...

mybatis源码解析-sql执行流程

1 执行器的创建 1. SimpleExecutor 描述&#xff1a;最基本的执行器&#xff0c;每次查询都会创建新的语句对象&#xff0c;并且不会缓存任何结果。 特点&#xff1a; 每次查询都会创建新的 PreparedStatement 对象。 不支持一级缓存。 适用于简单的查询操作&#xff0c;不…...

Golang | Leetcode Golang题解之第538题把二叉搜索树转换为累加树

题目&#xff1a; 题解&#xff1a; func getSuccessor(node *TreeNode) *TreeNode {succ : node.Rightfor succ.Left ! nil && succ.Left ! node {succ succ.Left}return succ }func convertBST(root *TreeNode) *TreeNode {sum : 0node : rootfor node ! nil {if n…...

【linux】HTTPS 协议原理

1. 了解 HTTPS 协议原理 &#xff08;一&#xff09;认识 HTTPS HTTPS 也是一种应用层协议&#xff0c;是在 HTTP 协议的基础上引入了一个加密层 因为 HTTP协议的内容都是按照文本的方式进行传输的&#xff0c;这个过程中&#xff0c;可能会出现一些篡改的情况 &#xff08;…...

安利一款开源企业级的报表系统SpringReport

SpringReport是一款企业级的报表系统&#xff0c;支持在线设计报表&#xff0c;并绑定动态数据源&#xff0c;无需写代码即可快速生成想要的报表&#xff0c;可以支持excel报表和word报表两种格式&#xff0c;同时还可以支持excel多人协同编辑&#xff0c;后续考虑实现大屏设计…...

数据安全-接口数据混合加密笔记

接口数据传输安全设计方案 采用非对称加密对称加密混合方式&#xff0c;接口混合加、解密过程梳理&#xff1a; 后端准备sm2公钥和私钥后端将SM2公钥传输到前端前端生成SM4密钥前端使用SM2公钥加密SM4秘钥&#xff0c;获得密文使用SM4秘钥加密数据将密文和加密数据传输至后端…...

JeecgBoot入门

最近在了解低代码平台&#xff0c;其中关注到gitee上开源项目JeecgBoot&#xff0c;JeecgBoot官方也有比较完整的入门教学文档&#xff0c;这里我们将耕者官方教程学习&#xff0c;并将其记录下来。 一、项目简介 JeecgBoot 是一款基于代码生成器的低代码开发平台拥有零代码能力…...

谷歌浏览器插件

项目中有时候会用到插件 sync-cookie-extension1.0.0&#xff1a;开发环境同步测试 cookie 至 localhost&#xff0c;便于本地请求服务携带 cookie 参考地址&#xff1a;https://juejin.cn/post/7139354571712757767 里面有源码下载下来&#xff0c;加在到扩展即可使用FeHelp…...

【JavaEE】-- HTTP

1. HTTP是什么&#xff1f; HTTP&#xff08;全称为"超文本传输协议"&#xff09;是一种应用非常广泛的应用层协议&#xff0c;HTTP是基于TCP协议的一种应用层协议。 应用层协议&#xff1a;是计算机网络协议栈中最高层的协议&#xff0c;它定义了运行在不同主机上…...

从WWDC看苹果产品发展的规律

WWDC 是苹果公司一年一度面向全球开发者的盛会&#xff0c;其主题演讲展现了苹果在产品设计、技术路线、用户体验和生态系统构建上的核心理念与演进脉络。我们借助 ChatGPT Deep Research 工具&#xff0c;对过去十年 WWDC 主题演讲内容进行了系统化分析&#xff0c;形成了这份…...

前端倒计时误差!

提示:记录工作中遇到的需求及解决办法 文章目录 前言一、误差从何而来?二、五大解决方案1. 动态校准法(基础版)2. Web Worker 计时3. 服务器时间同步4. Performance API 高精度计时5. 页面可见性API优化三、生产环境最佳实践四、终极解决方案架构前言 前几天听说公司某个项…...

服务器硬防的应用场景都有哪些?

服务器硬防是指一种通过硬件设备层面的安全措施来防御服务器系统受到网络攻击的方式&#xff0c;避免服务器受到各种恶意攻击和网络威胁&#xff0c;那么&#xff0c;服务器硬防通常都会应用在哪些场景当中呢&#xff1f; 硬防服务器中一般会配备入侵检测系统和预防系统&#x…...

高等数学(下)题型笔记(八)空间解析几何与向量代数

目录 0 前言 1 向量的点乘 1.1 基本公式 1.2 例题 2 向量的叉乘 2.1 基础知识 2.2 例题 3 空间平面方程 3.1 基础知识 3.2 例题 4 空间直线方程 4.1 基础知识 4.2 例题 5 旋转曲面及其方程 5.1 基础知识 5.2 例题 6 空间曲面的法线与切平面 6.1 基础知识 6.2…...

第一篇:Agent2Agent (A2A) 协议——协作式人工智能的黎明

AI 领域的快速发展正在催生一个新时代&#xff0c;智能代理&#xff08;agents&#xff09;不再是孤立的个体&#xff0c;而是能够像一个数字团队一样协作。然而&#xff0c;当前 AI 生态系统的碎片化阻碍了这一愿景的实现&#xff0c;导致了“AI 巴别塔问题”——不同代理之间…...

.Net Framework 4/C# 关键字(非常用,持续更新...)

一、is 关键字 is 关键字用于检查对象是否于给定类型兼容,如果兼容将返回 true,如果不兼容则返回 false,在进行类型转换前,可以先使用 is 关键字判断对象是否与指定类型兼容,如果兼容才进行转换,这样的转换是安全的。 例如有:首先创建一个字符串对象,然后将字符串对象隐…...

零基础在实践中学习网络安全-皮卡丘靶场(第九期-Unsafe Fileupload模块)(yakit方式)

本期内容并不是很难&#xff0c;相信大家会学的很愉快&#xff0c;当然对于有后端基础的朋友来说&#xff0c;本期内容更加容易了解&#xff0c;当然没有基础的也别担心&#xff0c;本期内容会详细解释有关内容 本期用到的软件&#xff1a;yakit&#xff08;因为经过之前好多期…...

华硕a豆14 Air香氛版,美学与科技的馨香融合

在快节奏的现代生活中&#xff0c;我们渴望一个能激发创想、愉悦感官的工作与生活伙伴&#xff0c;它不仅是冰冷的科技工具&#xff0c;更能触动我们内心深处的细腻情感。正是在这样的期许下&#xff0c;华硕a豆14 Air香氛版翩然而至&#xff0c;它以一种前所未有的方式&#x…...