stm32之EXIT外部中断详解
目录
- 1.引入: STM32F103
- 1.1 中断路径上的3个部件
- 1.2 STM32F103的GPIO中断
- 1.1.1 GPIO控制器 -- AFIO
- 1.1.2 EXTI
- 1.1.3 NVIC
- 1.1.4 CPU
- 1. PRIMASK
- 2. FAULTMASK
- 3. BASEPRI
- 1.3 中断执行流程
- 2.旋转编码器介绍
- 3.实验
- 3.1 EXIT
- 3.1.1 结构体
- 3.1.2 函数
- 3.2 NVIC
- 3.2.1 结构体
- 3.2.2 函数
- 3.3 混淆
- 3.4 中断函数
- 3.5 对射式红外传感器
- 3.6 旋转编码器计次
1.引入: STM32F103
在主程序运行过程中,出现了特定的中断触发条件(中断源),使得CPU暂停当前正在运行的程序,转而去处理中断程序,处理完成后又返回原来被暂停的位置继续运行
- 68个可屏蔽中断通道,包含EXTI、TIM、ADC、USART、SPI、I2C、RTC等多个外设
- 使用NVIC统一管理中断,每个中断通道都拥有16个可编程的优先等级,可对优先级进行分组,进一步设置抢占优先级和响应优先级
1.1 中断路径上的3个部件
● 中断源
-
中断源指引发中断信号的硬件模块,如GPIO、定时器、串口(UART)、DMA控制器等。这些模块都有各自的寄存器,可以设置中断相关的参数,例如:
-
- 使能中断:启用或禁用该模块的中断功能。
- 中断状态:检查该模块是否发生了中断。
- 中断类型:设置中断的触发条件,例如上升沿触发、下降沿触发或电平触发等。
-
中断源可以根据其设置的状态来决定是否向中断控制器发送中断请求信号。
● 中断控制器
-
中断控制器汇集所有中断源的信号,将其发送至CPU。中断控制器可以:
-
- 设置优先级:为不同的中断源设置优先级,以便在多重中断同时发生时,确定先响应哪个中断。当有多个中断源同时申请中断时,CPU会根据中断源的轻重缓急进行裁决,优先响应更加紧急的中断源
- 向CPU发出中断信号:中断控制器根据优先级和屏蔽设置向CPU发送中断请求信号。CPU通过读取中断控制器寄存器来判断哪个中断源需要响应。
-
中断控制器的实现因芯片平台而异,例如:
-
- STM32F103 使用 NVIC(嵌套向量中断控制器)来处理中断。
- ARM9 平台中通常由芯片厂商设计的特定中断控制器。
- Cortex A7 采用 GIC(通用中断控制器),具有更加复杂的中断管理功能。
● CPU
- CPU会在每条指令执行后检查是否有中断请求。
- CPU内部的寄存器提供了中断的总开关,可以通过这些寄存器来使能或禁用中断,从而实现对中断响应的控制。
1.2 STM32F103的GPIO中断
对于GPIO中断,STM32F103又引入了External interrupt/event controller (EXTI)
。用来设置GPIO的中断类型,如下图:
在STM32F103中,GPIO中断通过 EXTI(外部中断/事件控制器)模块来处理。EXTI允许我们配置GPIO中断的类型,如上升沿、下降沿或电平触发等。EXTI模块可以向NVIC(嵌套向量中断控制器)提供多达16个中断信号(EXTI0到EXTI15),以便将特定的GPIO中断事件传递到NVIC处理。
1.1.1 GPIO控制器 – AFIO
STM32F103的GPIO控制器中有AFIO_EXTICR1~AFIO_EXTICR4一共4个寄存器
名为:External interrupt configuration register,外部中断配置寄存器。
用来选择某个外部中断EXTIx的中断源,示例如下:
注意:从上图可知,EXTI0只能从PA0、……、PG0中选择一个,这也意味着PA0、……、PG0中只有一个引脚可以用于中断。这跟其他芯片不一样,很多芯片的任一GPIO引脚都可以同时用于中断。
AFIO主要用于引脚复用功能的选择和重定义
在STM32中,AFIO主要完成两个任务:复用功能引脚重映射、中断引脚选择
16个EXIT中各自的PA1、PA2、…、PA15,这些都是对应到GPIOA模块的16根引脚;同理PB1、PB2、…、PB15则是对应到GPIOB模块的16根引脚。
因此对于一个EXITx中的PAx、PBx、…、PGx,只能选择一个对应到某一个模块,有点抽象,就是你要配置GPIOA的PA1引脚作为中断引脚,那么就得将EXIT1映射到GPIOA模块,而此时你还想配置GPIOB的PB1作为中断源是不行的,因此EXIT1已经被GPIOA的PA1占用了。
同时对于D、E、F、G我们是可以不用去管的,它们是对应到PVD、RTC、USB、ETH,唤醒相关的。主要是关注A、B、C的中断线,江科大的stm32的板子我们观察IO引脚其实是之后GPIOA、GPIOB、GPIOC三个模块的引脚的。
1.1.2 EXTI
-
EXTI(Extern Interrupt)外部中断
-
EXTI可以监测指定GPIO口的电平信号,当其指定的GPIO口产生电平变化时,EXTI将立即向NVIC发出中断申请,经过NVIC裁决后即可中断CPU主程序,使CPU执行EXTI对应的中断程序
-
支持的触发方式:上升沿/下降沿/双边沿/软件触发
-
支持的GPIO口:所有GPIO口,但相同的Pin不能同时触发中断通道数:16个GPIO_Pin,外加PVD输出、RTC闹钟、USB唤醒、以太网唤醒
-
触发响应方式:中断响应/事件响应
-
- 中断响应是正常的流程,引脚电平触发中断
- 事件响应不会触发中断,而是触发别的外设操作,属于外设之间的联合工作
在GPIO控制器中,可以设置某个GPIO引脚作为中断源,给EXTI提供中断信号。但是,这个中断的触发方式是怎么的?高电平触发、低电平触发、上升沿触发、下降沿触发?这需要进一步设置。EXTI框图如下:
沿着上面框图中的红线,我们要设置:
- 选择哪些GPIO可以发出中断(EXITmux)
- Falling trigger selection register:是否选择下降沿触发(EventTrigger)
- Rising trigger selection register:是否选择上升沿触发(EventTrigger)
- …(EventTrigger)
- Interrupt mask register:是否屏蔽中断,允许某个EXTI中断(Masking)
当发生中断时,可以读取下列寄存器判断是否发生了中断、发生了哪个中断:
- Pending reqeust register
要使用EXTI,流程如下:
- 配置EXTI_IMR(中断屏蔽寄存器)以允许EXTI发出中断信号。
- 配置EXTI_RTSR和EXTI_FTSR寄存器,选择触发方式。
- 在NVIC中配置相关寄存器,允许NVIC将中断传递给CPU。
1.1.3 NVIC
NVIC的中断优先级由优先级寄存器的4位(0~15)决定,这4位可以进行切分,分为高n位的抢占优先级和低4-n位的响应优先级
抢占优先级高的可以中断嵌套,响应优先级高的可以优先排队,抢占优先级和响应优先级均相同的按中断号排队
分组方式 | 抢占优先级 | 响应优先级 |
---|---|---|
分组0 | 0位,取值为0 | 4位,取值为0~15 |
分组1 | 1位,取值为0~1 | 3位,取值为0~7 |
分组2 | 2位,取值为0~3 | 2位,取值为0~3 |
分组3 | 3位,取值为0~7 | 1位,取值为0~1 |
分组4 | 4位,取值为0~15 | 0位,取值为0 |
此时正在处理中断A,后面排队的中断C突然闯进来,暂时搁置A,去处理C | 此时正在处理中断A,排队的有B、C,中断C比较紧急,处理完A后先去处理C |
多个中断源汇聚到NVIC,NVIC的职责就是从多个中断源中取出优先级最高的中断,向CPU发出中断信号。处理中断时,程序可以写NVIC的寄存器,清除中断。涉及的寄存器:
我们暂时只需要关注:ISER(中断设置使能寄存器)、ICPR(中断清除挂起寄存器)。要注意的是,这些寄存器有很多个,比如ISER0、ISER1等等。里面的每一位对应一个中断。ISER0中的bit0对应异常向量表中的第16项(向量表从第0项开始),如下图:
1.1.4 CPU
Cortex M3/M4处理器内部有多个用于管理中断的寄存器,包括:
1. PRIMASK
-
PRIMASK:当PRIMASK的第0位设置为1时,可以屏蔽所有可配置优先级的中断。设置方法:
-
- 使用汇编指令 CPSIE I(使能中断)和 CPSID I(禁止中断)。
- 通过 MOV R0, #1 和 MSR PRIMASK, R0 设置PRIMASK寄存器。
把PRIMASK的bit0设置为1,就可以屏蔽所有优先级可配置的中断。
可以使用这些指令来设置它:
CPSIE I ; 清除PRIMASK,使能中断
CPSID I ; 设置PRIMASK,禁止中断或者:
MOV R0, #1
MSR PRIMASK R0 ; 将1写入PRIMASK禁止所有中断MOV R0, #0
MSR PRIMASK, R0 ; 将0写入PRIMASK使能所有中断
2. FAULTMASK
-
FAULTMASK:类似于PRIMASK,但可以屏蔽除NMI(不可屏蔽中断)外的所有中断,包括HardFault。设置方法:
-
- 使用 CPSIE F(使能中断)和 CPSID F(禁止中断)。
- 通过指令 MOV R0, #1 和 MSR FAULTMASK, R0 来设置FAULTMASK寄存器。
FAULTMASK和PRIMASK很像,它更进一步,出来一般的中断外,把HardFault都禁止了。
只有NMI可以发生。
可以使用这些指令来设置它:
CPSIE F ; 清除FAULTMASK
CPSID F ; 设置FAULTMASK或者:
MOV R0, #1
MSR FAULTMASK R0 ; 将1写入FAULTMASK禁止中断MOV R0, #0
MSR FAULTMASK, R0 ; 将0写入FAULTMASK使能中断
3. BASEPRI
- BASEPRI:用于屏蔽优先级大于或等于BASEPRI值的中断。例如,MOVS R0, #0x60 和 MSR BASEPRI, R0 禁止优先级在0x60到0xFF之间的中断
BASEPRI用来屏蔽这些中断:它们的优先级,其值大于或等于BASEPRI。
可以使用这些指令来设置它:
MOVS R0, #0x60
MSR BASEPRI, R0 ; 禁止优先级在0x60~0xFF间的中断MRS R0, BASEPRI ; 读取BASEPRIMOVS R0, #0
MSR BASEPRI, R0 ; 取消BASEPRI屏蔽
1.3 中断执行流程
中断嵌套:当一个中断程序正在运行时,又有新的更高优先级的中断源申请中断,CPU再次暂停当前中断程序,转而去处理新的中断程序,处理完成后依次进行返回。但其实好像是不推荐嵌套太多的中断(在Linux当中的,对于MCU的板子我其实也不是很确定)。
中断处理函数需要调用 C 函数,这就需要用到栈。
- 中断 A 正在处理的过程中,假设又发生了中断 B,那么在栈里要保存 A 的现场,然后处理 B。
- 在处理 B 的过程中又发生了中断 C,那么在栈里要保存 B 的现场,然后处理C。
如果中断嵌套突然暴发,那么栈将越来越大,栈终将耗尽。
所以,为了防止这种情况发生,也是为了简单化中断的处理,而在 Linux 系统上中断无法嵌套:即当前中断 A 没处理完之前,不会响应另一个中断 B(即使它的优先级更高)。
2.旋转编码器介绍
旋转编码器:用来测量位置、速度或旋转方向的装置,当其旋转轴旋转时,其输出端可以输出与旋转速度和方向对应的方波信号,读取方波信号的频率和相位信息即可得知旋转轴的速度和方向
类型:机械触点式/霍尔传感器式/光栅式
第三个方框的是霍尔传感器,是直接附着在电机上的传感器。
这里使用的是第二个方框的旋转编码器,对于这种编码器,我们是不可能无时无刻的去读取它是否有数据产生,那么就可以采用外部中断的方式,stm32去干别的事情,当我们转动编码器就会产生中断,stm32接收到了就可以去读取。
下面是其硬件电路图:
这种编码器输出的正交波形,正向和反向是通过A、B输出的波形之间是滞后还是提前90°来判断是正向旋转还是反向旋转的。下图中上方就是B输出的波形比A滞后了90°,也就是编码器是正向旋转;而下方的则是B输出的波形比A提前了90°,也就是反向旋转。
3.实验
3.1 EXIT
3.1.1 结构体
stm32f10x_exit.c、.h
typedef struct
{uint32_t EXTI_Line; /*!< Specifies the EXTI lines to be enabled or disabled.This parameter can be any combination of @ref EXTI_Lines */EXTIMode_TypeDef EXTI_Mode; /*!< Specifies the mode for the EXTI lines.This parameter can be a value of @ref EXTIMode_TypeDef */EXTITrigger_TypeDef EXTI_Trigger; /*!< Specifies the trigger signal active edge for the EXTI lines.This parameter can be a value of @ref EXTITrigger_TypeDef */FunctionalState EXTI_LineCmd; /*!< Specifies the new state of the selected EXTI lines.This parameter can be set either to ENABLE or DISABLE */
}EXTI_InitTypeDef;
对uint32_t EXTI_Line
,指定需要进行配置的对应的外部中断线(如PA0、PA1、…、PA15中的某一根或几根):
#define EXTI_Line0 ((uint32_t)0x00001) /*!< External interrupt line 0 */
#define EXTI_Line1 ((uint32_t)0x00002) /*!< External interrupt line 1 */
#define EXTI_Line2 ((uint32_t)0x00004) /*!< External interrupt line 2 */
#define EXTI_Line3 ((uint32_t)0x00008) /*!< External interrupt line 3 */
#define EXTI_Line4 ((uint32_t)0x00010) /*!< External interrupt line 4 */
#define EXTI_Line5 ((uint32_t)0x00020) /*!< External interrupt line 5 */
#define EXTI_Line6 ((uint32_t)0x00040) /*!< External interrupt line 6 */
#define EXTI_Line7 ((uint32_t)0x00080) /*!< External interrupt line 7 */
#define EXTI_Line8 ((uint32_t)0x00100) /*!< External interrupt line 8 */
#define EXTI_Line9 ((uint32_t)0x00200) /*!< External interrupt line 9 */
#define EXTI_Line10 ((uint32_t)0x00400) /*!< External interrupt line 10 */
#define EXTI_Line11 ((uint32_t)0x00800) /*!< External interrupt line 11 */
#define EXTI_Line12 ((uint32_t)0x01000) /*!< External interrupt line 12 */
#define EXTI_Line13 ((uint32_t)0x02000) /*!< External interrupt line 13 */
#define EXTI_Line14 ((uint32_t)0x04000) /*!< External interrupt line 14 */
#define EXTI_Line15 ((uint32_t)0x08000) /*!< External interrupt line 15 */
EXTIMode_TypeDef EXTI_Mode
,触发响应方式:
typedef enum
{EXTI_Mode_Interrupt = 0x00, //中断模式EXTI_Mode_Event = 0x04 //事件模式
}EXTIMode_TypeDef;
EXTITrigger_TypeDef EXTI_Trigger
,中断的触发模式
typedef enum
{EXTI_Trigger_Rising = 0x08, //上升沿触发EXTI_Trigger_Falling = 0x0C, //下降沿触发EXTI_Trigger_Rising_Falling = 0x10 //双边沿触发
}EXTITrigger_TypeDef;
FunctionalState EXTI_LineCmd;
:指定EXIT的状态,ENABLE or DISABLE
3.1.2 函数
/*** @brief 将 EXTI 外部中断/事件控制器的寄存器恢复到默认重置值。* @param 无* @retval 无* 该函数用于重置所有 EXTI 寄存器,将其恢复为系统默认状态。通常在初始化或* 重新配置前调用,以确保 EXTI 的状态为干净的重置状态。*/
void EXTI_DeInit(void);/*** @brief 根据指定的 EXTI_InitStruct 配置 EXTI 外设。* @param EXTI_InitStruct: 指向 EXTI_InitTypeDef 结构体的指针,包含 EXTI 外设的配置信息。* @retval 无* 此函数用于根据 EXTI_InitStruct 提供的配置信息对 EXTI 外设进行初始化。用户可以通过配置* EXTI_InitStruct 中的参数(如触发条件、线号等)来定制 EXTI 的行为,完成中断或事件触发* 的初始化。*/
void EXTI_Init(EXTI_InitTypeDef* EXTI_InitStruct);/*** @brief 将每个 EXTI_InitStruct 成员填充为其默认重置值。* @param EXTI_InitStruct: 指向 EXTI_InitTypeDef 结构体的指针,该结构体将被初始化。* @retval 无* 此函数将 EXTI_InitStruct 结构体的每个成员变量重置为默认值,通常在创建新配置结构体时* 调用,以确保所有字段都有已知的默认状态。用户可以在此基础上修改所需的参数来完成初始化。*/
void EXTI_StructInit(EXTI_InitTypeDef* EXTI_InitStruct);/*** @brief 生成软件中断。* @param EXTI_Line: 指定要启用或禁用的软件中断线路。该参数可以是任意组合的 EXTI_Linex,其中 x 的范围为 (0..19)。* @retval 无* 该函数生成指定线路的软件中断,模拟硬件中断触发,以用于测试或控制。例如,可在* 调试阶段用来触发中断处理程序。不同线路可以同时被触发,用于复合中断的模拟。*/
void EXTI_GenerateSWInterrupt(uint32_t EXTI_Line);/*** @brief 检查指定的 EXTI 标志状态。* @param EXTI_Line: 指定要检查的 EXTI 标志线路。该参数可以是任意 EXTI_Linex 的组合,其中 x 的范围为 (0..19)。* @retval FlagStatus: EXTI_Line 的新状态(SET 或 RESET)。* 该函数用于获取某条 EXTI 线路的中断标志状态。返回的状态可以是 SET(中断发生)* 或 RESET(未发生)。通常在中断服务程序中使用,以确定具体的中断源。*/
FlagStatus EXTI_GetFlagStatus(uint32_t EXTI_Line);/*** @brief 清除 EXTI 的线路挂起标志。* @param EXTI_Line: 指定要清除的 EXTI 标志线路。该参数可以是任意 EXTI_Linex 的组合,其中 x 的范围为 (0..19)。* @retval 无* 该函数清除 EXTI 线路的挂起标志,表明中断处理已完成,通常在中断服务程序末尾调用。* 一旦标志被清除,下一次相同中断触发才会重新设置标志。*/
void EXTI_ClearFlag(uint32_t EXTI_Line);/*** @brief 检查指定的 EXTI 线路是否被触发。* @param EXTI_Line: 指定要检查的 EXTI 线路。该参数可以是 EXTI_Linex,其中 x 的范围为 (0..19)。* @retval ITStatus: EXTI_Line 的新状态(SET 或 RESET)。* 该函数用于检查指定线路的中断触发状态。如果返回值为 SET,表明中断已经触发且未处理;* 否则为 RESET。可用于确定中断触发源,以便于分辨多路中断。*/
ITStatus EXTI_GetITStatus(uint32_t EXTI_Line);/*** @brief 清除 EXTI 的线路挂起位。* @param EXTI_Line: 指定要清除的 EXTI 挂起线路。该参数可以是任意 EXTI_Linex 的组合,其中 x 的范围为 (0..19)。* @retval 无* 此函数用于清除指定线路的挂起位,表示中断已被处理。清除后,相同线路的中断能够再次触发,* 用于控制连续的中断请求。*/
void EXTI_ClearITPendingBit(uint32_t EXTI_Line);
3.2 NVIC
在配置前是需要使用的NVIC_PriorityGroupConfig
函数去选择分组配置,也就是抢占优先级和响应优先级的分配。
3.2.1 结构体
typedef struct
{uint8_t NVIC_IRQChannel; /*!< Specifies the IRQ channel to be enabled or disabled.This parameter can be a value of @ref IRQn_Type (For the complete STM32 Devices IRQ Channels list, pleaserefer to stm32f10x.h file) */uint8_t NVIC_IRQChannelPreemptionPriority; /*!< Specifies the pre-emption priority for the IRQ channelspecified in NVIC_IRQChannel. This parameter can be a valuebetween 0 and 15 as described in the table @ref NVIC_Priority_Table */uint8_t NVIC_IRQChannelSubPriority; /*!< Specifies the subpriority level for the IRQ channel specifiedin NVIC_IRQChannel. This parameter can be a valuebetween 0 and 15 as described in the table @ref NVIC_Priority_Table */FunctionalState NVIC_IRQChannelCmd; /*!< Specifies whether the IRQ channel defined in NVIC_IRQChannelwill be enabled or disabled. This parameter can be set either to ENABLE or DISABLE */
} NVIC_InitTypeDef;
uint8_t NVIC_IRQChannel
,指定要启用或禁用的IRQ信道
#ifdef STM32F10X_MDADC1_2_IRQn = 18, /*!< ADC1 and ADC2 global Interrupt */USB_HP_CAN1_TX_IRQn = 19, /*!< USB Device High Priority or CAN1 TX Interrupts */USB_LP_CAN1_RX0_IRQn = 20, /*!< USB Device Low Priority or CAN1 RX0 Interrupts */CAN1_RX1_IRQn = 21, /*!< CAN1 RX1 Interrupt */CAN1_SCE_IRQn = 22, /*!< CAN1 SCE Interrupt */EXTI9_5_IRQn = 23, /*!< External Line[9:5] Interrupts */TIM1_BRK_IRQn = 24, /*!< TIM1 Break Interrupt */TIM1_UP_IRQn = 25, /*!< TIM1 Update Interrupt */TIM1_TRG_COM_IRQn = 26, /*!< TIM1 Trigger and Commutation Interrupt */TIM1_CC_IRQn = 27, /*!< TIM1 Capture Compare Interrupt */TIM2_IRQn = 28, /*!< TIM2 global Interrupt */TIM3_IRQn = 29, /*!< TIM3 global Interrupt */TIM4_IRQn = 30, /*!< TIM4 global Interrupt */I2C1_EV_IRQn = 31, /*!< I2C1 Event Interrupt */I2C1_ER_IRQn = 32, /*!< I2C1 Error Interrupt */I2C2_EV_IRQn = 33, /*!< I2C2 Event Interrupt */I2C2_ER_IRQn = 34, /*!< I2C2 Error Interrupt */SPI1_IRQn = 35, /*!< SPI1 global Interrupt */SPI2_IRQn = 36, /*!< SPI2 global Interrupt */USART1_IRQn = 37, /*!< USART1 global Interrupt */USART2_IRQn = 38, /*!< USART2 global Interrupt */USART3_IRQn = 39, /*!< USART3 global Interrupt */EXTI15_10_IRQn = 40, /*!< External Line[15:10] Interrupts */RTCAlarm_IRQn = 41, /*!< RTC Alarm through EXTI Line Interrupt */USBWakeUp_IRQn = 42 /*!< USB Device WakeUp from suspend through EXTI Line Interrupt */
#endif /* STM32F10X_MD */
uint8_t NVIC_IRQChannelPreemptionPriority;
,指定所选通道的抢占优先级
uint8_t NVIC_IRQChannelSubPriority;
,指定所选通道的响应优先级
3.2.2 函数
/*** @brief 配置优先级分组:抢占优先级和子优先级。* @param NVIC_PriorityGroup: 指定优先级分组的位数。* 参数可以是以下值之一:* @arg NVIC_PriorityGroup_0: 0 位用于抢占优先级* 4 位用于子优先级* @arg NVIC_PriorityGroup_1: 1 位用于抢占优先级* 3 位用于子优先级* @arg NVIC_PriorityGroup_2: 2 位用于抢占优先级* 2 位用于子优先级* @arg NVIC_PriorityGroup_3: 3 位用于抢占优先级* 1 位用于子优先级* @arg NVIC_PriorityGroup_4: 4 位用于抢占优先级* 0 位用于子优先级* @retval 无* 此函数配置优先级分组,用于设置中断的抢占优先级和子优先级的位数。在中断处理* 中,可以通过优先级分组实现不同中断的嵌套控制,确保高优先级中断的优先处理。*/
void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup);/*** @brief 根据 NVIC_InitStruct 指定的参数初始化 NVIC 外设。* @param NVIC_InitStruct: 指向 NVIC_InitTypeDef 结构体的指针,包含指定 NVIC 外设的配置信息。* @retval 无* 此函数将 NVIC 配置为用户定义的初始化结构体,允许用户设定中断优先级、使能中断等。* 通过该初始化配置,可以灵活地控制系统的中断处理行为。*/
void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct);/*** @brief 设置中断向量表的位置和偏移量。* @param NVIC_VectTab: 指定中断向量表的存储位置,可以选择放在 RAM 或 FLASH 中。* 参数可以是以下值之一:* @arg NVIC_VectTab_RAM:向量表在 RAM 中* @arg NVIC_VectTab_FLASH:向量表在 FLASH 中* @param Offset: 向量表基址的偏移量。该值必须为 0x200 的倍数。* @retval 无* 此函数允许用户更改中断向量表的存放位置和偏移量,适用于内存布局不同的系统需求,* 如引导加载程序或自定义异常向量表等。*/
void NVIC_SetVectorTable(uint32_t NVIC_VectTab, uint32_t Offset);/*** @brief 选择系统进入低功耗模式的条件。* @param LowPowerMode: 指定系统进入低功耗模式的新模式。* 参数可以是以下值之一:* @arg NVIC_LP_SEVONPEND: 待决中断导致事件激活* @arg NVIC_LP_SLEEPDEEP: 选择深度睡眠模式* @arg NVIC_LP_SLEEPONEXIT: 在退出中断后立即进入睡眠模式* @param NewState: LP 条件的新状态。此参数可以是:ENABLE 或 DISABLE。* @retval 无* 此函数配置系统的低功耗条件,例如选择深度睡眠模式、是否在中断结束后立即进入睡眠。* 用于实现节电控制,通常在不需要频繁处理任务的场景下使用。*/
void NVIC_SystemLPConfig(uint8_t LowPowerMode, FunctionalState NewState);/*** @brief 配置 SysTick 定时器的时钟源。* @param SysTick_CLKSource: 指定 SysTick 的时钟源。* 参数可以是以下值之一:* @arg SysTick_CLKSource_HCLK_Div8: AHB 时钟的 1/8 用作 SysTick 时钟源* @arg SysTick_CLKSource_HCLK: AHB 时钟用作 SysTick 时钟源* @retval 无* 此函数设置 SysTick 定时器的时钟源选择,以控制 SysTick 定时器的计时频率。* 可以选择以较慢的分频后时钟运行以减少功耗,或直接使用系统主时钟 AHB 提高* 定时精度。*/
void SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource);
3.3 混淆
/*开启时钟*/RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //开启GPIOB的时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); //开启AFIO的时钟,外部中断必须开启AFIO的时钟/*GPIO初始化*/GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOB, &GPIO_InitStructure); //将PB0和PB1引脚初始化为上拉输入/*AFIO选择中断引脚*/GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource0);//将外部中断的0号线映射到GPIOB,即选择PB0为外部中断引脚GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource1);//将外部中断的1号线映射到GPIOB,即选择PB1为外部中断引脚/*EXTI初始化*/EXTI_InitTypeDef EXTI_InitStructure; //定义结构体变量EXTI_InitStructure.EXTI_Line = EXTI_Line0 | EXTI_Line1; //选择配置外部中断的0号线和1号线EXTI_InitStructure.EXTI_LineCmd = ENABLE; //指定外部中断线使能EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; //指定外部中断线为中断模式EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; //指定外部中断线为下降沿触发EXTI_Init(&EXTI_InitStructure); //将结构体变量交给EXTI_Init,配置EXTI外设/*NVIC中断分组*/NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //配置NVIC为分组2//即抢占优先级范围:0~3,响应优先级范围:0~3//此分组配置在整个工程中仅需调用一次//若有多个中断,可以把此代码放在main函数内,while循环之前//若调用多次配置分组的代码,则后执行的配置会覆盖先执行的配置/*NVIC配置*/NVIC_InitTypeDef NVIC_InitStructure; //定义结构体变量NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn; //选择配置NVIC的EXTI0线NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //指定NVIC线路使能NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; //指定NVIC线路的抢占优先级为1NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //指定NVIC线路的响应优先级为1NVIC_Init(&NVIC_InitStructure); //将结构体变量交给NVIC_Init,配置NVIC外设NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn; //选择配置NVIC的EXTI1线NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //指定NVIC线路使能NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; //指定NVIC线路的抢占优先级为1NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2; //指定NVIC线路的响应优先级为2NVIC_Init(&NVIC_InitStructure); //将结构体变量交给NVIC_Init,配置NVIC外设
以这个代码例子,要使用的是GPIOB的PB0、PB1引脚,同时这两个引脚都是要有中断功能的,而PB0是对应到EXIT0、PB1对应到EXIT1的。
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource0);//将外部中断的0号线映射到GPIOB,即选择PB0为外部中断引脚
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource1);//将外部中断的1号线映射到GPIOB,即选择PB1为外部中断引脚
所以就使用了GPIO_EXTILineConfig
将外部中断的0号线和1号线映射到GPIOB,这个0、1号线指的是就是PB0(EXIT0的)、PB1(EXIT1的),不要认为是EXIT0的第0号线PA0和EXIT1的第1号线PB1,这个是比较容易混淆的。因为对应GPIOB模块是有PB0、…、PB15共16根引脚,对应到各自的EXITx,这里所提到的外部中断的x号线是指模块的PB0、…、PB15的PBx,然后再去根据x对应到EXITx
之后就是配置EXTI_InitStructure
结构体,去配置外部中断PB0、PB1的相关信息,也就是响应方式、中断触发方式、使能。
已经配置了外部中断,就得配置一下中断的优先级,也就是去配置EXIT,而这个则是NVCI干的事情。
说白了就是16个EXIT,虽然每一个EXIT都有A~F的中断线,共有16*6,但是实际上呢,能够一起使用的只有16根中断线(各个EXIT抽取一根),也就是最多只能嵌套16个中断,因为一个EXIT只能取出一根来使用。GPIOA模块的PA1使用了EXIT1的PA1,GPIOB模块的PB1就不能使用EXIT1的PB1
3.4 中断函数
startup_stm32f10x_md.s启动文件中
发生中断时,会到对应的中断向量表,跳转到指定的中断函数:
__Vectors DCD __initial_sp ; Top of StackDCD Reset_Handler ; Reset HandlerDCD NMI_Handler ; NMI HandlerDCD HardFault_Handler ; Hard Fault HandlerDCD MemManage_Handler ; MPU Fault HandlerDCD BusFault_Handler ; Bus Fault HandlerDCD UsageFault_Handler ; Usage Fault HandlerDCD 0 ; ReservedDCD 0 ; ReservedDCD 0 ; ReservedDCD 0 ; ReservedDCD SVC_Handler ; SVCall HandlerDCD DebugMon_Handler ; Debug Monitor HandlerDCD 0 ; ReservedDCD PendSV_Handler ; PendSV HandlerDCD SysTick_Handler ; SysTick Handler; External InterruptsDCD WWDG_IRQHandler ; Window WatchdogDCD PVD_IRQHandler ; PVD through EXTI Line detectDCD TAMPER_IRQHandler ; TamperDCD RTC_IRQHandler ; RTCDCD FLASH_IRQHandler ; FlashDCD RCC_IRQHandler ; RCCDCD EXTI0_IRQHandler ; EXTI Line 0DCD EXTI1_IRQHandler ; EXTI Line 1DCD EXTI2_IRQHandler ; EXTI Line 2DCD EXTI3_IRQHandler ; EXTI Line 3DCD EXTI4_IRQHandler ; EXTI Line 4DCD DMA1_Channel1_IRQHandler ; DMA1 Channel 1DCD DMA1_Channel2_IRQHandler ; DMA1 Channel 2DCD DMA1_Channel3_IRQHandler ; DMA1 Channel 3DCD DMA1_Channel4_IRQHandler ; DMA1 Channel 4DCD DMA1_Channel5_IRQHandler ; DMA1 Channel 5DCD DMA1_Channel6_IRQHandler ; DMA1 Channel 6DCD DMA1_Channel7_IRQHandler ; DMA1 Channel 7DCD ADC1_2_IRQHandler ; ADC1_2DCD USB_HP_CAN1_TX_IRQHandler ; USB High Priority or CAN1 TXDCD USB_LP_CAN1_RX0_IRQHandler ; USB Low Priority or CAN1 RX0DCD CAN1_RX1_IRQHandler ; CAN1 RX1DCD CAN1_SCE_IRQHandler ; CAN1 SCEDCD EXTI9_5_IRQHandler ; EXTI Line 9..5DCD TIM1_BRK_IRQHandler ; TIM1 BreakDCD TIM1_UP_IRQHandler ; TIM1 UpdateDCD TIM1_TRG_COM_IRQHandler ; TIM1 Trigger and CommutationDCD TIM1_CC_IRQHandler ; TIM1 Capture CompareDCD TIM2_IRQHandler ; TIM2DCD TIM3_IRQHandler ; TIM3DCD TIM4_IRQHandler ; TIM4DCD I2C1_EV_IRQHandler ; I2C1 EventDCD I2C1_ER_IRQHandler ; I2C1 ErrorDCD I2C2_EV_IRQHandler ; I2C2 EventDCD I2C2_ER_IRQHandler ; I2C2 ErrorDCD SPI1_IRQHandler ; SPI1DCD SPI2_IRQHandler ; SPI2DCD USART1_IRQHandler ; USART1DCD USART2_IRQHandler ; USART2DCD USART3_IRQHandler ; USART3DCD EXTI15_10_IRQHandler ; EXTI Line 15..10DCD RTCAlarm_IRQHandler ; RTC Alarm through EXTI LineDCD USBWakeUp_IRQHandler ; USB Wakeup from suspend
__Vectors_End
以NVIC选择的是EXIT15_10的某一个为例,发生中断时执行的中断函数是EXTI15_10_IRQHandler
,因此我们只需要是定义实现该函数就行了。但是不要认为只能执行
和linux其实不太一样的,对于一些linux开发版(可能没有EXIT),可以在设备的驱动程序中去注册自己的中断处理函数,比如在GPIO模块中连接了多个设备,这些设备发生的中断会汇聚到模块上,发送同一个中断号给GIC控制器(看作是NVIC),下级是共享同一个类型的中断的。发生中断时调用哪一个设备的中断处理函数则有上级的中断处理函数来揣测调用。(在嵌入式驱动开发专栏的interrupt子系统中有讲解过)
在stm32中,对于一个EXIT模块的16根中断线PA0、PB0、…,它只能选择其中的一根去映射到GPIO模块
3.5 对射式红外传感器
EXIT的配置:对于对射式红外传感器,DO输出引脚接的是GPIOB14,那么就得用AFIO去将外部中断线第14线映射到GPIOB模块,也就是EIXT14的PB14,接下来就是去配置它:使能、中断触发方式、响应模式。
NVIC的配置:置NVIC,也就是对应的EXIT的中断优先级
然后就是去定义中断处理函数EXTI15_10_IRQHandler
Hardware:
- 📎OLED_Font.h
- 📎OLED.h
- 📎CountSensor.c
- 📎CountSensor.h
main.c:
- 📎main.c
📎5-1 对射式红外传感器计次.zip
3.6 旋转编码器计次
User:
- 📎main.c
Hardware:
- 📎Encoder.c
- 📎Encoder.h
- 📎OLED.c
- 📎OLED.h
- 📎OLED_Font.h
相关文章:
stm32之EXIT外部中断详解
目录 1.引入: STM32F1031.1 中断路径上的3个部件1.2 STM32F103的GPIO中断1.1.1 GPIO控制器 -- AFIO1.1.2 EXTI1.1.3 NVIC1.1.4 CPU1. PRIMASK2. FAULTMASK3. BASEPRI 1.3 中断执行流程 2.旋转编码器介绍3.实验3.1 EXIT3.1.1 结构体3.1.2 函数 3.2 NVIC3.2.1 结构体3.2.2 函数 3…...
STM32 开发 - stm32f10x.h 头文件(内存映射、寄存器结构体与宏、寄存器位定义、实现点灯案例)
概述 STM32F10x.h 是 STM32F1 系列微控制器的核心头文件,提供了所有外设寄存器的定义和内存映射 一、内存映射 #define PERIPH_BASE ((uint32_t)0x40000000)#define APB1PERIPH_BASE PERIPH_BASE #define APB2PERIPH_BASE (PERIPH_BASE 0x…...
UniApp 的现状与 WASM 支持的迫切性
一、UniApp 的跨平台优势与性能瓶颈 UniApp 凭借“一次开发,多端发布”的核心理念,已成为跨平台开发的主流框架之一。然而,随着移动应用场景的复杂化(如 3D 渲染、音视频处理、AI 推理),传统的 JavaScript…...
Prometheus、Zabbix和Nagios针对100个节点的部署设计架构图
一、Prometheus 架构图(联邦集群+分布式存储) graph TD;subgraph 全局监控层GlobalProm[Prometheus Server] -->|联邦查询| RegionalProm1[区域Prometheus]GlobalProm -->|联邦查询| RegionalProm2[区域Prometheus]GlobalProm -->|联邦查询| RegionalProm3[区域Pro…...
坚果派已适配的鸿蒙版flutter库【持续更新】
坚果派已适配的鸿蒙版flutter库 序号原仓版本适配仓文章解读是否完成1https://pub.dev/packages/fluttertoast8.2.12https://gitcode.com/nutpi/FlutterToasthttps://www.nutpi.net/thread?topicId1575是2https://pub.dev/packages/flutter_udid4.0.0https://gitcode.com/nut…...
代码随想录打卡|Day28 动态规划(理论基础、斐波那契数列、爬楼梯、使用最小花费爬楼梯)
动态规划 Part01 理论基础 代码随想录讲解链接 视频讲解链接 斐波那契数 力扣题目链接 代码随想录链接 视频讲解链接 题目描述: 斐波那契数 (通常用 F(n) 表示)形成的序列称为 斐波那契数列 。该数列由 0 和 1 开始,后面的每一…...
《USB技术应用与开发》第四讲:实现USB鼠标
一、标准鼠标分析 1.1简介 1.2页面显示 其中页面显示的“”不用管它,因为鼠标作为物理抓包,里面有时候会抓到一些错误,不一定是真正的通讯错误,很可能是本身线路接触质量不好等原因才打印出来的“”。 1.3按下鼠标左键 &#x…...
elk中kibana一直处于可用和降级之间且es群集状态并没有问题的解决方法
前言 在公司部elk的时候发现kibana的web界面一直很卡,数据量为0也会很卡,es群集状态正常,资源足够。 报错信息 [2025-03-17T09:54:50.19400:00][INFO ][status] Kibana is now available (was degraded) [2025-03-17T09:55:03.28000:00][I…...
2025.4.26总结
今天把马良老师的《职场十二法则》看完后,感触极大,这们课程就是一场职场启蒙课。 虽然看过不少关于职场的书籍,但大多数是关于职场进阶,方法方面的。并没有解答“面对未来二三十年的职场生涯,我该怎么去看待自己的工…...
一、UI自动化测试01--认识和元素定位方法
目录 一、自动化测试1. 自动化应用场景2. ⾃动化测试的优缺点3. ⾃动化测试的分类 二、UI ⾃动测试1. 适合使用的项目2. 实现时机3. 常⻅的UI⾃动化测试⼯具4. Selenium 框架5. Web ⾃动化环境部署6. Web ⾃动化基本代码 二、元素定位1. 浏览器开发者⼯具⽅法1: 直接获取信息⽅…...
目标检测原理简介
目标检测是一类计算机视觉任务,简单来说,目标检测可被定义为在计算机中输入一张图像,计算机需要找出图像中所有感兴趣的目标(物体),确定它们的类别和位置,如图一所示。目标检测是计算机视觉领域的核心问题之一,相较于最原始的将整张图片分类为某一类别,目标检测不光可…...
软件设计原则
开闭原则 对扩展开放,对修改关闭。在程序需要进行拓展的时候,不能去修改原有的代码,实现一个热插拔的效果。简言之,是为了使程序的扩展性好,易于维护和升级。 想要达到这样的效果,需要使用接口和抽象类。 因…...
Postman脚本处理各种数据的变量
一、变量是字符串里列表, 如 "["100","101","102","103","108"]" //把字符串的变量处理成列表 var myListJSON.parse(pm.environment.get(giftTabId)) #giftTabId变量名 //设置随机取值 var rando…...
嵌入式硬件开发工具---万用表---示波器---仿真器
万用表 主要功能: 测量交直流电压、电流 测量电阻、二级管及电路通断 其他----电容、频率、温度----特殊的万用表 * 检查电路是否正常 * 检查电路连接情况 示波器 主要功能: 以波形展示电信号随时间变化的关系 主要指标: 带宽---大…...
数据预处理之特征选择 (Feature Selection)
哈喽,大家好,我是我不是小upper~ 今天的文章和大家来聊聊数据与处理方法中常用的特征选择 在开始说特征选择前,咱们先搞清楚这个所谓的“特征”到底是啥玩意儿。 打个比方说,如果我们要训练一个模型来判断某个人是否会买一双运…...
Java基础 — 循环
介绍 Java基础循环是程序流程控制的核心结构,主要用于重复执行特定代码块。常见的循环包括for、while和do-while三种形式,开发者可根据不同场景灵活选择。 合理使用循环关键字能有效提升代码执行效率。掌握循环结构的核心在于理解执行流程与条件判断的时…...
参考平面的宽度-信号与电源完整性分析
参考平面的宽度: 计算特征阻抗时假设参考平面是无限宽的平面。在参考平面的宽度远大于线宽或介质厚度时,这种假设是正确的。但是PCB板上的参考平面经常被反焊盘掏空,当互连线经过参考平面掏空区域附近时,掏空的局部互连线参考平面变窄&#x…...
【Linux】Centos7 安装 Docker 详细教程
一、安装步骤 步骤一:确定你是Centos7及以上的版本 cat /etc/redhat-release 步骤二:卸载旧版本 查看官方文档:CentOS | Docker Docs 步骤三:安装GCC等工具 1.首先确保 CentOS7 能上外网 ping www.baidu.com 2.更新 Centos7…...
开源AI智能名片链动2+1模式S2B2C商城小程序源码赋能下的社交电商创业者技能跃迁与价值重构
摘要:在移动互联网深度重构商业生态的背景下,社交电商创业者面临流量成本攀升、用户粘性不足、供应链协同低效等核心痛点。本文以“开源AI智能名片链动21模式S2B2C商城小程序源码”技术体系为研究对象,通过分析其技术架构、商业逻辑及实战案例…...
计算机视觉与深度学习 | LSTM原理及与卡尔曼滤波的融合
长短期记忆网络(LSTM)是一种特殊的循环神经网络(RNN),旨在解决传统RNN在处理长序列数据时出现的梯度消失和梯度爆炸问题。以下为你详细介绍其基本原理: 核心思想:LSTM的核心思想是引入记忆单元和门控机制来控制信息的流动,从而解决传统RNN的梯度消失问题。记忆单元类似…...
阿里云域名智能解析至国内外AWS的合规化部署指南
引言 随着全球化业务的发展,企业常面临地域合规性与用户体验优化的双重挑战。本文以阿里云域名解析为核心,结合AWS中国区(北京/宁夏)与Global区域部署,提供一套完整的解决方案,实现: 智能流量调度:国内用户访问AWS中国区,海外用户自动路由至AWS Global全链路合规:满…...
一、鸿蒙编译篇
一、下载源码和编译 https://blog.csdn.net/xusiwei1236/article/details/142675221 https://blog.csdn.net/xiaolizibie/article/details/146375750 https://forums.openharmony.cn/forum.php?modviewthread&tid897 repo init -u https://gitee.com/openharmony/mani…...
计算机网络 | 应用层(3)-- 因特网中的电子邮件
💓个人主页:mooridy 💓专栏地址:《计算机网络:自定向下方法》 大纲式阅读笔记 关注我🌹,和我一起学习更多计算机的知识 🔝🔝🔝 目录 3. 因特网中的电子邮件 …...
Missashe考研日记-day27
Missashe考研日记-day27 0 写在前面 博主昨晚有事所以没学专业课,白天学了其他科,但是觉得不太好写博客,就合在今天一起写好了。 1 专业课408 学习时间:3h30min学习内容: 今天把内存管理部分剩下的关于分页分段和段…...
【Castle-X机器人】五、物联网模块配置与调试
持续更新。。。。。。。。。。。。。。。 【Castle-X机器人】五、物联网模块配置与调试 五、物联网模块配置与调试5.1 物联网模块调试物联网模块测试:控制物联网模块:物联网模块话题五、物联网模块配置与调试 5.1 物联网模块调试 调试前需确保Castle-x与mqtt主机服务器处于同…...
FastAPI 零基础入门指南:10 分钟搭建高性能 API
一、为什么选择 FastAPI? 想象一下,用 Python 写 API 可以像搭积木一样简单,同时还能拥有媲美 Go 语言的性能,这个框架凭借三大核心优势迅速风靡全球: 开发效率提升 3 倍:类型注解 自动文档,…...
有关图的类型的题目(1)
1、图着色问题 #include<bits/stdc.h> using namespace std; const int N510,MN*N; int color[N]; vector<int> g[M]; int v,m,k,n;void add(int a,int b){g[a].push_back(b);g[b].push_back(a); } int judge(int cnt){if(cnt!k)return 0;for(int i1;i<v;i){fo…...
threejs 零基础学习day01
一、threejs本地环境搭建 1、下载源码 (1)进入threejs官网,把源码下载到本地访问。https://github.com/mrdoob/three.js (2)使用git命令的方式进行下载(优点是,threejs更新频繁,这…...
dubbo 异步化实践
DubboService public class AsyncOrderFacadeImpl implements AsyncOrderFacade {private Logger logger LoggerFactory.getLogger(AsyncOrderFacadeImpl.class);// 构建线程池ThreadPoolExecutor threadPoolExecutor new ThreadPoolExecutor(1000, 1000, 10, TimeUnit.SECOND…...
Web端ER可视化
背景介绍 因业务需要,团队决定对原ER图功能进行重构。重构来自两方面,一是功能上进行了细分,二是实现方式发生了变化。下面是重构前后对比: 重构前重构后功能方面只有逻辑模型层面的ER图包括概念模型、逻辑模型、物理模型3个层面的ER图实现方式单页面、antv/g6微前端、Rea…...
Java在云计算、大数据、云原生下的应用和优势 - 面试实战
Java在云计算、大数据、云原生下的应用和优势 - 面试实战 第一轮提问 面试官:马架构,请简单介绍一下Java在云计算中的主要应用场景有哪些? 马架构:Java在云计算中的主要应用场景包括微服务架构设计、容器化部署(如D…...
精益数据分析(27/126):剖析用户价值与商业模式拼图
精益数据分析(27/126):剖析用户价值与商业模式拼图 在创业和数据分析的领域中,每一次深入学习都是一次成长的契机。今天,我们继续秉持共同进步的理念,深入研读《精益数据分析》,剖析用户价值的…...
从 Lambda 到 DSL:Kotlin 接口实现的演进之路
Kotlin 中优化 Android 接口实现的几种方式 在 Android 开发中,Kotlin 提供了多种优雅的方式来优化接口实现。以下是几种优化方案: 1. 使用 SAM 转换简化单方法接口 对于单一抽象方法(Single Abstract Method, SAM)接口: // 优化前 butto…...
GitOps进化:深入探讨 Argo CD 及其对持续部署的影响
什么是 GitOps? 虽然软件开发生命周期的大部分已经实现自动化,但基础设施仍然在很大程度上依赖于人工,需要专业团队的参与。随着当今基础设施需求的不断增长,实施基础设施自动化变得越来越重要。现代基础设施需要具备弹性&#x…...
有源晶振与无源晶振详解:区别、应用与选型指南
一、基本定义 无源晶振(Crystal,晶体谐振器) 结构:仅包含石英晶体,无内置振荡电路。 工作原理:依赖外部电路(如MCU的振荡器)驱动,通过机械振动产生谐振频率。 核心公式…...
机器学习:逻辑回归实现二元分类
本例子以鸡蛋受精卵为例,假设未受精的鸡蛋在某个区域聚集,受精的在另一个区域。比如,用正态分布生成两个类别的数据,均值不同,方差相同或不同。例如,未受精的鸡蛋的特征均值为[1,1],受精的为[4,4],这样两类数据点可以在二维空间中被分开。 首先,生成数据。使用sklear…...
Android学习总结之kotlin篇(一)
1. open 关键字的用法和作用深入源码分析 类的 open 修饰:在 Kotlin 字节码层面,对于一个open类,编译器会在生成的字节码中添加ACC_SUPER和ACC_OPEN标志。例如,定义一个open class TestOpenClass,反编译其字节码可以看…...
arcgis空间分析理论研究
arcgis的空间分析功能有(1)地形与地表分析;(2)距离与成本分析;(3)密度分析;(4)水文分析;(5)统计分析ÿ…...
70. 爬楼梯
假设你正在爬楼梯。需要 n 阶你才能到达楼顶。 每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢? 注意:给定 n 是一个正整数。 示例 1: 输入: 2输出: 2解释: 有两种方法可以爬到楼顶。…...
Eigen核心矩阵/向量类 (Matrix, Vector, Array)
1. Matrix 类(稠密矩阵) 模板参数 cpp Matrix<Scalar, Rows, Cols, Options, MaxRows, MaxCols> Scalar: 元素类型(如 float, double, int)。 Rows/Cols: 行数和列数(Dynamic 表示动态大小)。 O…...
立创EDA
空格键:旋转 alt w : 布线 alt v : 放置过孔 shift x :先在原理图中框选,按下shiftx,批量选中pcd中的对应元件 shift h : 选中的网络持续高亮/取消高亮 更改位号:举例 框选要更改的电阻 右侧栏属性 --> 位号…...
计算机网络笔记(十二)——2.5数字传输系统
数字传输系统是光纤通信中实现高速数据传输的核心技术,解决了传统模拟传输的速率不统一、同步性差等问题。 一、早期数字传输的问题 速率标准不统一:北美(T1: 1.544Mbps)和欧洲(E1: 2.048Mbps)采用不同的…...
[FPGA Video IP] Video Processing Subsystem
Xilinx Video Processing Subsystem IP (PG231) 详细介绍 概述 Xilinx LogiCORE™ IP Video Processing Subsystem (VPSS)(PG231)是一个高度可配置的视频处理模块,设计用于在单一 IP 核中集成多种视频处理功能,包括缩放…...
java基础之枚举和注解
枚举 简介 枚举:enumeration,jdk1.5中引入的新特性,用于管理和使用常量 入门案例 第一步:定义枚举,这里定义一个动物类,里面枚举了多种动物 public enum AnimalEnum {CAT, // 猫DOG, // 狗PIG // …...
前端开发本地配置 HTTPS 全面详细教程
分为两步:生成证书、本地服务配置使用证书一、HTTPS 的基本概念 HTTPS 是一种安全的 HTTP 协议,它通过 SSL/TLS 对数据进行加密,确保数据在传输过程中不被窃取或篡改。在前端开发中,某些功能(如 Geolocation API、Web…...
C语言中宏的高级应用
一、宏的核心高级特性 1. 变参宏(Variadic Macros) 支持不定数量参数,用于灵活处理格式化字符串、日志输出等场景。 #include <stdio.h>// 定义支持可变参数的调试宏 #define DEBUG_LOG(format, ...) \printf("[DEBUG] %s:%d |…...
Simulink 数据字典(Data Dictionary)详解:使用场景、存储内容与调用方法
1. 引言 在 Simulink 建模中,随着模型复杂度增加,参数管理变得尤为重要。传统方法(如 MATLAB 工作区变量或脚本)在团队协作或大型项目中容易导致数据分散、版本混乱。数据字典(Data Dictionary) 提供了一种…...
部署yolo到k230教程
训练:K230 借助 AICube部署AI 视觉模型 YOLO等教程_嘉楠 ai cube多标签分类-CSDN博客K230模型训练ai cube报错生成部署文件异常_aicube部署模型显示生成部署文件异常-CSDN博客 部署: # 导入必要的库和模块 import os import ujson # 超快的JS…...
【高频考点精讲】第三方库安全审计:如何避免引入带漏洞的npm包
大家好,我是全栈老李。今天咱们聊一个前端工程师必须掌握的生存技能——如何避免把带漏洞的npm包引入项目。这可不是危言耸听,去年某大厂就因为在生产环境用了有漏洞的lodash版本,被黑客利用原型污染漏洞直接攻破后台系统。 为什么npm包会变成"定时炸弹"? npm生…...
【后端】主从单体数据库故障自动切换,容灾与高可用
在现代企业级应用中,数据库的高可用性和容灾能力是保障业务连续性的关键。尤其是在一些对稳定性要求较高的业务场景中,当主数据库发生故障时,如何快速切换到备用数据库并确保业务不受影响,成为了一个重要课题。本文将介绍一种基于 SpringBoot 和 Druid 数据源的解决方案,通…...