中断-NVIC与EXTI外设详解(超全面)

news2024/10/5 16:22:36

✅作者简介:嵌入式入坑者,与大家一起加油,希望文章能够帮助各位!!!!
📃个人主页:@rivencode的个人主页
🔥系列专栏:玩转STM32
💬推荐一款模拟面试、刷题神器,从基础到大厂面试题👉点击跳转刷题网站进行注册学习

目录

  • 一.NVIC-嵌套向量中断控制器
    • 1.中断向量表
    • 2.NVIC内核外设寄存器
    • 3.中断编程
  • 二.EXTI—外部中断/事件控制器
    • 1.外部中断/事件线路映像
    • 2.EXTI功能框图
    • 3.选择中断线与EXTI 初始化结构体详解
  • 三.外部中断控制实验
    • 实验原理
    • 编程要点
    • 实验效果
  • 四.总结

一.NVIC-嵌套向量中断控制器

NVIC :嵌套向量中断控制器,属于内核外设,管理着包括内核和片上所有外设的中断相关的功能。

这里解释一下片上外设与内核外设他们都在芯片里面,但内核外设是在内核CPU里面,片上外设就是内核之外咯。
在这里插入图片描述
在这里插入图片描述

NVIC 是嵌套向量中断控制器,控制着整个芯片中断相关的功能,它跟内核紧密耦合,是内核里面的一个外设。但是各个芯片厂商在设计芯片的时候会对 Cortex-M3 内核里面的 NVIC 进行裁剪,把不需要的部分去掉,所以STM32 的 NVIC 是 Cortex-M3 的 NVIC 的一个子集。

几个关于内核外设重要的库文件:
Cortex-M3 内核的外设也比较多,但STM32并没有用到这么多内核外设对其进行了裁剪,STM32重要的内核外设用到的库函数放在了misc.c文件之中所以core_cm3.c文件用的较少。

core_cm3.c:内核外设的驱动固件库
core_cm3.h:实现了内核(CPU)里面的外设的寄存器映射,还有很多关于内核外设的库函数。
misc.h:NVIC_InitTypeDef结构体,以及库函数的参数和声明
misc.c:NVIC(嵌套向量中断控制器)、SysTick(系统滴答定时器)相关函数

1.中断向量表

CM3 内核支持 256 个中断,其中包含了 16 个内核中断和 240 个外部中断,并且具有 256级的可编程中断设置。但 STM32 并没有使用 CM3 内核的全部东西,而是只用了它的一部分。STM32 有 84 个中断,包括 16 个内核中断和 68 个可屏蔽中断,具有 16 级可编程的中断优先级。而我们常用的就是这 68 个可屏蔽中断,但是 STM32 的 68 个可屏蔽中断,在 STM32F103 系列上面,又只有 60 个(在 107 系列才有 68 个)。

而我要讲的是103系列其中系统异常有 8 个(如果把 Reset 和 HardFault 也算上的话就是 10 个),外部中断有 60个。除了个别中断的优先级被定死外,其它中断的优先级都是可编程的。

下面灰色的就是系统异常(中断),中断就是异常,异常就是中断这里就不区分了,表中的优先级是硬件编号,数字越小优先级越高这里复位中断的编号最小,所以一按板子上的复位键会立马执行复位程序。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.NVIC内核外设寄存器

NVIC管理着中断向量表中的60个中断
在固件库中,NVIC 的结构体定义给每个寄存器都预留了很多位,恐怕为的是日后扩展功能。不过 STM32F103 可用不了这么多,只是用了部分而已

在这里插入图片描述
具体使用了各个寄存器使用了多少个请看图

在这里插入图片描述
在这里插入图片描述

  • ISER[8]:ISER 全称是:Interrupt Set-Enable Registers:这是一个中断使能寄存器组(有8个这样的寄存器)。上面STM32F103 的可屏蔽中断只有 60 个,一个寄存器有32位一位可以表示一个中断两个寄存器总共可以表示 64 个中断。而 STM32F103 只用了其中的前 60 位。所以对我们来说,有用的就是两个(ISER[0]和 ISER[1]),ISER[0]的 bit0-bit31 分别对应中断 0-31。ISER[1]的 bit0-27 对应中中断32~59;这样总共 60 个中断就分别对应上了。你要使能某个中断,必须设置相应的 ISER 位为 1,使该中断被使能(这里仅仅是使能,还要配合中断分组、屏蔽、IO 口映射等设置才算是一个完整的中断设置)。

在这里插入图片描述

  • ICER[8]:全称是:Interrupt Clear-Enable Registers:是一个中断除能寄存器组。该寄存器组与 ISER 的作用恰好相反,是用来清除某个中断的使能的。向寄存器写1清除写0无效。

  • ISPR[8]:全称是:Interrupt Set-Pending Registers:是一个中断挂起控制寄存器组。每个位对应的中断和 ISER 是一样的。通过置 1当置位中断挂起寄存器的时候,相应的中断将会被挂起,此时这个中断将不会立即执行,而是等待可执行的时候再执行;比如高低级别的中断同时产生,就先挂起低级别的中断,等高级别的中断执行完毕,解除并执行低级中断这个过程一般是自发进行

  • ICPR[8]:全称是:Interrupt Clear-Pending Registers:是一个中断解挂控制寄存器组。其作用与 ISPR 相反,对应位也和 ISER 是一样的。通过设置 1,可以将挂起的中断解除挂起。写 0 无效。

  • IABR[8]:全称是:Interrupt Active Bit Registers:是一个中断激活标志位寄存器组。对应位所代表的中断和 ISER 一样,如果为 1,则表示该位所对应的中断正在被执行。这是一个只读寄存器,通过它可以知道当前在执行的中断是哪一个。在中断执行完了由硬件自动清零。

  • IP[240]:全称是:Interrupt Priority Registers:是一个中断优先级控制的寄存器组。这个寄存器组相当重要!STM32 的中断分组与这个寄存器组密切相关。240 个 8bit 的寄存器组成,每个可屏蔽中断占用 8bit,这样总共可以表示 240 个可屏蔽中断。而 STM32 只用到了其中的前 60 个。IP[59]-IP[0]分别对应中断 59~0也就是说:一个中断需要一个IP寄存器来配置优先级。 比如说中断硬件编号为20的中断配置的寄存器就为IP[20]

在这里插入图片描述
看图所知这里只分配了80个IP寄存器但对我们配置60中断绰绰有余,这里建议一下一定要去看看Cortex-M3编程手册有关NIVC的寄存器,这样心底有个底。

IP寄存器 宽度为 8bit,原则上每个外部中断可配置的优先级为 0~255(十进制),数值越小,优先级越高。但是绝大多数 CM3 芯片都会精简设计,以致实际上支持的优先级数减少,在F103 中,只使用了高 4bit,如下所示:

在这里插入图片描述
用于表达优先级的这 4bit,又被分组成抢占优先级和响应优先级

STM32 将中断分为 5 个组,组 0-4。该分组的设置是由 SCB->AIRCR 寄存器的 bit10~8 来定义的。
在这里插入图片描述
比如组2来说:2位配置抢占式优先级(00 01 10 11)换成十进制不就是0~3嘛,2位配置响应式优先级0 ~3,数字越小优先级越高其他分组以此类推。
注意:组1抢占式优先级0位,那就没有抢占式优先级,

  • 配置分组

在系统代码执行的过程只进行一次中断优先级分组,设置分组之后一般不会进行变动,不然中断执行会混乱,如:假设你分成组2,抢占式优先级有2位,后面改成组3的话,就会变成3位抢占式优先级,则之前的一位响应优先级变成了抢占式优先级,则之前配置的抢占式和响应优先级的值就不确定了乱套了。

在这里插入图片描述

  • 抢占式优先级与响应式优先级的区别
    在这里插入图片描述
    加深理解:
    1.抢占式优先级高的可以打断正在执行的(抢占式优先级低)中断(挂起),转而执行抢占式优先级高的中断执行完毕后在返回原来(抢占式优先级低)中断继续执行,这就是所谓的中断嵌套。而响应优先级并不能嵌套

2.若抢占式优先级与响应式优先级都相同则硬件编号(在中断向量表的排序顺序)小的先执行

3.中断编程

一般中断使能一般有两个门,外设使能相应的中断然后送入NVIC再使能,外设使能中断是小门,NVIC使能中断是大门,只有都使能才能响应中断。
请添加图片描述

1.使能外设某个中断,这个具体由每个外设的相关中断使能位控制。

2.配置中断优先级分组,然后初始化 NVIC_InitTypeDef 结构体,设置抢占优先级和子优先级,使能中断请求。NVIC_InitTypeDef 结构体在固件库头文件 misc.h 中定义。

配置中断优先级分组
在这里插入图片描述
初始化 NVIC_InitTypeDef 结构体

在这里插入图片描述

  • NVIC_IROChannel:用来设置中断源,不同的中断中断源不一样,且不可写错,即使写错了程序也不会报错,只会导致不响应中断。具体的成员配置可参考stm32f10x.h 头文件里面的 IRQn_Type 结构体定义,这个结构体包含了所有的中断源。

在这里插入图片描述

  • NVIC_IRQChannelPreemptionPriority:抢占优先级,具体的值要根据优先级分组来确定。

  • NVIC_IRQChannelSubPriority:子优先级(响应优先级),具体的值要根据优先级分组来确定 。

  • NVIC_IRQChannelCmd:中断使能(ENABLE)或者(DISABLE)。操作的是 NVIC_ISER 和 NVIC_ICER 这两个寄存器。

配置好 NVIC_InitTypeDef 结构体然后就调用NVIC_Init()函数,由函数将参数写入寄存器

现在来具体来分析一下这个函数加深我们对NVIC寄存器的理解

void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct)
{
  uint32_t tmppriority = 0x00, tmppre = 0x00, tmpsub = 0x0F;
  
  /* Check the parameters */
  assert_param(IS_FUNCTIONAL_STATE(NVIC_InitStruct->NVIC_IRQChannelCmd));
  assert_param(IS_NVIC_PREEMPTION_PRIORITY(NVIC_InitStruct->NVIC_IRQChannelPreemptionPriority));  
  assert_param(IS_NVIC_SUB_PRIORITY(NVIC_InitStruct->NVIC_IRQChannelSubPriority));
    
  if (NVIC_InitStruct->NVIC_IRQChannelCmd != DISABLE)
  {
    /* Compute the Corresponding IRQ Priority --------------------------------*/    
    tmppriority = (0x700 - ((SCB->AIRCR) & (uint32_t)0x700))>> 0x08;
    tmppre = (0x4 - tmppriority);
    tmpsub = tmpsub >> tmppriority;

    tmppriority = (uint32_t)NVIC_InitStruct->NVIC_IRQChannelPreemptionPriority << tmppre;
    tmppriority |=  NVIC_InitStruct->NVIC_IRQChannelSubPriority & tmpsub;
    tmppriority = tmppriority << 0x04;
        
    NVIC->IP[NVIC_InitStruct->NVIC_IRQChannel] = tmppriority;
    
    /* Enable the Selected IRQ Channels --------------------------------------*/
    NVIC->ISER[NVIC_InitStruct->NVIC_IRQChannel >> 0x05] =
      (uint32_t)0x01 << (NVIC_InitStruct->NVIC_IRQChannel & (uint8_t)0x1F);
  }
  else
  {
    /* Disable the Selected IRQ Channels -------------------------------------*/
    NVIC->ICER[NVIC_InitStruct->NVIC_IRQChannel >> 0x05] =
      (uint32_t)0x01 << (NVIC_InitStruct->NVIC_IRQChannel & (uint8_t)0x1F);
  }
}

在这里插入图片描述
3、编写中断服务函数
在启动文件 startup_stm32f10x_hd.s 中我们预先为每个中断都写了一个中断服务函数,只是这些中断函数都是为空,为的只是初始化中断向量表。实际的中断服务函数都需要我们重新编写,为了方便管理我们把中断服务函数统一写在 stm32f10x_it.c 这个库文件中。
在这里插入图片描述

如果一切配置完毕,当中断来临时,CPU会根据相应的中断去中断向量表找到对应的中断函数的地址,然后调用执行中断服务函数。

二.EXTI—外部中断/事件控制器

这里的外部中断是指由外部条件触发例如按键触发(GPIO),对于互联型产品(F107),外部中断/事件控制器由20个产生事件/中断请求的边沿检测器组成,对于其它产品(我们这里是F103),则有19个能产生事件/中断请求的边沿检测器。每个输入线可以独立地配置输入类型(脉冲或挂起)和对应的触发事件(上升沿或下降沿或者双边沿都触发)。每个输入线都可以独立地被屏蔽。挂起寄存器保持着状态线的中断请求
在这里插入图片描述

1.外部中断/事件线路映像

而中断线每次只能连接到 1 个 IO 口上,这样就需要通过配置来决定对应的中断线配置到哪个 GPIO 上了。
在这里插入图片描述
EXTI16~19也作为EXTI外设的输入线
在这里插入图片描述
16个中断线的不是每个中断都有独立的中断服务函数,IO口外部中断在中断向量表中只分配了7个中断向量,也就是只能使用7个中断服务函数
在这里插入图片描述
从表中可以看出,外部中断线5~9分配一个中断向量,共用一个服务函数。
外部中断线10~15分配一个中断向量,共用一个中断服务函数。

对应的中断服务函数,直接去启动文件里面找以防写错。
在这里插入图片描述

2.EXTI功能框图

信号线上打一个斜杠并标注“20”字样,这个表示在控制器内部类似的信号线路有 20 个,这与 EXTI 总共有 20 个中断/事件线是吻合的。所以我们只要明白其中一个的原理,那其他 19 个线路原理也就知道了

在这里插入图片描述
通过在软件中断/事件寄存器写’1’,也可以通过软件产生中断/事件请求
在这里插入图片描述

脉冲发生器:
在这里插入图片描述
输入一个有效信号 1 时就会产生一个脉冲,如果输入端是无效信号就不会输出脉冲。这个脉冲信号可以给其他外设电路使用,比如定时器 TIM、模拟数字转换器 ADC 等等,这样的脉冲信号一般用来触发 TIM 或者 ADC 开始转换

中断与事件的区别:

  • 中断:需要CPU参与,需要调用软件的中断服务函数才能完成中断后产生的结果
  • 事件:靠脉冲发生器产生一个脉冲,进而由硬件自动完成这个事件产生的结果,当然相应的联动部件需要先设置好,触发TIM计时,AD转换等,事件不要软件的参与,降低了CPU的负荷,而且硬件速度快于软件速度

详情推荐一篇文章:《中断与事件的区别》

接下来逐一介绍用到的寄存器,进一步理解框图原理:

  • 外部中断配置寄存器

在这里插入图片描述

  • 上升&下降沿触发选择寄存器

在同一中断线上,可以同时设置上升沿和下降沿触发。即任一边沿都可触发中断
在这里插入图片描述
在这里插入图片描述

  • 软件中断事件寄存器(EXTI_SWIER)

在这里插入图片描述

  • 挂起寄存器

在这里插入图片描述
中断或事件屏蔽寄存器
在这里插入图片描述

3.选择中断线与EXTI 初始化结构体详解

  • 选择中断线
    在配置中断线时一定要先使能AFIO外设的时钟,因为配置中断线是用到ADIO外设的寄存器,我们知道配置寄存器必须要有时钟

使能时钟
在这里插入图片描述
配置中断线
在这里插入图片描述

在这里插入图片描述

  • 配置EXTI初始化结构体
    在这里插入图片描述

1) EXTI_Line:EXTI 中断/事件线选择,可选 EXTI0 至 EXTI19。

2) EXTI_Mode:EXTI 模式选择,可选为产生中断(EXTI_Mode_Interrupt)或者产生事件(EXTI_Mode_Event)。

3) EXTI_Trigger:EXTI 边沿触发事件可选上升沿触发(EXTI_Trigger_Rising)、下降沿触发 ( EXTI_Trigger_Falling) 或者上升沿和下降沿都触发( EXTI_Trigger_Rising_Falling)。

4) EXTI_LineCmd:控制是否使能 EXTI 线,可选使能 EXTI 线(ENABLE)或禁用(DISABLE)。

最后调用EXTI_Init函数,将结构体配置好的参数写入对应的寄存器,这个比较简单我就不讲了,这里提一下这个结构体中断/事件线的选择并不是配置中断线/事件线,配置线的函数上面已经提及,这里选择线是为了知道中断线在寄存器哪个位置(019)对应中断线(EXTI019),好配置相应的寄存器。

三.外部中断控制实验

实验目的:利用按键产生一个下降沿,让系统产生一个中断,执行中断服务函数,函数将GPIO电平翻转使得灯,按一下亮按一下灭。

实验原理

在这里插入图片描述
EXTI程序框图分析:
在这里插入图片描述

编程要点

1) 初始化用来产生中断的 GPIO;
2) 初始化 EXTI;
3) 配置 NVIC;
4) 编写中断服务函数;

直接上代码咯:

exti.c

#include "exti.h"

static void NVIC_EXTI_Config(void)
{
	NVIC_InitTypeDef  NVIC_InitStruct;
	//中断优先级分组这里是组1
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
	//选择中断源
	NVIC_InitStruct.NVIC_IRQChannel= EXTI15_10_IRQn;
	//设置抢占式优先级
	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority =1;
	//设置响应式优先级
	NVIC_InitStruct.NVIC_IRQChannelSubPriority =1;
	//使能中断源
	NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
	//调用NVIC初始化函数
	NVIC_Init(&NVIC_InitStruct);
}


void EXTI_Key_Config(void)
{		

	 GPIO_InitTypeDef  GPIO_InitStruct;
	 EXTI_InitTypeDef  EXTI_InitStruct;
  
	 RCC_APB2PeriphClockCmd(EXTI_Key1_GPIO_CLK,ENABLE);
	 //上拉输入
	 GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IPU;
	 GPIO_InitStruct.GPIO_Pin= EXTI_Key1_GPIO_PIN ;
   GPIO_Init(EXTI_Key1_GPIO_POTR,&GPIO_InitStruct);
	 //配置NVIC中断
	 NVIC_EXTI_Config();
   //一定要使能外设AFIO外设的时钟
	 RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
	 //选择信号源
	 GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource15);
	 //选择中断线
	 EXTI_InitStruct.EXTI_Line = EXTI_Line15;
	 //选择模式这里选择中断模式
	 EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt;
	 //下降沿模式
	 EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Falling;
	 //使能中断
	 EXTI_InitStruct.EXTI_LineCmd = ENABLE;
	 EXTI_Init(&EXTI_InitStruct);
	
}

exti.h

#ifndef __EXTI_H
#define __EXTI_H


#include "stm32f10x.h"


#define   EXTI_Key1_GPIO_PIN         GPIO_Pin_15
#define   EXTI_Key1_GPIO_POTR        GPIOA
#define   EXTI_Key1_GPIO_CLK         RCC_APB2Periph_GPIOA

void EXTI_Key_Config(void);
#endif /*__EXTI_H */


main.c

#include "stm32f10x.h"
#include "led.h"
#include "exti.h"

#define SOFT_DELAY Delay(0x0FFFFF);

void Delay(__IO u32 nCount); 


int main(void)
{	
	/* LED 端口初始化 */
	LED_GPIO_Config();	 
  EXTI_Key_Config();
	LED_G(OFF);
	LED_R(OFF);

	while(1)
	{
	}
}

void Delay(__IO uint32_t nCount)	 //简单的延时函数
{
	for(; nCount != 0; nCount--);
}

中断服务函数

void EXTI15_10_IRQHandler(void)
{
	//防抖
	  Delay(0x0FFFF);
	//判断按键是否按下
	if( GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_15)== 0)
	{
	
    if(  EXTI_GetITStatus(EXTI_Line15) != RESET )
	  {
			//电平翻转
		  GPIOA->ODR ^= GPIO_Pin_8;
		}
  	//清除中断挂起位
	 EXTI_ClearITPendingBit(EXTI_Line15);
	}

}

注意:执行完函数时一定要清除中断挂起为,不然系统会一直进入中断函数

在这里插入图片描述

实验效果

请添加图片描述

四.总结

由于本文涉及的知识点太多,参考了很多资料然后结合自己的理解写出这篇文章快接近万字了,到这终于写完啦,如果有错误还请指正,如果涉及到初始化函数那些寄存器具体怎么运算写入的不懂的可以评论区问我,建议虽然是库函数数编程,但尽量去看看函数是如何将参数写入寄存器的以及各个寄存器的作用,这样可以极大加深我们对原理的理解。觉得文章对你有所帮助就快快点赞收藏叭!!!

结束语:
最近发现一款刷题神器,如果大家想提升编程水平,玩转C语言指针,还有常见的数据结构(最重要的是链表和队列)后面嵌入式学习操作系统的时如freerots、RT-Thread等操作系统,链表与队列知识大量使用。
大家可以点击下面连接进入牛客网刷题

点击跳转进入网站(C语言方向)
点击跳转进入网站(数据结构算法方向)
在这里插入图片描述

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

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

相关文章

档案馆对于档案室档案库房内温度和湿度的控制要求

编辑搜图 请点击输入图片描述&#xff08;最多18字&#xff09; 01 纸质档案库的温湿度要求 用房名称温度&#xff08;℃&#xff09;相对湿度&#xff08;%&#xff09;纸质档案库14~2445~60 02 特殊档案库的温湿度要求 用房名称温度&#xff08;℃&#xff09;相对湿度&am…

Golang中的运算符

目录 运算符 算术运算符 代码案例&#xff1a; 关系运算符 代码案例&#xff1a; 逻辑运算符 代码案例&#xff1a; 位运算符 代码案例&#xff1a; 赋值运算符 代码案例&#xff1a; 其他运算符 运算符 算术运算符 Go语言中的算术运算符包括加、减、乘、除和取模…

【深入理解redis】数据结构

文章目录 动态字符串SDS字符串编码类型 intsetDictZipListZipList的连锁更新问题 QuickListSkipListRedisObjectStringListSet结构ZSETHash Redis 共有 5 种基本数据结构&#xff1a;String&#xff08;字符串&#xff09;、List&#xff08;列表&#xff09;、Set&#xff08;…

2023进销存财务软件哪个好?哪些适合中小商户使用?

对于开店的老板来说&#xff0c;门店的财务管理一直都是比较头疼的一件事&#xff0c;销售业绩人工统计困难&#xff0c;记账对账效率低且容易出错。 使用进销存财务软件可以有效的帮助门店解决财务管理问题&#xff0c;但市面上这么多进销存财务软件&#xff0c;哪些性价比较高…

Android编译优化之混淆配置

Android编译优化之混淆配置 背景 为了使用java8及后续java新版本的特性&#xff0c;Google增加了一步编译过程—脱糖&#xff08;desugaring&#xff09;&#xff0c;但这一步会导致更长的编译时间&#xff0c;这也是为什么Google会推出D8和R8编译器来优化编译速度。 什么是脱…

【C语言】扫雷游戏

这里写目录标题 前言1.初始化棋盘2.展示棋盘3.布置雷4.开始扫雷4.1判断输赢4.2扫雷时连续性展开4.3展示玩法 5.整体代码展示5.1 game.h头文件展示5.2 game.c源文件展示5.3 text.c源文件展示 所属专栏&#xff1a;C语言 博主首页&#xff1a;初阳785 代码托管&#xff1a;chuyan…

了解 XML结构(一)

文章目录 1 XML定义2 了解XML结构3 XML节点类型4 加载读取XML5 小结 1 XML定义 XML是一种可扩展标记语言&#xff08;Extensible Markup Language, XML&#xff09;,可以用来标记数据&#xff0c;定义数据类型&#xff0c;是一种允许用户对自己的标记语言进行定义的源语言。 …

数据治理是一个部门的工作还是全业务体系的工作?_光点科技

随着互联网时代的到来&#xff0c;数据已成为企业生产和经营的重要资源。但是&#xff0c;随着数据量的不断增加和数据形态的多样化&#xff0c;如何管理和利用数据也成为了企业面临的一个重要问题。在这个过程中&#xff0c;数据治理成为了一个备受关注的话题。 那么&#xff…

ChatGPT1论文解读《Improving Language Understanding by Generative Pre-Training》

论文总结 以下是我阅读完整篇论文做的个人总结&#xff0c;基本包含了chatGPT1设计的完整框架思路&#xff0c;可以仅看【论文总结】章节。 在GPT1实现的核心架构中&#xff0c;包含两个阶段。 第一阶段 在第一阶段基于一个包含7000本书籍内容的海量未标注文本数据集进行无…

IP-Guard能否支持通过审批后才能发送邮件?

支持,但目前暂时只支持带有附件的邮件通过申请审批或者自我备案放开策略控制发送出去。 使用方式: 1、申请审批:设置了禁止发送邮件的邮件控制策略后,在申请权限-发送邮件中,设置允许发送,设置相关审批流程,管理员审批完成后即可发送。 -申请权限-审批流程 2、自我备案:…

SSM框架学习-注解开发第三方bean管理

1. 复习xml配置文件管理第三方bean 在Spring中&#xff0c;可以使用依赖注入&#xff08;Dependency Injection&#xff09;来管理和使用第三方Bean。Spring提供了多种方式来进行依赖注入&#xff0c;比如构造函数注入、Setter方法注入、字段注入等。下面以Setter方法注入为例&…

pycharm 常用插件,常用插件推荐

1. Key Promoter X 如果让我给新手推荐一个 PyCharm 必装插件&#xff0c;那一定是 Key Promoter X 。 它就相当于一个快捷键管理大师&#xff0c;它时刻地在&#xff1a; 教导你&#xff0c;当下你的这个操作&#xff0c;应该使用哪个快捷操作来提高效率&#xff1f;提醒你…

Scala学习(二)

文章目录 1.Scala的运算符1.1 Scala中的equals和 2.流程控制2.1 if2.2 Scala中的三目运算符2.3 for循环 3.循环中断 1.Scala的运算符 1.1 Scala中的equals和 回顾Java中的运算符 equals和,equals比较的为值&#xff0c; 比较的为地址 String a1new String("hi");…

【数据结构】线性表——带头双向循环链表

文章目录 带头双向循环链表带头双向循环链表主体结构带头双向循环链表操作函数介绍带头双向循环链表操作函数实现带头双向循环链表的初始化函数&#xff1a;打印函数带头双向循环链表插入函数&#xff1a;指定结点后插入和查找函数头插尾插 带头双向循环链表删除函数指定结点删…

2022东南大学网安916专硕上岸经验帖

本文目录 第一部分简单介绍我的一些选择 第二部分寒假大三下学期小学期暑假及大四上学期考前准备及考试过程考后估分与真实分数复试准备与复试过程复试结果导师选择经验对自己考研情况的评价一些建议 第一部分 简单介绍 最近忙完了毕业设计论文和教师资格证面试&#xff0c;终…

pc端项目的h5页面运行在手机浏览器使用vconsole查看页面元素、控制台、请求等信息

文章目录 一、vconsole介绍1. 作用2. 优势 二、使用1、jq项目和js项目2、vue项目 三、使用介绍1. 使用成功&#xff0c;在页面右下角会出现如下图的vConsole2. 常用功能&#xff08;控制台、请求、元素、存储器&#xff09; 一、vconsole介绍 1. 作用 使用vconsole来查看h5页…

怎么自学python?为什么选择python

自然是因为Python简单易学且应用领域广 Python近段时间一直涨势迅猛&#xff0c;在各大编程排行榜中崭露头角&#xff0c;得益于它多功能性和简单易上手的特性&#xff0c;让它可以在很多不同的工作中发挥重大作用。 正因如此&#xff0c;目前几乎所有大中型互联网企业都在使…

python写完程序怎么运行

python有两种运行方式&#xff0c;一种是在python交互式命令行下运行; 另一种是使用文本编辑器直接在命令行上运行。 注&#xff1a;以上两种运行方式均由CPython解释器编译运行。 当然&#xff0c;也可以将python代码写入eclipse中&#xff0c;用JPython解释器运行&#xff0c…

ACM - 字符串 - 基础(KMP)

字符串 一、KMP1、模板题 HDU1711 Number Sequence2、求最大匹配数 Ⅰ&#xff1a; HDU 2087 剪花布条&#xff08;子串不重叠&#xff09;3、求最大匹配数 Ⅱ&#xff1a;AcWing 831. KMP字符串&#xff08;子串可重叠&#xff09;4、s2 是不是 s1 的翻转&#xff1a;Leetcode…

draw.io二次开发(3)从删删减减开始定制自己的drawio

经过克隆代码、配置IntelliJ/IDEA和Tomcat、以及本地部署&#xff08;详见前几篇&#xff09;之后&#xff0c;终于到了上手改代码的环节了。 首先需要强调的一点是&#xff1a;千万不要去改 *.min.js 文件中的代码&#xff0c;这些文件都是生成的压缩代码&#xff0c;我们一定…