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

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

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调试教程),单步执行或者当程序停留在打断点的地方,都会使程序暂停执行,此时如果在串口助手中发送数据,会导致程序收不到串口数据或者接收到的数据异常。

相关文章:

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

1)实验平台:正点原子MPSoC开发板 2)平台购买地址:https://detail.tmall.com/item.htm?id692450874670 3)全套实验源码手册视频下载地址: http://www.openedv.com/thread-340252-1-1.html 第八章UART串口中…...

【云原生】解读Kubernetes三层网络方案

在上一篇文章中,我以网桥类型的 Flannel 插件为例,为你讲解了 Kubernetes 里容器网络和 CNI 插件的主要工作原理。不过,除了这种模式之外,还有一种纯三层(Pure Layer 3)网络方案非常值得你注意。其中的典型…...

elasticsearch8.3.2搭建部署

Elasticsearch8.3.2搭建部署详细步骤 0.过往文章 ES-6文章: Elasticsearch6.6.0部署、原理和使用介绍: https://blog.csdn.net/wt334502157/article/details/119515730 ES-7文章: Elasticsearch7.6.1部署、原理和使用介绍: https://blog.csdn.net/wt…...

MySQL_InnoDB引擎

InnoDB引擎 逻辑存储结构 表空间(ibd文件),一个mysql实例可以对应多个表空间,用于存储记录、索引等数据。 段,分为数据段(Leaf node segment)、索引段(Non-leaf node segment)、回滚段(Rollba…...

json-server使用

文章目录json-server使用简介安装json-server启动json-server操作创建数据库查询数据增加数据删除数据修改数据putpatch配置静态资源静态资源首页资源json-server使用 简介 github地址 安装json-server npm install -g json-server启动json-server json-server --watch db…...

实现mint操作(参考pancake)

区块链发展越来越好,nft已经火了很久,今天写一下如何用js、web3js、调用合约,实现mint nft。简单的调用://引入一些依赖 (根据需要,有一些是其他功能的) import useActiveWeb3React from ./web3…...

Linux进程信号

目录 一、认识信号 1.1 生活角度的信号 1.2 技术角度的信号 1.3 信号的发送与记录 1.4 常见信号处理方式 二、产生信号 2.1 通过终端按键产生信号(核心转储) 2.2 通过系统函数向进程发送信号 2.2.1 kill()函数 2.2.2 raise()函数 2.2.3 abort()函数 2.3 因软件条件…...

1.7 Web学生管理系统

1.定义通讯协议基于前面介绍过的 FLask Web 网站 与 urlib 的访问网站的方法,设计一个综合应用实例。它是一个基于 Web 的学生记录管理程序。学生的记录包括 id(学号) 、name(姓名) 、grade(成绩),服务器的作用是建立与维护一个Sqllite 的学生数据库 stu…...

前端教学视频分享(视频内容与市场时刻保持紧密相连,火热更新中。。。)

⚠️获取公众号 本次要想大家推荐一下本人的公众号,在微信中搜索公众号 李帅豪在对话框中输入前端视频四个字即可立即获取所有视频,不收费无广告!!! 本公众号收集了近两年来前端最新最优秀的学习视频,涵盖…...

Docker-consul的容器服务更新与发现

一.Consul概述1.1 什么是服务注册与发现服务注册与发现是微服务架构中不可或缺的重要组件。起初服务都是单节点的,不保障高可用性,也不考虑服务的压力承载,服务之间调用单纯的通过接口访问。直到后来出现了多个节点的分布式架构,起…...

Java笔记-线程中断

线程的中断 1.应用场景: 假设从网络下载一个100M的文件,如果网速很慢,用户等得不耐烦,就可能在下载过程中点“取消”,这时,程序就需要中断下载线程的执行。 2.常用中断线程的方法: 1.使用标…...

js中的自调用表达式

自调用表达式 由函数表达式创建的函数可以自调用,称之为自调用表达式。 语法 由函数表达式创建函数: const myFn function () {let a 100console.log(a);return a } myFn() //调用后执行,输出100表达式后面紧跟 ( ) 则会自动调用: const myFn fu…...

Python操作的5个坏习惯,你中了几个呢?

很多文章都有介绍怎么写好 Python,我今天呢相反,说说写代码时的几个坏习惯。有的习惯会让 Bug 变得隐蔽难以追踪,当然,也有的并没有错误,只是个人觉得不够完美。 注意:示例代码在 Python 3.6 环境下编写 …...

C++并发与多线程编程(3)---线程间共享数据

主要内容:共享数据带来的问题使用互斥量保护数据数据保护的替代方案共享数据带来的问题当涉及到共享数据时,问题可能是因为共享数据修改所导致。如果共享数据是只读的,那么只读操作不会影响到数据,更不会涉及对数据的修改&#xf…...

洞察:2022年医疗行业数据安全回顾及2023年展望

过去的2022年,统筹安全与发展,在医疗信息化发展道路中,数据安全不可或缺。这一年,实施五年多的《网络安全法》迎来首次修改,《数据安全法》、《个人信息保护法》实施一周年,配套的《数据出境安全评估办法》…...

多传感器融合定位十五-多传感器时空标定(综述)

多传感器融合定位十五-多传感器时空标定1. 多传感器标定简介1.1 标定内容及方法1.2 讲解思路2. 内参标定2.1 雷达内参标定2.2 IMU内参标定2.3 编码器内参标定2.4 相机内参标定3. 外参标定3.1 雷达和相机外参标定3.2 多雷达外参标定3.3 手眼标定3.4 融合中标定3.5 总结4. 时间标…...

开发微服务电商项目演示(三)

一,nginx动静分离第1步:通过SwitchHosts新增二级域名:images.zmall.com第2步:将本次项目的易买网所有静态资源js/css/images复制到nginx中的html目录下第3步:在nginx的核心配置文件nginx.conf中新增二级域名images.zma…...

C/C++排序算法(二) —— 选择排序和堆排序

文章目录前言1. 直接选择排序🍑 基本思想🍑 具体步骤🍑 具体步骤🍑 动图演示🍑 代码实现🍑 代码升级🍑 特性总结2. 堆排序🍑 向下调整算法🍑 任意树调整为堆的思想&#…...

爬虫笔记之——selenium安装与使用(1)

爬虫笔记之——selenium安装与使用(1)一、安装环境1、下载Chrome浏览器驱动(1)查看Chrome版本(2)下载相匹配的Chrome驱动程序地址:https://chromedriver.storage.googleapis.com/index.html2、学…...

STC15单片机软串口的使用

STC15软串口的使用📖在没有使用定时器资源的情况下,根据波特率位传输时间,利用STC-ISP工具自动计算出位延时函数。 ✨在官方所提供的库函数中位传输时间函数,仅适用于使用波特率为:9600的串口数据传输: void BitTime(…...

Unity3D中Gfx.WaitForPresent优化方案

前言 在Unity中,Gfx.WaitForPresent占用CPU过高通常表示主线程在等待GPU完成渲染(即CPU被阻塞),这表明存在GPU瓶颈或垂直同步/帧率设置问题。以下是系统的优化方案: 对惹,这里有一个游戏开发交流小组&…...

Spring Boot面试题精选汇总

🤟致敬读者 🟩感谢阅读🟦笑口常开🟪生日快乐⬛早点睡觉 📘博主相关 🟧博主信息🟨博客首页🟫专栏推荐🟥活动信息 文章目录 Spring Boot面试题精选汇总⚙️ **一、核心概…...

相机Camera日志分析之三十一:高通Camx HAL十种流程基础分析关键字汇总(后续持续更新中)

【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了:有对最普通的场景进行各个日志注释讲解,但相机场景太多,日志差异也巨大。后面将展示各种场景下的日志。 通过notepad++打开场景下的日志,通过下列分类关键字搜索,即可清晰的分析不同场景的相机运行流程差异…...

CRMEB 框架中 PHP 上传扩展开发:涵盖本地上传及阿里云 OSS、腾讯云 COS、七牛云

目前已有本地上传、阿里云OSS上传、腾讯云COS上传、七牛云上传扩展 扩展入口文件 文件目录 crmeb\services\upload\Upload.php namespace crmeb\services\upload;use crmeb\basic\BaseManager; use think\facade\Config;/*** Class Upload* package crmeb\services\upload* …...

html-<abbr> 缩写或首字母缩略词

定义与作用 <abbr> 标签用于表示缩写或首字母缩略词&#xff0c;它可以帮助用户更好地理解缩写的含义&#xff0c;尤其是对于那些不熟悉该缩写的用户。 title 属性的内容提供了缩写的详细说明。当用户将鼠标悬停在缩写上时&#xff0c;会显示一个提示框。 示例&#x…...

Chromium 136 编译指南 Windows篇:depot_tools 配置与源码获取(二)

引言 工欲善其事&#xff0c;必先利其器。在完成了 Visual Studio 2022 和 Windows SDK 的安装后&#xff0c;我们即将接触到 Chromium 开发生态中最核心的工具——depot_tools。这个由 Google 精心打造的工具集&#xff0c;就像是连接开发者与 Chromium 庞大代码库的智能桥梁…...

论文阅读笔记——Muffin: Testing Deep Learning Libraries via Neural Architecture Fuzzing

Muffin 论文 现有方法 CRADLE 和 LEMON&#xff0c;依赖模型推理阶段输出进行差分测试&#xff0c;但在训练阶段是不可行的&#xff0c;因为训练阶段直到最后才有固定输出&#xff0c;中间过程是不断变化的。API 库覆盖低&#xff0c;因为各个 API 都是在各种具体场景下使用。…...

Python网页自动化Selenium中文文档

1. 安装 1.1. 安装 Selenium Python bindings 提供了一个简单的API&#xff0c;让你使用Selenium WebDriver来编写功能/校验测试。 通过Selenium Python的API&#xff0c;你可以非常直观的使用Selenium WebDriver的所有功能。 Selenium Python bindings 使用非常简洁方便的A…...

Java 与 MySQL 性能优化:MySQL 慢 SQL 诊断与分析方法详解

文章目录 一、开启慢查询日志&#xff0c;定位耗时SQL1.1 查看慢查询日志是否开启1.2 临时开启慢查询日志1.3 永久开启慢查询日志1.4 分析慢查询日志 二、使用EXPLAIN分析SQL执行计划2.1 EXPLAIN的基本使用2.2 EXPLAIN分析案例2.3 根据EXPLAIN结果优化SQL 三、使用SHOW PROFILE…...

字符串哈希+KMP

P10468 兔子与兔子 #include<bits/stdc.h> using namespace std; typedef unsigned long long ull; const int N 1000010; ull a[N], pw[N]; int n; ull gethash(int l, int r){return a[r] - a[l - 1] * pw[r - l 1]; } signed main(){ios::sync_with_stdio(false), …...