【正点原子FPGA连载】第八章UART串口中断实验 摘自【正点原子】DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南

news2024/12/27 4:00:52

1)实验平台:正点原子MPSoC开发板
2)平台购买地址:https://detail.tmall.com/item.htm?id=692450874670
3)全套实验源码+手册+视频下载地址: http://www.openedv.com/thread-340252-1-1.html

第八章UART串口中断实验

我们在使用PS的时候,通常会添加UART控制器,用于打印信息和调试代码。除此之外,PS在和外部设备通信时,也会经常使用串口进行通信。在“Hello World实验”章节中,我们在PS中已经添加了UART控制器,本章我们进一步向大家介绍UART控制器以及UART控制器利用中断进行通信的方法。
本章包括以下几个部分:
88.1简介
8.2实验任务
8.3硬件设计
8.4软件设计
8.5下载验证

8.1简介

UART控制器介绍
UART控制器是一个全双工异步收发控制器,MPSOC内部包含两个UART控制器,UART0和UART1。每一个UART控制器支持可编程的波特率发生器、64字节的接收FIFO和发送FIFO、产生中断、RXD和TXD信号的环回模式设置以及可配置的数据位长度、停止位和校验方式等。
UART控制器的配置以及状态的获取由控制(Control)和状态寄存器(Status Registers)完成。另外,UART控制器不仅可以连接至MIO,也可以映射到EMIO,从而使用PL的端口来实现串口通信的功能。当UART控制器连接到MIO时,只有Tx(发送)和Rx(接收)两个引脚;而当连接EMIO时,除Tx和Rx引脚外,可选的还有CTS、RTS、DSR、DCD、RI、DTR等引脚,这些引脚用于串口的流控制,即调制解调器的数据通讯中。
UART控制器采用独立的接收和发送数据路径,每个路径包含一个64字节的FIFO,控制器对发送和接收FIFO中的数据进行串并转换操作。FIFO的中断标志支持轮询处理或中断驱动处理两种方式。另外,控制器中还有一个模式开关,支持RXD和TXD信号的各种环回配置。UART控制器内部框图如下图所示:
在这里插入图片描述

图8.1.1 UART控制器内部框图
UART控制器的寄存器通过APB 从机接口和PS AXI总线互联,控制器的寄存器用于对UART控制器进行配置和获取状态。波特率发生器(Baud Rate Generator)为UART控制器的接收端和发送端提供位周期时钟;中断控制器(GIC)为串口的收发提供了中断服务的功能。
APB总线接口通过向TxFIFO寄存器写值,将数据加载到TxFIFO存储器中。当数据加载至TxFIFO后,TxFIFO的空标志变成无效的状态,直到最后一个数据从TxFIFO中移出,加载至传输移位寄存器,TxFIFO恢复空的标志位。同时TxFIFO使用TFULL(满中断状态)用于表示当前TxFIFO已经写满,并且会阻止数据继续写入。如果此时继续执行写操作,那么会触发溢出,数据不会加载到TxFIFO中。
RxFIFO存储器接收来自接收移位寄存器的数据,当接收完数据后,RxFIFO空标志信号同样变成无效的状态,直到所有的数据通过APB总线发送出去。RxFIFO的满标志状态用于表示RxFIFO已经写满,并且会阻止更多的数据写入。
图8.1.2中的模式切换(Mode Switch)控制RxD和TxD的信号连接方式,总共分为四种模式,分别为:正常模式(Normal Mode)、自动回音模式(Automatic Echo Mode)、本地环回模式(Local Loopback Mode)和远程环回模式(Remote Loopback Mode)。
模式切换的功能示意图如所示:
在这里插入图片描述

图8.1.2 模式切换功能示意图
从上图中可以清晰的看出UART不同模式下所实现的功能。正常模式是标准的UART操作模式;自动回音模式下,RxD连接至TxD,控制器可以接收数据,但是不能发送数据;本地环回模式没有连接RxD和TxD的引脚,用于本地程序的环回测试;远程环回模式下,RxD连接至TxD,但是并没有和控制器连接,因此控制器在此模式下无法发送数据和接收数据。当然在实际应用中,最常用的就是UART的正常模式。
在讲解完UART控制器之后,接下来我们向大家介绍程序中UART控制器的设计方法。如果我们只是用串口来打印信息的话,那么可以直接使用print()或者xil_printf()函数就可以了,无需在程序中对串口做配置。但是如果我们需要使用UART来完成某些特定功能的话,如串口接收中断,那么就要了解UART控制器初始化、UART中断初始化以及UART常用的API函数等相关内容了。
UART的启动顺序
UART的启动顺序如下:
1、复位控制器(在PS系统复位时);
2、配置IO引脚信号。RxD和TxD可以连接至MIO或者EMIO,只有EMIO可以使用串口的流控制。
3、配置UART参考时钟;
4、配置控制器功能(UART控制器初始化);
5、配置中断,通过中断来管理RxFIFO和TxFIFO;
6、配置串口流控制(可选);
7、管理发送和接收的数据,可以采用轮询或中断驱动处理两种方式。
配置控制器功能
控制器功能主要配置字符帧、波特率、FIFO触发器等级、Rx超时机制,并启用控制器。重置控制器后必须要配置所有这些参数。步骤如下:
1、配置UART数据帧格式。如:数据位长度、停止位、校验方式、IO模式等;
2、设置波特率;
3、设置RxFIFO触发器等级,可以选择启用或禁用该功能;
4、使能UART控制器;
5、配置接收器的超时机制,可以选择启用或禁用该功能。
发送数据
我们可以使用轮询或者中断两种方式控制TxFIFO和RxFIFO的数据流。这两个FIFO大小均为64个字节,因此当TxFIFO的空标志有效时,我们可以直接向其写入64个字节,无需检查TxFIFO的状态。实际上当发送器处于活跃状态时,可写入的字节数要超过64个字节,因为控制器同时也在移出数据,将其串行化转移到TxD信号上。
采用轮询方法发送数据的顺序如下:
1、检查TxFIFO是否为空;
2、向TxFIFO写入数据,可以写入64个字节;
3、向TxFIFO中写入更多数据。我们可以等待TxFIFO为空之后再写入64个字节,即执行第2步;也可以检测TxFIFO是否写满,即不停的读取TFUL标志和写单个字节的数据。
采用中断方法发送数据的顺序如下:
1、禁用TxFIFO空中断;
2、向TxFIFO写数据,可以写入64个字节的数据;
3、检测TxFIFO是否为满状态,不停的读取TFUL标志和写单个字节的数据;
4、重复步骤2和3,直到TxFIFO已满;
5、使能TxFIFO空中断;
6、等待,直到TxFIFO为空,然后从步骤1重新开始;
接收数据
采用轮询方法接收数据的顺序如下:
1、等待,直到RxFIFO中的数据数量达到触发等级;
2、从RxFIFO中读取数据;
3、重复步骤2直到FIFO空;
4、发生Rx超时中断时将其重置。
采用中断方法接收数据的顺序如下:
1、使能中断;
2、等待,直到RxFIFO中的数据数量达到触发等级或者发生超时;
3、从RxFIFO中读取数据;
4、重复步骤2和3,直到RxFIFO为空;
5、清除中断标志。

8.2实验任务

本章的实验任务是使用UART控制器,完成串口中断数据环回的功能。

8.3硬件设计

从实验任务我们可以画出如下的系统框图,DDR4中存放和运行程序、UART实现串口通信。
在这里插入图片描述

图 8.3.1 系统框图
由系统框图可知,本次实验的框图和《Hello World实验》的框图一样,同样只需要搭建嵌入式最小系统,最小系统只包括PS部分。这里添加的UART控制器不仅仅只是打印信息,同时为了实现串口数据环回的功能。
由于本次实验嵌入式系统的搭建和《Hello World实验》完全相同,这里不再详细讲解搭建的步骤,大家可以按照《Hello World实验》章节的步骤来创建一个新的嵌入式系统,或者将《Hello World实验》章节的工程另存为本次实验的工程,工程名为uart_intr_loop。
这里简单介绍下MPSOC PS的配置界面,如图 8.3.2所示。MPSOC开发板上的USB UART连接的引脚是MIO42和MIO43,因此在配置界面选择的是UART0 MIO42…MIO43。图中的Modem signals表示是否添加串口的流控制功能,即调制解调器,如果选中的话,会额外增加一些引脚,一般不勾选。需要注意的是,串口的流控制功能只能用于EMIO接口,MIO接口不支持此功能。
在这里插入图片描述

图 8.3.2 UART MIO配置界面
如果想要把UART控制器的引脚映射到EMIO接口,只需要将UART的引脚改为EMIO,如图 8.3.3所示。然后在Vivado工程中添加对应的管脚约束,生成Bitstream文件并导出Hardware即可。
在这里插入图片描述

图 8.3.3 UART控制器EMIO接口配置
本次实验使用的是板载的USB UART接口,连接的是MIO42和MIO43引脚,因此这里不做修改。
接下来,直接导出硬件,然后新建vitis文件夹,将导出的xsa文件拷贝到里面,最后打开Vitis软件,并将路径指向新建的vitis文件夹下。

8.4软件设计

在硬件设计的最后,我们打开了Vitis开发环境,如下图所示。
在这里插入图片描述

图 8.4.1 Vitis开发环境界面
下面我们在Vitis中创建应用工程,选择菜单File->New->Application Project, 新建一个应用工程。
在这里插入图片描述

图 8.4.2 新建应用工程
在弹出的图 8.4.3所示界面中,输入工程名“uart_intr_loop”,然后点击“Next >”按钮。
在这里插入图片描述

图 8.4.3 输入工程名
接下添加硬件平台文件,然后点击“Next”按钮,如下图所示:
在这里插入图片描述

图8.4.4 添加硬件平台文件
在弹出的界面中,使用默认设置,然后点击“Next”。然后在接下来的界面中选择空应用工程,如下图所示,这样应用工程就搭建好了。
在这里插入图片描述

图8.4.5 选择空应用工程
可以看到Vitis中创建了一个名为uart_intr_loop的应用工程。展开design_1_wrapper,找到platform.spr并双击,右面的界面中出现design_1_wrapper的标签页,然后找到板级支持包并点击,可以看到UART文档和导入示例,如图8.4.6和图8.4.7所示:
在这里插入图片描述

图8.4.6 板级支持包
在这里插入图片描述

图8.4.7 uart文档和示例
如果我们点击Import Examples,会弹出下图所示的导入示例界面,关于UART有5个示例,如下图所示:
在这里插入图片描述

图8.4.8 导入示例
感兴趣的朋友可以参考下官方提供的UART例程,其中xuartps_intr_example是串口中断的示例。
这里我们不导入官方的例程,而是新建一个源文件。在uart_intr_loop/src目录上右键,选择New->File一栏。在弹出的对话框中File name一栏我们输入文件名“main.c”,然后点击“Finish”。
新建源文件之后,在左侧uart/src目录下可以看到main.c文件,同时在主页面已经打开了该文件的文本编辑框。我们在新建的main.c文件中输入以下代码:

1   #include "xparameters.h"
2   #include "xuartps.h"
3   #include "xil_printf.h"
4   #include "xscugic.h"
5   #include "stdio.h"
6   
7   #define UART_DEVICE_ID     XPAR_XUARTPS_0_DEVICE_ID     //串口设备ID
8   #define INTC_DEVICE_ID     XPAR_SCUGIC_SINGLE_DEVICE_ID //中断ID
9   #define UART_INT_IRQ_ID    XPAR_XUARTPS_0_INTR          //串口中断ID
10  
11  XScuGic Intc;              //中断控制器驱动程序实例
12  XUartPs Uart_Ps;           //串口驱动程序实例
13  
14  //UART初始化函数
15  int uart_init(XUartPs* uart_ps)
16  {
17      int status;
18      XUartPs_Config *uart_cfg;
19  
20      uart_cfg = XUartPs_LookupConfig(UART_DEVICE_ID);
21      if (NULL == uart_cfg)
22          return XST_FAILURE;
23      status = XUartPs_CfgInitialize(uart_ps, uart_cfg, uart_cfg->BaseAddress);
24      if (status != XST_SUCCESS)
25          return XST_FAILURE;
26  
27      //UART设备自检
28      status = XUartPs_SelfTest(uart_ps);
29      if (status != XST_SUCCESS)
30          return XST_FAILURE;
31  
32      //设置工作模式:正常模式
33      XUartPs_SetOperMode(uart_ps, XUARTPS_OPER_MODE_NORMAL);
34      //设置波特率:115200
35      XUartPs_SetBaudRate(uart_ps,115200);
36      //设置RxFIFO的中断触发等级
37      XUartPs_SetFifoThreshold(uart_ps, 1);
38  
39      return XST_SUCCESS;
40  }
41  
42  //UART中断处理函数
43  void uart_intr_handler(void *call_back_ref)
44  {
45      XUartPs *uart_instance_ptr = (XUartPs *) call_back_ref;
46      u32 rec_data = 0 ;
47      u32 isr_status ;                           //中断状态标志
48  
49      //读取中断ID寄存器,判断触发的是哪种中断
50      isr_status = XUartPs_ReadReg(uart_instance_ptr->Config.BaseAddress,
51                     XUARTPS_IMR_OFFSET);
52      isr_status &= XUartPs_ReadReg(uart_instance_ptr->Config.BaseAddress,
53                     XUARTPS_ISR_OFFSET);
54  
55      //判断中断标志位RxFIFO是否触发
56      if (isr_status & (u32)XUARTPS_IXR_RXOVR){
57          rec_data = XUartPs_RecvByte(XPAR_PSU_UART_0_BASEADDR);
58          //清除中断标志
59          XUartPs_WriteReg(uart_instance_ptr->Config.BaseAddress,
60                  XUARTPS_ISR_OFFSET, XUARTPS_IXR_RXOVR) ;
61      }
62      XUartPs_SendByte(XPAR_PSU_UART_0_BASEADDR,rec_data);
63  }
64  
65  //串口中断初始化
66  int uart_intr_init(XScuGic *intc, XUartPs *uart_ps)
67  {
68      int status;
69      //初始化中断控制器
70      XScuGic_Config *intc_cfg;
71      intc_cfg = XScuGic_LookupConfig(INTC_DEVICE_ID);
72      if (NULL == intc_cfg)
73          return XST_FAILURE;
74      status = XScuGic_CfgInitialize(intc, intc_cfg,
75              intc_cfg->CpuBaseAddress);
76      if (status != XST_SUCCESS)
77          return XST_FAILURE;
78  
79      //设置并打开中断异常处理功能
80      Xil_ExceptionInit();
81      Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
82              (Xil_ExceptionHandler)XScuGic_InterruptHandler,
83              (void *)intc);
84      Xil_ExceptionEnable();
85  
86      //为中断设置中断处理函数
87      XScuGic_Connect(intc, UART_INT_IRQ_ID,
88              (Xil_ExceptionHandler) uart_intr_handler,(void *) uart_ps);
89      //设置UART的中断触发方式
90      XUartPs_SetInterruptMask(uart_ps, XUARTPS_IXR_RXOVR);
91      //使能GIC中的串口中断
92      XScuGic_Enable(intc, UART_INT_IRQ_ID);
93      return XST_SUCCESS;
94  }
95  
96  //main函数
97  int main(void)
98  {
99      int status;
100 
101     status = uart_init(&Uart_Ps);    //串口初始化
102     if (status == XST_FAILURE) {
103         xil_printf("Uart Initial Failed\r\n");
104         return XST_FAILURE;
105     }
106 
107     uart_intr_init(&Intc, &Uart_Ps); //串口中断初始化
108     while (1);
109     return status;
110 }

在代码的第11行和第12行,XScuGic和XUartPs为程序中定义的两个结构体。如果在Vitis软件中,按住Ctrl键不放,将鼠标移动到XScuGic或者XUartPs上,当鼠标变成手指状时,单击鼠标左键,会自动跳转到定义这两个结构体的地方。其中XScuGic包含了中断控制器相关的参数和数据,而XUartPs则包含了串口相关的参数和数据。
在程序的main函数中,首先对串口进行初始化(uart_init),如第101行所示。初始化完成后,函数返回初始化的结果,如果初始化失败,打印错误信息并返回;如果初始化成功,则开始执行串口中断初始化函数(uart_intr_init),如第107行所示。最后主程序会一直停留在while无限循环,如代码中第108行所示。
在代码的第15行至第40行完成了对UART的初始化。其中代码的第28行XUartPs_SelfTest函数实现了UART设备自检的功能,即使用UART本地环回的模式,并验证数据是否可以正确发送和接收。XUartPs_SetOperMode函数设置串口的工作模式,这里输入的参数XUARTPS_OPER_MODE_NORMAL为正常的工作模式。XUartPs_SetBaudRate函数用于设置串口的通信波特率,这里设置的波特率为115200,如果需要修改成其它波特率,可直接在此修改输入的参数即可。XUartPs_SetFifoThreshold函数用于设置RxFIFO的中断触发等级,即触发RxFIFO中断的数据个数,这里设置的值为1,即每收到一个值就触发中断。注意,中断触发等级最大值不超过63。
在代码的第65行至第94行完成了串口中断的初始化。程序首先对中断控制器进行初始化,随后设置并打开中断异常处理的功能。接下来为串口中断设置中断处理函数,通过XScuGic_Connect函数进行设置,这里设置的串口中断处理函数为uart_intr_handler。XUartPs_SetInterruptMask函数用于设置UART的中断触发方式,函数输入的参数为XUARTPS_IXR_RXOVR,表示达到RxFIFO的触发等级时,开始触发中断,当然也可以设置成RxFIFO为满时触发中断或者为空时触发中断等。最后,通过XScuGic_Enable函数来使能GIC中的串口中断。
在代码的第42行至第63行为UART中断处理函数,由于RxFIFO的触发等级设置为1,因此每次接收到数据都会进入此中断函数。程序中首先读取中断ID寄存器,判断触发的是哪种中断,再读取中断的状态。当判断中断标志位为RxFIFO触发中断时,通过XUartPs_RecvByte函数来读取接收到的数据,并清除对应的中断标志位。最后通过XUartPs_SendByte函数发送接收到的数据,实现串口环回的功能。
程序设计完成后,按快捷键Ctrl+S保存main.c文件,然后编译工程。编译完成后控制台(Console)中会出现提示信息“Build Finished”,同时在应用工程的Binaries目录下可以看到生成的elf文件。
软件设计部分到这里就完成了。

8.5下载验证

首先我们将下载器与开发板上的JTAG接口连接,下载器另外一端与电脑连接。然后使用USB连接线将USB_UART接口与电脑连接,用于串口通信。最后连接开发板的电源,给开发板上电。
打开Vitis Terminal终端,设置并连接串口。然后下载本次实验的程序。下载完成后,在Terminal中点击下图箭头处的命令输入图标,打开命令输入窗口,如下图所示:
在这里插入图片描述

图8.5.1 打开命令输入栏
然后输入待发送的数据,这里输入“Hello Zynq”,然后按下回车键,即可在接收数据窗口中接收到数据,如下图所示:
在这里插入图片描述

图8.5.2 发送数据操作界面
程序成功打印出了“Hello Zynq”字符串,说明本次实验在MPSOC开发板上面下载验证成功。
最后这里强调几点程序需要注意的地方。首先程序会对UART串口进行初始化,我们知道,当使用一些打印函数的时候(如:xil_printf()),实际上调用的还是UART相关的API函数,如果在初始化的过程中,使用打印函数,或者在打印的过程中对串口进行初始化,都会导致串口助手打印信息出错。其次当需要Debug在线调试的时候(定时器中断实验的下载验证部分有Debug调试教程),单步执行或者当程序停留在打断点的地方,都会使程序暂停执行,此时如果在串口助手中发送数据,会导致程序收不到串口数据或者接收到的数据异常。

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

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

相关文章

【SSD 代码精读】之 数据增强(Data Augmentation)

SSD 数据增强前言1、Compose2、SSDCropping3、Resize4、ColorJitter5、ToTensor6、RandomHorizontalFlip7、Normalization8、AssignGTtoDefaultBox前言 原论文 根据原论文,我们需要处理的有以下: data_transform {"train": transforms.Com…

vue2.x中使用vuex

Vuex是什么? Vuex是一个专门为Vue.js应用程序开发的状态管理模式。它采用集中式存储来管理应用程序中所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。Vuex也被集成到了Vue的官方调试工具vue-devtools中,提供了诸如零配置…

Java:使用Java功能确保应用程序安全的方法

与添加新功能一样重要的是,应用程序开发人员需要开始更加重视他们设计的应用程序的安全性。毕竟,更多的应用程序功能意味着更多的数据驻留在应用程序中。如果没有适当的安全控制,这些数据很容易被入侵者窃取。Java是目前世界上最安全、最流行…

如何去阅读源码,我总结了18条心法

在聊如何去阅读源码之前,先来简单说一下为什么要去阅读源码,大致可分为以下几点原因:最直接的原因,就是面试需要,面试喜欢问源码,读完源码才可以跟面试官battle提升自己的编程水平,学习编程思想…

不要慌,我们谈一谈如何用好 ChatGPT

别人贪婪时我恐惧,别人恐惧时我贪婪。 ——巴菲特 ChatGPT 火了,技术领域的社交媒体、自媒体几乎被 ChatGPT 刷屏,这些内容当中最让人惶恐不安的是我们是否会被 AI 取代之类的文章。 比如以下几个文章标题: 《ChatGPT可能马上…

Transformer结构解读

咱们还是照图讨论,transformer结构图如下,本文主要讨论Encoder部分:图一一、首先说一下Encoder的输入部分:在NLP领域,个人理解,这个inputs就是我们的句子分词之后的词语,比如“我,喜…

符号让人疯狂

符号让人疯狂 判断背了个LV符号的包就想可能有钱 趣讲大白话:人是通过符号区分生活的 聪明人想想:能超越或摆脱符号依赖吗? *********** 信息社会加速符号的传递和创造 我们已经被各种信息传递的符号淹没 信息符号的筛选成了人的主要工作 再…

GRB非隔离系列宽电压输入负高电压输出 电压控制型

特点● 效率高达70%以上● 1*2英寸标准封装● 单电压负输出● 价格低● 电压控制,输出电压随控制电压变化线性变化● 工作温度: -40℃~85℃● 阻燃封装,满足UL94-V0 要求● 温度特性好● 可直接焊在PCB 上应用GRB 系列模块电源是一种DC-DC升压变换器。该模块电源的输…

十、Linux文件 - fread函数讲解

目录 1.fread函数讲解 2.fread函数实战 1.fread函数讲解 从文件中读入数据到指定的地址中 函数原型: size_t fread(void*buff , size_t size, size_t count , FILE* stream) /* * description :对已打开的流进行数据读取 * param ‐ ptr :指向 数据块的…

好用的电脑备份软件推荐

现在几乎每个人都有一台电脑,上面存储着大量的数据,比如宝贵的照片、视频、工作文档等等。但电脑也随时存在许多威胁,比如病毒、Windows 更新错误、死机黑屏、驱动程序问题、系统崩溃等。为防止任何数据丢失,你需要一个专业的电脑…

Oracle数据库故障处理-单块读hang存储异常导致hang死,数据库大量的db file seq read等待(p1 p2无反映)

1 故障描述 2023年1月27日下午接到业务反馈数据库存在大量的锁表阻塞信息,并且业务的页面以及数据库的一些查询均处于阻塞状态,简单的查询sql也需要查询很长时间且未返回结果,数据库hang状态。 问题现象2 1 数据库进程无法杀除。 2 操作系统进程使用…

也许你应该学学 postman了

使用 最简单的方法就是直接在浏览器中复制 Copy as cURL ,然后把数据导入 postman,然后 send ,收工。 我们这里拿 知乎首页 举例 在对应的请求下复制 cURL 打开 postman , 点击左上角的 Import , 选择Paste Raw Tex…

如何使用逻辑分析仪,解析通信数据

如何使用逻辑分析仪,解析通信数据使用工具:逻辑分析仪(几十块买的裸板),软件是:PulseView一、在开发或者移植某一个模块时,你可能遇到这样的问题:二、逻辑分析仪的使用使用工具&…

二级C语言操作例题(四十)

一、程序填空题 在此程序中,函数fun的功能是:在形参s所指字符串中寻找与参数c相同的字符,并在其后插入一个与之相同的字符,若找不到相同的字符则不做任何处理。 例如,若s所指字符串”baacda”,中c的字符为…

JavaWeb-JavaScript API

目录DOM获取元素事务操作操作元素获取/修改元素属性获取/修改表单元素属性实现一个全选效果,主要是操作input的checked属性获取/修改元素样式点击放大字体夜间模式(关灯开灯)操作节点新增节点删除节点案例-猜数字案例-表白墙DOM DOM 全称为 Document Object Model.…

【Spring6源码・MVC】请求处理流程源码解析

上一篇《【Spring6源码・MVC】初始化registry,完成url和controller的映射关系》我们知道,在IOC容器加载的同时,初始化了registry这个HashMap,这个HashMap中存放了请求路径和对应的方法。当我们请求进来,会通过这个regi…

合并两个有序链表-力扣21-java双百方案

一、题目描述将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 示例 1:输入:l1 [1,2,4], l2 [1,3,4]输出:[1,1,2,3,4,4]示例 2:输入:l1 [], l2 []输出&#xff1…

C++中编译静态库与动态库

1.库的理解库就是写好的现有的,成熟的,可复用的代码。现实中每个程序都要依赖很多基础的底层库,不可能每个人的代码都从零开始,因此库的存在意义非同寻常。本质上来说库是一种可执行代码的二进制形式,是预编译代码的集…

【Vue3】element-plus中el-tree的递归处理赋值回显问题

目录一:先获取所有权限tree二:在获取所有该角色能有的权限tree三:递归处理勾选tree节点由于项目是从0-1开始构建的 rbac都需要重新构建对接 所以涉及到了权限管理和菜单管理 一级菜单包含多个二级菜单 若二级不全选,则一级显示 半…

scipy超几何函数

文章目录hyp2f1广义超几何函数其他超几何函数hyp2f1 当c不是0,−1,⋯0,-1,\cdots0,−1,⋯时&#xff0c;对于∣z∣<1|z|<1∣z∣<1&#xff0c;超几何函数可表示为 2F1(a;b;c;z)∑n0∞a(n)b(n)c(n)znn!_2F_1(a;b;c;z)\sum^\infty_{n0}\frac{a^{(n)}b^{(n)}}{c^{(n)}}\…