STM32 中断编程入门
目录
一、中断系统
1、中断的原理
2、中断类型
外部中断
定时器中断
DMA中断
3、中断处理函数
中断标志位清除
中断服务程序退出
二、实际应用
中断控制LED
任务要求
代码示例
中断控制串口通信
任务要求1
代码示例
任务要求2
代码示例
总结
学习目标:
学习stm32中断原理和开发编程方法,实现中断点亮LED灯;中断发送消息。
一、中断系统
STM32微控制器的中断系统是其功能强大和灵活性的重要组成部分。中断允许微控制器在执行主程序的同时,及时响应外部事件或内部条件的变化,从而实现高效的实时控制和数据处理。核心的中断控制器是NVIC(Nested Vectored Interrupt Controller),负责管理和分发所有的中断请求,并支持优先级分组,使开发人员能够为不同的中断源设置不同的优先级。STM32支持多种类型的中断,包括外部中断、定时器中断、串口中断和DMA中断。每种中断类型都有特定的配置方式和中断服务程序编写规范,以确保及时和有效地处理相应的事件。中断使能和中断优先级设置是配置中断系统的关键步骤,同时需要编写高效的中断服务程序,以便快速响应并尽快恢复主程序的执行。这些特性使得STM32在广泛的嵌入式应用中表现出色,为实时控制和数据处理提供了强大支持。
1、中断的原理
下面通过一个生活中的例子,帮助更好的去理解中断:
可以看到图中,由最开始的看书,转到最后的去卫生间,这个过程中,看书就受到了中断。我们将看书看作主程序,快递电话、肚子疼视为中断源,取快递和去卫生间视为中断服务程序 ,但是通过箭头可以看到,最后还是返回到了看书的 “主程序” ,所以,中断还存在返回,我们叫做中断返回。
在计算机中,执行程序过程中,当出现异常情况(断电等)或特殊请求(数据传输等)时,计算机暂停现行程序的运行,转向对这些异常情况或特殊请求进行处理,处理完毕后再返回到现行程序的中断处,继续执行原程序,这就是“中断”。
中断的主要处理流程为:中断请求——>中断响应——>中断服务——>中断返回
中断请求:中断请求是中断源向CPU发出中断请求信号,此时中断控制系统的中断请求寄存器被置位,向CPU请求中断
中断响应:CPU的中断系统判断中断源的中断请求是否符合中断响应条件,如果符合条件,则暂时中断当前程序并控制程序跳转到中断服务程序
中断服务:为处理中断而编写的程序称为中断服务程序,是由开发人员针对具体中断所要实现的功能进行设计和编写的,需要由开发人员来实现
中断返回:CPU退出中断服务程序,返回到中断请求响应之前被中止的位置继续执行主程序。这部分操作同样由硬件来实现,不需要开发人员进行处理
当发生了异常或中断,内核要想响应这些异常或中断,就需要知道这些异常或中断的服务程序的入口地址,再由入口地址找到相应的中断服务程序,由中断入口地址组成的表称作中断向量表(如下图)。
STM32中断系统的结构和工作原理如下:
中断请求来源:STM32的中断请求可以来自外部和内部两个方面。外部中断是由GPIO口引脚的电平或边沿信号变化触发,而内部中断通常是由硬件模块(如定时器、ADC)或软件产生的。
NVIC控制器:在STM32中,所有中断请求都由NVIC(Nested Vectored Interrupt Controller)控制器进行管理和调度。NVIC是一个基于向量表的中断控制器,通过优先级和向量表来实现对中断请求的管理。
中断分组:STM32将中断分为多个组别,每个组别包含一组中断请求。不同组别的中断请求可以具有不同的优先级,并且可以使用优先级抢占和屏蔽机制来确保系统的实时性和可靠性。STM32中断分组方式可选为0~4个前缀,用于设定中断优先级组和亚组。
中断服务程序:当中断事件发生后,CPU会暂停当前任务并跳转到相应的中断服务程序,处理该事件。中断服务程序通常包括以下几个步骤:保存CPU寄存器的值(包括堆栈指针、程序计数器等)处理中断请求(根据外部或内部中断的类型进行相应的处理,如清除标志位、读取数据等操作)执行用户自定义代码(根据实际需求执行用户自定义的代码段)恢复CPU寄存器的值(将保存在堆栈中的寄存器值恢复到其原始状态,以便CPU继续执行之前的任务)
中断优先级:STM32中,所有中断请求都具有唯一的编号(IRQn),并且可以根据编号和中断分组方式确定其优先级。优先级高的中断可以打断正在执行的低优先级中断,从而确保系统的实时性和可靠性。如果多个中断请求的优先级相同,则可以使用优先级抢占机制来确定响应顺序
2、中断类型
外部中断
EXTI(外部中断/事件控制器)支持19个外部中断/事件请求,每个中断/事件都有独立的触发和屏蔽设置,具有中断模式和事件模式两种设置模式。
其是一种通过配置GPIO引脚并使用EXTI线路实现的事件处理机制。在初始化GPIO引脚为输入并设置相应的中断触发方式后,可以通过编写中断服务程序来响应外部事件。例如,配置GPIO引脚为上升沿触发,当引脚接收到上升沿信号时,会触发预先定义的中断服务程序,以便快速处理事件。这种机制使得STM32能够高效地监听和响应外部触发事件,广泛应用于各种应用场景中。
- 输入线:EXTI有19个中断/事件输入线,这些输入线可以通过寄存器设置为任意一个GPIO,也可以是一些外设事件。
- 边沿检测电路:它会根据上升沿触发选择寄存器(EXTI_RTSR)和下降沿出发选择器(EXTI_FTSR)对应的设置来控制信号触发。
上升沿触发选择寄存器:要配置STM32微控制器的外部中断以在上升沿触发时响应,首先需通过GPIO的配置寄存器(如GPIOxCRH或GPIOxCRL)将相应引脚设置为输入模式。接着,在EXTIx_RTSR寄存器中设置相应的位来使能对应的外部中断线x的上升沿触发。最后,在NVIC中使能对应外部中断的中断处理。这些步骤确保了当引脚接收到上升沿信号时,系统能够及时调用预定义的中断服务程序来处理事件。
下降沿触发选择寄存器:要配置STM32微控制器的外部中断以在下降沿触发时响应,首先需通过GPIO的配置寄存器(如GPIOx_CRH或GPIOx_CRL)将相应引脚设置为输入模式。接着,在EXTIx_FTSR寄存器中设置相应的位来使能对应的外部中断线x的下降沿触发。最后,在NVIC中使能对应外部中断的中断处理。这些步骤确保了当引脚接收到下降沿信号时,系统能够及时调用预定义的中断服务程序来处理事件。
GPIO的中断是以组为单位的,同组的外部中断公用一条外部中断线。
例如:PA0、PB0、PC0、PD0、PE0、PF0、PG0这些为一组,如果使用PA0作为外部中断源,那么PB0、PC0、PD0、PE0、PF0、PG0就不能同时再作为外部中断使用了,在此情况下,只能使用类似于PB1、PC2这种末端序号不同的外部中断源。
GPIO引脚和外部中断线的映射关系图如下:
定时器中断
STM32微控制器的定时器是关键的外设,用于生成精确的时间延迟和周期性任务。通过选择合适的定时器类型(如通用定时器TIM或基本定时器TIM6/TIM7),配置工作模式和中断触发条件,可以实现定时器中断功能。配置过程包括设置时钟源、计数器初值和自动重装载寄存器,以及使能中断并编写相应的中断服务程序。这些步骤确保了定时器可以在达到预设计数值时产生中断请求,从而实现精确的时间控制和周期性任务执行,适用于实时操作系统、通信协议和其他时间敏感应用。
要配置STM32微控制器的定时器中断,首先选择适合需求的定时器(如TIM1、TIM2等),配置其工作模式、时钟源和计数周期。通过使能定时器中断控制寄存器中的更新中断位(UIE),允许定时器溢出时产生中断请求。
- 时钟和预分频设置:选择适当的时钟源和预分频器,以确定定时器的计数频率。
- 计数器设置:设置定时器的计数器初值和自动重装载寄存器(ARR),确定定时器的计数周期。
- 中断使能:通过使能定时器中断使能寄存器中的相应中断使能位(如UIE),允许定时器溢出时产生中断请求。
然后编写中断服务程序来处理定时器中断事件,包括清除中断标志、执行特定的定时任务并重新配置定时器。最后,确保在主程序中使能全局中断,以确保定时器中断能够正常触发和处理。这些步骤能够有效配置和利用STM32定时器中断功能,用于实现各种时间相关的应用和功能需求。
DMA中断
在STM32微控制器中,DMA(直接存储器访问)提供了高效的数据传输机制,允许外设和内存之间直接交换数据,无需CPU的干预,从而提升系统效率和响应速度。DMA传输完成时可触发中断通知CPU,通过使能DMA中断并配置中断服务程序,可以实现在数据传输完成时执行额外操作或启动后续任务,适用于实时数据处理、高速数据采集和图形显示等应用场景,有效优化系统性能和数据处理效率。
3、中断处理函数
中断标志位清除
void EXTI0_IRQHandler(void)
{if (EXTI_GetITStatus(EXTI_Line0) != RESET){EXTI_ClearITPendingBit(EXTI_Line0);// 接中断服务程序代码}
}
中断服务程序退出
void EXTI0_IRQHandler(void)
{if (EXTI_GetITStatus(EXTI_Line0) != RESET){EXTI_ClearITPendingBit(EXTI_Line0);// 接中断服务程序代码}NVIC_ClearPendingIRQ(EXTI0_IRQn);
二、实际应用
中断控制LED
任务要求
用stm32F103核心板的GPIOA端一管脚接一个LED,GPIOB端口一引脚接一个开关(用杜邦线模拟代替)。采用中断模式编程,当开关接高电平时,LED亮灯;接低电平时,LED灭灯。如果完成后,尝试在main函数while循环中加入一个串口每隔1s 发送一次字符的代码片段,观察按键中断对串口发送是否会带来干扰或延迟。
代码示例
LED.c
#include "stm32f10x.h" // Device header/*** 函 数:LED初始化* 参 数:无* 返 回 值:无*/
void LED_Init(void)
{/*开启时钟*/RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //开启GPIOA的时钟/*GPIO初始化*/GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_ResetBits(GPIOA, GPIO_Pin_0);
}
exti_key.c
#include "exti_key.h"
#include "misc.h"void EXTI_Key_Init(void)
{ GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1; // 使用 B 口的引脚 1GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;GPIO_Init(GPIOB, &GPIO_InitStructure);NVIC_InitTypeDef NVIC_InitStructure;NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn; // 使用与 GPIOB 引脚 1 相关的外部中断通道NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure); EXTI_InitTypeDef EXTI_InitStructure;EXTI_ClearITPendingBit(EXTI_Line1); GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource1); // 将 GPIOB 和引脚 1 配置为外部中断EXTI_InitStructure.EXTI_Line = EXTI_Line1;EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;EXTI_InitStructure.EXTI_LineCmd = ENABLE;EXTI_Init(&EXTI_InitStructure);
}
main.c
#include "stm32f10x.h" // Device header
#include "LED.h"
#include "exti_key.h"int main(void)
{LED_Init();GPIO_ResetBits(GPIOA,GPIO_Pin_0);EXTI_Key_Init();while (1){}
}
//void EXTI1_IRQHandler(void)
//{
// if(EXTI_GetITStatus(EXTI_Line1) != RESET)
// {
// GPIO_WriteBit(GPIOA,GPIO_Pin_0,(BitAction)((1-GPIO_ReadOutputDataBit(GPIOA,GPIO_Pin_0))));
// EXTI_ClearITPendingBit(EXTI_Line1);
// }
//}
//两种方法
uint8_t led = 1;void EXTI1_IRQHandler(void)
{if(EXTI_GetITStatus(EXTI_Line1) != RESET){led = ~led; //状态翻转//如果等于1,则PB1复位点亮,否则置1熄灭if(led == 1)GPIO_ResetBits(GPIOA,GPIO_Pin_0);elseGPIO_SetBits(GPIOA,GPIO_Pin_0); }EXTI_ClearITPendingBit(EXTI_Line1); //清除EXTI1的中断标志位
}
即可实现中断控制LED灯亮灭。
中断控制串口通信
任务要求1
当stm32接收到1个字符“s”时,停止持续发送“hello windows!”; 当接收到1个字符“t”时,持续发送“hello windows!”
代码示例
#include "stm32f10x.h"
#include "misc.h"
#include <string.h>volatile uint8_t send_enabled = 0; // 全局变量,控制发送行为void USART_Configuration(void) {USART_InitTypeDef USART_InitStructure;GPIO_InitTypeDef GPIO_InitStructure;// 打开 GPIO 与 USART 端口的时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_USART1, ENABLE);// 配置 USART1 Tx (PA.09) 为复用推挽输出GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);// 配置 USART1 Rx (PA.10) 为浮空输入GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;GPIO_Init(GPIOA, &GPIO_InitStructure);// 配置 USART 参数USART_InitStructure.USART_BaudRate = 9600;USART_InitStructure.USART_WordLength = USART_WordLength_8b;USART_InitStructure.USART_StopBits = USART_StopBits_1;USART_InitStructure.USART_Parity = USART_Parity_No;USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;USART_Init(USART1, &USART_InitStructure);// 使能 USARTUSART_Cmd(USART1, ENABLE);// 使能接收中断USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);// 配置 NVICNVIC_InitTypeDef NVIC_InitStructure;NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure);
}void USART1_IRQHandler(void) {if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) {char data = USART_ReceiveData(USART1);if(data == 's') { // 接收到 's' 停止发送send_enabled = 0;} else if (data == 't') { // 接收到 't' 开始发送send_enabled = 1;}USART_ClearITPendingBit(USART1, USART_IT_RXNE);}
}void Delay(__IO uint32_t nCount) {for(; nCount != 0; nCount--);
}int main(void) {SystemInit();USART_Configuration();char *str = "hello windows!\r\n";while(1) {if(send_enabled) {for(uint32_t i = 0; i < strlen(str); i++) {while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);USART_SendData(USART1, str[i]);}}Delay(5000000);}
}
任务要求2
当stm32接收到字符“stop stm32!”时,停止持续发送“hello windows!”; 当接收到字符“go stm32!”时,持续发送“hello windows!”(提示:要将接收到的连续字符保存到一个字符数组里,进行判别匹配。写一个接收字符串的函数。)
代码示例
NVIC.c
#include "stm32f10x.h" // Device headervoid NVIC_Configuration(void) {NVIC_InitTypeDef NVIC_InitStructure;NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure);
}
Serial.c
#include "stm32f10x.h" // Device header
#include <stdio.h>
#include <stdarg.h>/*** 函 数:串口初始化* 参 数:无* 返 回 值:无*/
void Serial_Init(void)
{/*开启时钟*/USART_InitTypeDef USART_InitStructure;GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_USART1, ENABLE);// USART Tx (PA.09) 配置为复用推挽输出GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);// USART Rx (PA.10) 配置为浮空输入GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;GPIO_Init(GPIOA, &GPIO_InitStructure);USART_InitStructure.USART_BaudRate = 9600;USART_InitStructure.USART_WordLength = USART_WordLength_8b;USART_InitStructure.USART_StopBits = USART_StopBits_1;USART_InitStructure.USART_Parity = USART_Parity_No;USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;USART_Init(USART1, &USART_InitStructure);USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); // 开启接收中断USART_Cmd(USART1, ENABLE);
}
main.c
#include "stm32f10x.h"
#include "misc.h"
#include <string.h>
#include "Delay.h"
#include "Serial.h"
#include "NVIC.h"#define BUFFER_SIZE 100
volatile char buffer[BUFFER_SIZE];
volatile int buffer_index = 0;
volatile int send_enabled = 0;void USART1_IRQHandler(void) {if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) {char data = (char)USART_ReceiveData(USART1);if (buffer_index < BUFFER_SIZE - 1) {buffer[buffer_index++] = data;buffer[buffer_index] = '\0'; // 保持字符串结尾char* temp_buffer = (char*)buffer; // 创建一个非 volatile 指针if (strstr(temp_buffer, "stop stm32!") != NULL) {send_enabled = 0;buffer_index = 0; // 清空缓冲区} else if (strstr(temp_buffer, "go stm32!") != NULL) {send_enabled = 1;buffer_index = 0; // 清空缓冲区}}}
}int main(void) {SystemInit();Serial_Init();NVIC_Configuration();char *str = "hello windows!\r\n";while (1) {if (send_enabled) {for (uint32_t i = 0; i < strlen(str); i++) {while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);USART_SendData(USART1, str[i]);}}Delay_ms(500);}
}
最后使用串口助手即可(野火以及其他串口助手均可)。
总结
本章内容理解上不存在太多有问题的地方,对于中断的理解更像是正51单片机的另一个翻版,对于实践过程中的问题,远远多于理论理解,关于软件的操作,环境的配置,串口的调试运行,都是之前学习的逐渐累积,在学习上,没有一蹴而就,要脚踏实地,做好每一步,才可以更好更快,更高效率完成任务。
相关文章:

STM32 中断编程入门
目录 一、中断系统 1、中断的原理 2、中断类型 外部中断 定时器中断 DMA中断 3、中断处理函数 中断标志位清除 中断服务程序退出 二、实际应用 中断控制LED 任务要求 代码示例 中断控制串口通信 任务要求1 代码示例 任务要求2 代码示例 总结 学习目标&…...

使用maven搭建一个SpingBoot项目
1.首先创建一个maven项目 注意选择合适的jdk版本 2.添加依赖 2.在pom.xml中至少添加依赖 spring-boot-starter-web 依赖,目的是引入Tomcat,以及SpringMVC等,使项目具有web功能。 <!-- 引入 包含tomcat,SpringMVC,…...
使用 HTTPS 已成为网站的标配了
网站使用HTTPS的原因 背景:十年前,HTTPS并不普遍,但随着网络安全意识的提高,现在已成为网站标配。 网站升级到HTTPS的动机 安全问题:HTTP缺乏安全机制,易被窃取和篡改数据。例如,电信运营商劫…...
前后端分离Nginx
背景 旧的部署方式是将前端代码打包进后端包的resource server {listen 80;listen 443 ssl;server_name xxx.test.com;location / {proxy_pass http://xxx.test.com;} }后端:https:// xxx.test.com/simcard/querySimcard 前端:https:// x…...

【简单讲解下Tauri】
🌈个人主页: 程序员不想敲代码啊 🏆CSDN优质创作者,CSDN实力新星,CSDN博客专家 👍点赞⭐评论⭐收藏 🤝希望本文对您有所裨益,如有不足之处,欢迎在评论区提出指正,让我们共…...
mac上挂载linux目录
在 macOS 上挂载 CentOS 目录步骤: 在挂载前确保 macOS 和 CentOS 在同一个局域网内,并且可以相互访问。如果有网络配置问题,可能会导致挂载失败或连接被拒绝的错误。 要在 macOS 上将 CentOS 的 /disk2/go 目录通过 NFS 挂载到 /Users/zon…...

Linux系统的服务——以Centos7为例
一、Linux系统的服务简介 服务是向外部提供对应功能的进程,其运行在系统后台,能够7*24小时持续不断的提供外界随时发来的服务请求,且服务进程常驻在内存中,具有固定的端口号,通过端口号就能找到服务内容。 提供服务的一…...

Numpy矩阵运算
版权声明 本文原创作者:谷哥的小弟作者博客地址:http://blog.csdn.net/lfdfhl Numpy概述 Numpy是Python的一个开源数值计算扩展库,主要用于存储和处理大型多维数组和矩阵,并且提供了大量的数学函数来操作这些数组。Numpy是Pytho…...

Spring容器Bean之XML配置方式
一、首先看applicationContext.xml里的配置项bean 我们采用xml配置文件的方式对bean进行声明和管理,每一个bean标签都代表着需要被创建的对象并通过property标签可以为该类注入其他依赖对象,通过这种方式Spring容器就可以成功知道我们需要创建那些bean实…...

【Rust入门】生成随机数
文章目录 前言随机数库rand添加rand库到我们的工程生成一个随机数示例代码 总结 前言 在编程中,生成随机数是一种常见的需求,无论是用于数据分析、游戏开发还是模拟实验。Rust提供了强大的库来帮助我们生成随机数。在这篇文章中,我们将通过一…...

普通Java工程如何在代码中引用docker-compose.yml中的environment值
文章目录 一、概述二、常规做法1. 数据库配置分离2. 代码引用配置3. 编写启动类4. 支持打包成可执行包5. 支持可执行包打包成docker镜像6. docker运行 三、存在问题分析四、改进措施1. 包含environment 变量的编排文件2. 修改读取配置文件方式3. 为什么可以这样做 五、运行效果…...

微观特征轮廓尺寸测量:光学3D轮廓仪、共焦显微镜与台阶仪的应用
随着科技进步,显微测量仪器以满足日益增长的微观尺寸测量需求而不断发展进步。多种高精度测量仪器被用于微观尺寸的测量,其中包括光学3D表面轮廓仪(白光干涉仪)、共聚焦显微镜和台阶仪。有效评估材料表面的微观结构和形貌…...
Rust开发环境搭建
Rust开发环境搭建 环境 rust: 1.79.0(2024-06-13)1. Rustup下载器在线安装 windows: https://static.rust-lang.org/rustup/dist/x86_64-pc-windows-msvc/rustup-init.exe unix: curl --proto https --tlsv1.2 -sSf https://sh.rustup.rs | sh2. R…...

图文识别0难度上手~基于飞浆对pdf简易ocr并转txt
前言 本篇pdf适用windows对视觉识别0基础的的纯小白用户。大佬请绕道~~ 注意: 本项目pdf的ocr对于表格、画图文字,水印等干扰没做任何处理,因此希望各位使用该功能的pdf尽量不要含有这些干扰项,以免影响翻译效果。 流程 1.构建…...
FFmpeg常用命令手册
官方文档:ffmpeg Documentation 常规选项 -i input_url 输入文件或者输入流的路径 Main 选项 -f fmt (input/output) 强制指定输入或输出文件的格式, 常见的格式名称包括flv,mp4、hls、mpegts、avi、mov -c[:stream_specifier] codec (i…...

CTF入门知识点
CTF知识点 md5函数 <?php$a 123;echo md5($a,true); ?> 括号中true显示输出二进制 替换成false显示输出十六进制绕过 ffifdyop 这个字符串被 md5 哈希了之后会变成 276f722736c95d99e921722cf9ed621c,这个字符串前几位刚好是 or 6 而 Mysql 刚好又会把 …...
Leetcode 完美数
1.题目要求: 对于一个 正整数,如果它和除了它自身以外的所有 正因子 之和相等,我们称它为 「完美数」。给定一个 整数 n, 如果是完美数,返回 true;否则返回 false。示例 1:输入:num 28 输出&a…...
springboot中的定时任务编写
第1部分:引言 1.1 定时任务的重要性 在现代软件开发中,定时任务是应用程序自动化和运维效率的关键组成部分。无论是数据备份、系统健康检查、定期报告生成,还是用户活动触发的自动化流程,定时任务都扮演着不可或缺的角色。它们确…...

第100+14步 ChatGPT学习:R实现随机森林分类
基于R 4.2.2版本演示 一、写在前面 有不少大佬问做机器学习分类能不能用R语言,不想学Python咯。 答曰:可!用GPT或者Kimi转一下就得了呗。 加上最近也没啥内容写了,就帮各位搬运一下吧。 二、R代码实现随机森林分类 ÿ…...
C#面 :ASP.Net Core中有哪些异常处理的方案?
在 ASP.NET Core中,有多种异常处理方案可供选择。以下是其中几种常见的异常处理方案: 中间件异常处理: ASP.NET Core提供了一个中间件来处理全局异常。通过在Startup类的Configure方法中添加UseExceptionHandler中间件,可以捕获…...
SkyWalking 10.2.0 SWCK 配置过程
SkyWalking 10.2.0 & SWCK 配置过程 skywalking oap-server & ui 使用Docker安装在K8S集群以外,K8S集群中的微服务使用initContainer按命名空间将skywalking-java-agent注入到业务容器中。 SWCK有整套的解决方案,全安装在K8S群集中。 具体可参…...

3.3.1_1 检错编码(奇偶校验码)
从这节课开始,我们会探讨数据链路层的差错控制功能,差错控制功能的主要目标是要发现并且解决一个帧内部的位错误,我们需要使用特殊的编码技术去发现帧内部的位错误,当我们发现位错误之后,通常来说有两种解决方案。第一…...
MVC 数据库
MVC 数据库 引言 在软件开发领域,Model-View-Controller(MVC)是一种流行的软件架构模式,它将应用程序分为三个核心组件:模型(Model)、视图(View)和控制器(Controller)。这种模式有助于提高代码的可维护性和可扩展性。本文将深入探讨MVC架构与数据库之间的关系,以…...

DBAPI如何优雅的获取单条数据
API如何优雅的获取单条数据 案例一 对于查询类API,查询的是单条数据,比如根据主键ID查询用户信息,sql如下: select id, name, age from user where id #{id}API默认返回的数据格式是多条的,如下: {&qu…...
数据库分批入库
今天在工作中,遇到一个问题,就是分批查询的时候,由于批次过大导致出现了一些问题,一下是问题描述和解决方案: 示例: // 假设已有数据列表 dataList 和 PreparedStatement pstmt int batchSize 1000; // …...
Typeerror: cannot read properties of undefined (reading ‘XXX‘)
最近需要在离线机器上运行软件,所以得把软件用docker打包起来,大部分功能都没问题,出了一个奇怪的事情。同样的代码,在本机上用vscode可以运行起来,但是打包之后在docker里出现了问题。使用的是dialog组件,…...

排序算法总结(C++)
目录 一、稳定性二、排序算法选择、冒泡、插入排序归并排序随机快速排序堆排序基数排序计数排序 三、总结 一、稳定性 排序算法的稳定性是指:同样大小的样本 **(同样大小的数据)**在排序之后不会改变原始的相对次序。 稳定性对基础类型对象…...
SQL慢可能是触发了ring buffer
简介 最近在进行 postgresql 性能排查的时候,发现 PG 在某一个时间并行执行的 SQL 变得特别慢。最后通过监控监观察到并行发起得时间 buffers_alloc 就急速上升,且低水位伴随在整个慢 SQL,一直是 buferIO 的等待事件,此时也没有其他会话的争抢。SQL 虽然不是高效 SQL ,但…...

AirSim/Cosys-AirSim 游戏开发(四)外部固定位置监控相机
这个博客介绍了如何通过 settings.json 文件添加一个无人机外的 固定位置监控相机,因为在使用过程中发现 Airsim 对外部监控相机的描述模糊,而 Cosys-Airsim 在官方文档中没有提供外部监控相机设置,最后在源码示例中找到了,所以感…...
NPOI操作EXCEL文件 ——CAD C# 二次开发
缺点:dll.版本容易加载错误。CAD加载插件时,没有加载所有类库。插件运行过程中用到某个类库,会从CAD的安装目录找,找不到就报错了。 【方案2】让CAD在加载过程中把类库加载到内存 【方案3】是发现缺少了哪个库,就用插件程序加载进…...