STM32基础学习笔记-NVIC中断面试基础题4

news2024/11/16 9:38:34

第四章、NVIC: 外部中断_串口中断

1、按键按下后,GPIO 会产生一个上升/下降沿,G030内部是如何触发外部中断的呢?

配置GPIO引脚:

首先,需要将特定的GPIO引脚配置为输入模式,并设置为外部中断源。这通常通过配置寄存器来完成。

选择触发方式:

在G030中,可以选择上升沿、下降沿或双边沿触发外部中断。这个设置通常在外部中断控制寄存器(如EXTI寄存器)中进行配置。

中断使能:

需要使能对应的外部中断线,以便在GPIO引脚状态变化时能够触发中断。这通常涉及到设置中断使能寄存器。

中断向量表:

当外部中断被触发时,处理器会根据中断向量表跳转到相应的中断服务程序(ISR)。

中断处理:

在ISR中,可以执行特定的操作,例如读取按键状态、切换LED状态等。ISR执行完毕后,处理器会恢复到中断发生前的状态。

常见问题
1、基本概念:异常和中断 ? (处理器的内外部
2、中断意义和作用 ?
3、中断处理过程 ?
4、NVIC 定义?位置 ?
5、中断向量表 ?在哪儿定义 ?
## 2、中断向量表 是一个存储器区域,其中包含了所有中断服务程序(ISR)的入口地址。当中断发生时,处理器会根据中断类型查找对应的入口地址,并跳转到该地址执行相应的ISR。

定义位置:

在STM32等微控制器中,中断向量表通常在启动文件(startup file)中定义。启动文件是编译后生成的二进制文件的一部分,通常包含以下内容:

中断向量表的起始地址:通常位于内存的固定地址(如0x00000000)。

中断向量的具体实现:每个中断向量对应一个ISR的地址。

中断向量表示例:

void (* const g_pfnVectors[])(void) attribute ((section(“.isr_vector”))) = {

(void (*)(void))((uint32_t)&_estack), // 栈顶地址

Reset_Handler,                        // 复位中断

NMI_Handler,                          // NMI中断

HardFault_Handler,                    // 硬故障中断

// ... 其他中断向量};

NVIC 工作原理 ?

NVIC 中断优先级及其分组 ? ( 比较原则:抢占 -> 响应 -> 自然 )

3、中断嵌套 ?为什么会发生的嵌套 ?

**优先级机制:**不同中断源可以设置不同的优先级。当一个高优先级的中断在低优先级中断的服务程序执行期间发生时,系统会中断当前的服务程序,转而执行高优先级的中断服务程序。
**中断使能:**在某些微控制器中,ISR可以在执行期间允许其他中断的响应,这样就可能导致中断嵌套。
**硬件设计:**某些微控制器的硬件设计允许中断嵌套,以提高系统的响应能力。

4、外部中断 定义( GPIO 上升沿 下降沿 )

外部中断是指由外部设备或信号触发的中断请求,通常用于响应外部事件,如按键、传感器信号、通信接口等。外部中断允许微控制器在特定事件发生时立即中断当前程序的执行,转而执行相应的中断服务程序(ISR),以处理这些事件。

EXTI工作原理 ? GPIO -> AFIO -> EXTI

5、EXTI支持的触发方式

上升沿触发(Rising Edge Trigger):

当信号从低电平变为高电平时触发中断。

下降沿触发(Falling Edge Trigger):

当信号从高电平变为低电平时触发中断。

双边沿触发(Both Edge Trigger):

当信号在上升沿或下降沿变化时都触发中断。

软件触发(Software Trigger):

通过软件手动触发中断,通常用于调试或特定应用场景。

6、AFIO定义及其工作原理

AFIO(Alternate Function I/O)是STM32微控制器中的一个外设,用于配置和管理引脚的替代功能。它允许用户将某些引脚配置为特定的功能,如外部中断、定时器输入、串口通信等,而不仅仅是普通的GPIO功能。

工作原理:

引脚复用:STM32的每个引脚可以被配置为多种功能。AFIO负责管理这些引脚的复用,确保在不同的外设之间正确分配引脚。

外部中断配置:AFIO可以配置外部中断的触发源。通过设置特定的寄存器,用户可以选择哪个引脚作为外部中断的输入,并指定其触发方式(上升沿、下降沿或双边沿)。

引脚映射:AFIO提供了引脚映射功能,允许用户将外设功能映射到不同的引脚上。这对于设计灵活的电路非常重要,尤其是在资源有限的情况下。

寄存器配置:AFIO的配置通常涉及设置特定的寄存器,如AFIO_MAPR寄存器,用于选择引脚的替代功能。

示例代码:

// 启用AFIO时钟

RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);

// 配置外部中断线

GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0); // 将PA0配置为外部中断源

// 配置EXTI触发方式

EXTI_InitTypeDef EXTI_InitStructure;

EXTI_InitStructure.EXTI_Line = EXTI_Line0; // 选择外部中断线0

EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; // 中断模式

EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; // 上升沿触发

EXTI_InitStructure.EXTI_LineCmd = ENABLE; // 使能外部中断

EXTI_Init(&EXTI_InitStructure);

7、外部中断整体执行流程

中断源配置:

配置外部中断源(如GPIO引脚)以检测特定的事件(如上升沿、下降沿或双边沿)。

设置中断优先级和触发方式。

中断使能:

使能外部中断控制器(如EXTI)和相应的中断线。

确保中断在NVIC(嵌套向量中断控制器)中被使能。

事件触发:

当外部事件发生(如按键按下或释放)时,外部中断被触发。

触发信号会被送到中断控制器。

中断请求:

中断控制器生成中断请求(IRQ),并将其发送到NVIC。

NVIC根据中断优先级决定是否响应该中断。

中断处理:

如果当前没有高优先级中断在执行,NVIC会暂停当前执行的程序,保存上下文。

跳转到相应的中断服务程序(ISR)。

ISR执行:

在ISR中,执行中断处理逻辑,例如读取传感器数据、切换LED状态等。

清除中断标志位,以便下次中断能够被正确触发。

恢复上下文:

ISR执行完毕后,恢复之前保存的上下文。

恢复后,继续执行被中断的程序。

8、NVIC学习

1.NVIC

挂载在AHB下的外设

全称:嵌套向量中断控制器 中断,讲究实时性

异常:由cpu内部发生的错误(不可控),nvic中指的是某个引脚发生上升沿或者下降沿的跳变(触发时机)

中断:由外设引发的错误(可控)

NVIC的中断优先级由优先级寄存器的4位(0-15决定)

抢占优先级高于响应优先级高于自然优先级(抢占和响应,数值小,级别高)

2.AFIO外设

主要用于配置和管理引脚的替代功能

主要功能:

引脚复用:通过 AFIO,可以将多个外设的功能映射到同一组引脚上,从而节省引脚资源。

中断管理:AFIO 还可以用于配置外部中断的触发方式,例如上升沿、下降沿或双边沿触发。

JTAG/SWD 配置:AFIO 允许用户选择是否启用 JTAG 或 SWD 调试接口,以便在开发过程中进行调试。

寄存器:

AFIO 的配置通常涉及到几个寄存器:

AFIO_MAPR:用于配置引脚的复用功能和中断的触发方式。

AFIO_EXTICR:用于配置外部中断的引脚映射。

使用场景:

多功能引脚:在设计中需要使用多个外设时,AFIO 可以帮助实现引脚的灵活配置。

外部中断:在需要响应外部事件时,AFIO 可以配置中断引脚的触发方式。

配置示例:

在 STM32 的开发中,使用 HAL 库或直接操作寄存器来配置 AFIO。例如,配置某个引脚为 USART的TX引脚,通常需要设置相应的AFIO_MAPR寄存器。

与门:都为1才是1 或门:有一个为1就是1

3.EXTI中断流程

PA0-GPIO-AFIO-EXTI-NVIC-CPU

             复用输入->引脚复用(将不同分分组但引脚号相同的划分为一组,引出一根外部中断线exti0)EXTI这儿检测上升沿或者下降沿是否发生,或门这儿是判断软件触发还是硬件触发,与门,触发出现,中断线屏蔽,接着是挂起寄存器,起到了缓冲的作用,再到NVIC,起到了打开或者关闭我们的外部中断线的作用,让不让外部中断线进去,为外部中断线赋予抢占或者/响应优先级。

PA0引脚触发外部中断的流程详细说明:

用于接收外部信号的PA0引脚,在使用外部中断时,PA0被配置为输入模式,以便检测外部信号的变化。然后是对GPIO进行配置,通过配置寄存器,可以将PA0设置为输入模式,并选择上拉或下拉电阻,以确保在没有外部信号时引脚的状态是确定的。接着通过AFIO配置 PA0的中断功能。具体来说,就是将PA0的中断线(EXTI Line)与GPIO引脚关联,以便在引脚状态变化时触发中断。

EXTI负责监测GPIO引脚的状态变化,并生成中断请求。对于PA0,EXTI控制器会监测其状态变化(上升沿、下降沿或双边沿),并在状态变化时生成中断请求。

在这里,主要是边沿检测电路,上升沿触发选择寄存器检测到上升沿,接着遇到或门进入下一步,然后中断屏蔽寄存器和这个输出的都是1,接下来的与门也是1,经过挂起请求寄存器,输出至NVIC中断控制器;

一旦NVIC确定要响应中断,它会将CPU的执行流转移到与PA0相关联的中断服务例程。此时,CPU会暂停当前的任务,执行中断服务例程中的代码,以处理外部中断事件。中断服务例程执行完毕后,CPU会恢复到中断发生前的状态,继续执行之前的任务。

4.EXTI

使能和优先级

Hal库中,中断的一般流程:

①中断向量表提供中断服务函数;

②所有外设都有一个总的中断处理函数;

③各种回调函数(weak)

④若要使用回调函数,必须重新声明

EXIO_1_hander 统一处理所有外部中断

EXTI 4_15_hander 统一的外部中断处理函数

Exti的外部中断代码:

中断向量表中提供的外部中断服务函数(这是中断的入口)

外部中断统一处理入口函数:

xxx_Rising_callback(weak)

xxx_fallng_callback(weak)

再根据要求重写相关的回调函数

exti0_1_handler(){

统一的处理函数()

}

9、DMA

全称:Direct Memory Access,即直接存储器访问。

DMA用来提供在外设和存储器之间或者存储器和存储器之间的高速数据传输。无须CPU的干预,通过DMA数据可以快速地移动。这就节省了CPU的资源来做其他操作。

1.DMA传输方式

DMA的作用就是实现数据的直接传输,而去掉了传统数据传输需要CPU寄存器参与的环节,主要涉及四种情况的数据传输,但本质上是一样的,都是从内存的某一区域传输到内存的另一区域(外设的数据寄存器本质上就是内存的一个存储单元)。

四种情况的数据传输如下:

外设到内存

内存到外设

内存到内存

外设到外设

DMA传输有专门的传输通道;

DMA传输参数:

首先需要①数据的源地址,②数据传输位置的目标地址;③传输数据多少的数据传输量,④进行多少次传输的传输模式;

只要剩余传输数据量不是0,而且DMA是启动状态,就会发生数据传输;

2.DMA的主要特征

每个通道都有专门的硬件DMA请求,每个通道都同样支持软件触发,这些功能通过软件来配置;

在同一个DMA模块上面,多个请求之间的优先权可以用软件编程来设置(四级:很高、高、中等和低)优先权设置相等的时候,由硬件进行决定(请求0优先于请求1);

独立数据源和目标数据区的传输宽度(字节、半字、全字),模拟打包和拆包的过程。源和目标地址必须按数据传输宽度对齐;

支持循环的缓冲器管理;

每个通道都有3个事件标志(DMA半传输、DMA传输完成和DMA传输出错),这3个事件标志逻辑或成为一个单独的中断请求;

存储器和存储器间的传输、外设和存储器、存储器和外设之间的传输;

闪存、SRAM、外设的SRAM、APB1、APB2和AHB外设均可作为访问的源和目标;

可编程的数据传输数目:最大为65535。

大容量的STM32芯片有2个DMA控制器;DMA1有7个通道,DMA有5个通道,每个通道都可以配置一些外设地址

3.DMA工作系统框图

上方的框图,我们可以看到STM32内核,存储器,外设及DMA的连接,这些硬件最终通过各种各样的线连接到总线矩阵中,硬件结构之间的数据转移都经过总线矩阵的协调,使各个外设和谐的使用总线来传输数据。

如果没有DMA,CPU传输数据还要以内核作为中转站,比如要将ADC采集的数据转移到到SRAM中,这个过程是这样的:

内核通过DCode经过总线矩阵协调,从获取AHB存储的外设ADC采集的数据,

然后内核再通过DCode经过总线矩阵协调把数据存放到内存SRAM中。

有DMA的话,

DMA传输时外设对DMA控制器发出请求。

DMA控制器收到请求,触发DMA工作。

DMA控制器从AHB外设获取ADC采集的数据,存储到DMA通道中

DMA控制器的DMA总线与总线矩阵协调,使用AHB把外设ADC采集的数据经由DMA通道存放到SRAM中,这个数据的传输过程中,完全不需要内核的参与,也就是不需要CPU的参与;

专业介绍:在发生一个事件后,外设向DMA控制器发送一个请求信号。DMA控制器根据通道的优先权处理请求。当DMA控制器开始访问发出请求的外设时,DMA控制器立即发送给它一个应答信号。当从DMA控制器得到应答信号时,外设立即释放它的请求。一旦外设释放了这个请求,DMA控制器同时撤销应答信号。DMA传输结束,如果有更多的请求时,外设可以启动下一个周期。

总之,每次DMA传送由3个操作组成:

从外设数据寄存器或者从当前外设/存储器地址寄存器指示的存储器地址取数据,第一次传输时的开始地址是DMA_CPARx或DMA_CMARx寄存器指定的外设基地址或存储器单元;

存数据到外设数据寄存器或者当前外设/存储器地址寄存器指示的存储器地址,第一次传输时的开始地址是DMA_CPARx或DMA_CMARx寄存器指定的外设基地址或存储器单元;

执行一次DMA_CNDTRx寄存器的递减操作,该寄存器包含未完成的操作数目。

4.DMA传输方式

1是正常模式;2是循环传输模式

其中还有一个仲裁器:作用是确定各个DMA传输的优先级

仲裁器根据通道的请求的优先级来启动外设/存储器的访问

5.DMA配置部分

分为DMA寄存器以及DMA库函数:

DMA寄存器:

DMA配置参数包括:通道地址、优先级、数据传输方向、存储器/外设数据宽度、存储器/外设地址是否增量、循环模式、数据传输量。

DMA库函数配置过程:

使能DMA时钟:RCC_AHBPeriphClockCmd();

初始化DMA通道:DMA_Init();

//设置通道;传输地址;传输方向;传输数据的数目;传输数据宽度;传输模式;优先级;是否开启存储器到存储器。

使能外设DMA;

以串口为例:使能串口DMA发送,串口DMA使能函数。调用函数:USART_DMACmd();

使能DMA通道传输;函数:DMA_Cmd();

查询DMA传输状态。函数:DMA_GetFlagStatus();

获取当前剩余数据量大小 函数: DMA_GetCurrDataCounter(DMA1_Channel4);

结合UART的运用: UART DMA传输

DMA就是一个搬运工,可以将数据从一个位置搬运到另一个位置。

以UART为例,如果要接收数据,会触发UART中断,然后CPU介入,在中断中通过CPU将UART输入寄存器的值读出来,存放到内存中;

而DMA方式,产生UART中断后,DMA直接参与,把UART输入寄存器的值搬运到内存中,CPU只需要在去检查内存的值就好了,这样提高了CPU的效率。

10、实验

1、外部中断实验

HAL_GPIO_EXTI_Falling_Callback()

HAL_GPIO_EXTI_Rising_Callback()

2、串口接受中断实验

HAL_UART_Receive_IT()

HAL_UART_RxCpltCallback()

HAL_UART_Transmit_IT()

HAL_UART_TxCpltCallback()

3、串口空闲中断实验

HAL_UARTEx_ReceiveToIdle_IT()

HAL_UARTEx_RxEventCallback()

  1. 串口空闲中断_DMA实验

HAL_UARTEx_ReceiveToIdle_DMA()

HAL_UARTEx_RxEventCallback()

“color:#4874CB;”> HAL_UARTEx_ReceiveToIdle_IT()

HAL_UARTEx_RxEventCallback()

[外链图片转存中…(img-E7QBIJMm-1726724546681)]

[外链图片转存中…(img-8ZY8M85c-1726724546681)]

[外链图片转存中…(img-UR1P6Zfe-1726724546682)]

  1. 串口空闲中断_DMA实验

HAL_UARTEx_ReceiveToIdle_DMA()

HAL_UARTEx_RxEventCallback()

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

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

相关文章

Nexus3的妙用

nexus 3使用场景 Nexus是一个全能仓库,通过部署nexus可以实现包含yum、apt、Maven、pypi、docker等的多种仓库。以下是nexus的适用场景: 当公共仓库无法访问或缓慢时,搭建nexus。比如国内docker无法访问,需要镜像加速。可以使用海外主机部署nexus,在nexus中创建docker(p…

uniapp微信小程序遮罩层u-popup禁止底层穿透

添加 touchmove.prevent&#xff0c;遮罩层底部的页面就不会滑动了微信开发者工具不生效&#xff0c;真机生效 <u-popup :show"showEwm" close"closeEwm" mode"center" touchmove.prevent><view class"ewmshow"></vie…

宝塔部署vue项目出现的各种问题

使用宝塔面板&#xff0c;网站页面&#xff0c;构建php静态网页 问题一&#xff1a;图片等静态资源无法加载 找到真正请求的url&#xff0c; 然后在项目目录下面创建对应的目录&#xff0c;将资源放入 问题二&#xff1a;刷新出现404 在这里任意位置添加 ## 添加上这个配…

力扣【118-杨辉三角】【数组-C语言】

题目&#xff1a;力扣-118 杨辉三角&#xff1a;&#xff08;算法思路&#xff09; 1. 每行第一个数和最后一个数都是1 2. 把杨辉三角左端对齐&#xff0c;从第三行开始&#xff0c;非首尾的元素值等于上一行同列的元素与该元素之前的元素之和&#xff0c;即 t [ j ] r e t …

软考高级:需求工程- 需求获取方式 AI解读

需求获取是项目管理和产品开发中的关键步骤&#xff0c;关系到项目的成功与否。你提到的几种需求获取方式涵盖了多个维度&#xff0c;以下我将逐一解析它们的用途与优势。 生活化例子 需求获取就像你要准备一场家庭聚会&#xff0c;需要先了解每个家庭成员的喜好。你可以通过…

【OceanBase 诊断调优】—— GC问题根因分析

GC 流程涉及到 RS 的状态切换和 LS 的资源安全回收&#xff0c;流程上较长。且 GC 线程每个租户仅有一个&#xff0c;某个日志流 GC Hang 死时会卡住所有其余日志流的 GC&#xff0c;进而造成更大的影响。 本文档会帮助大家快速定位到 GC 故障的模块&#xff0c;直达问题核心。…

SQL分组聚合子查询问题

场景 订单表 t_order 有如下数据&#xff1a; 字段分别为&#xff0c; 销售订单号、 订货数量 发货表 t_order_delivery 有如下数据&#xff1a; 字段分别为&#xff0c; 销售订单号、 发货数量 问题 问题1&#xff1a;查询部分发货的 销售订单号数据 &#xff1f; 分析…

数据集-目标检测系列-海洋鱼类检测数据集 fish>> DataBall

数据集-目标检测系列-海洋鱼类检测数据集 fish>> DataBall 数据集-目标检测系列-海洋鱼类检测数据集 fish 数据量&#xff1a;1W 数据项目地址&#xff1a; gitcode: https://gitcode.com/DataBall/DataBall-detections-100s/overview github: https://github.com/…

wpf中如何访问控件和生成使用事件?

实际上对于初次使用wpf的同学来说&#xff0c;尤其是有winform编程经验的童鞋来说&#xff0c;最需要解决的就是快速掌握访问控件的方法以及生成和使用事件。这样才能让页面具有最起码的交互性。下面我们来分别讲述。 文章原出处&#xff1a;https://blog.csdn.net/haigear/ar…

「数组」离散化 / Luogu B3694(C++)

目录 概述 思路 算法过程 复杂度 Code 概述 Luogu B3694&#xff1a; 给定一个长度为 n 的数列 aa。定义 rank(i) 表示数列 a 中比 ai 小的不同数字个数再加一。 对 1≤i≤n&#xff0c;现在请你求出所有的 rank(i)。 输出格式 对每组数据&#xff0c;输出一行 n 个整数&a…

智慧照明,安全度夏:揭秘如何前置防御暴雨中的路灯杆漏电隐患

随着夏季暴雨频发&#xff0c;多地近期发生的多起路人因路灯杆漏电触电身亡的悲剧&#xff0c;再次为公众安全敲响了警钟。从河南郑州到辽宁营口&#xff0c;一起起触目惊心的触电事故&#xff0c;不仅夺走了宝贵的生命&#xff0c;也引发了社会各界对暴雨天气下公共设施安全隐…

轴承介绍以及使用

轴承&#xff08;Bearing&#xff09;是在机械传动过程中起固定、旋转和减小载荷摩擦系数的部件。也可以说&#xff0c;当其它机件在轴上彼此产生相对运动时&#xff0c;用来降低运动力传递过程中的摩擦系数和保持转轴中心位置固定的机件。 轴承是当代机械设备中一种举足轻重的…

Go Mail设置指南:如何提升发送邮件效率?

Go Mail使用技巧与配置教程&#xff1f;如何用Go Mail实现发信&#xff1f; 随着工作负载的增加&#xff0c;如何高效地发送和管理邮件成为了许多职场人士面临的挑战。AokSend将为您提供一份详细的Go Mail设置指南&#xff0c;帮助您提升发送邮件的效率&#xff0c;让您的邮件…

数据库学习1

&#x1f31f;欢迎来到 我的博客 —— 探索技术的无限可能&#xff01; &#x1f31f;博客的简介&#xff08;文章目录&#xff09; 目录 登录 查看所有库 切换数据库 查看对应库所有的表 修改权限和密码 启动和停止服务器 创建数据库 查看数据库的表结构 创建表 在表…

Github Webhook触发Jenkins自动构建

1.功能说明 Github Webhook可以触发Jenkins自动构建&#xff0c;通过配置Github Webhook&#xff0c;每次代码变更之后&#xff08;例如push操作&#xff09;&#xff0c;Webhook会自动通知Jenkins服务器&#xff0c;Jenkins会自动执行预定义的构建任务&#xff08;如Jenkins …

揭秘“隐形杀手”:谐波对医院电网的隐形危害

谐波主要由非线性负载设备如医疗器械、节能照明、变频调速装置等产生。在医院的复杂配电网络中&#xff0c;这些谐波成分如同细小的波纹&#xff0c;不断叠加&#xff0c;最终扰乱了电能的纯净性&#xff0c;导致电能品质下降&#xff0c;电力供应的可靠性也随之降低。 医院里…

Linux ping c实现

linux下ping程序的c实现 #include <stdio.h> #include <stdlib.h> #include <sys/socket.h> #include <netinet/in.h> #include <stdint.h> #include <netdb.h> #include <arpa/inet.h> #include <unistd.h> #include <st…

服务设计原则介绍

在Java或任何软件开发中&#xff0c;设计服务时遵循一些核心原则是非常重要的&#xff0c;这些原则不仅有助于构建高质量、可维护的软件系统&#xff0c;还能提高系统的可扩展性和可重用性。以下是一些关键的服务设计原则&#xff1a; 单一职责原则&#xff08;SingleResponsib…

将python代码文件转成Cython 编译问题集

准备setup.py from distutils.core import setup from Cython.Build import cythonize import glob# 指定目标目录 python setup.py build -c mingw32 target_dir "src"# 使用glob模块匹配目录中的所有.pyx文件 pyx_files glob.glob(target_dir "/**/*.py&q…

路政通 | OPENAIGC开发者大赛高校组AI创新之星奖

在第二届拯救者杯OPENAIGC开发者大赛中&#xff0c;涌现出一批技术突出、创意卓越的作品。为了让这些优秀项目被更多人看到&#xff0c;我们特意开设了优秀作品报道专栏&#xff0c;旨在展示其独特之处和开发者的精彩故事。 无论您是技术专家还是爱好者&#xff0c;希望能带给…