【STM32】STM32中断体系

一、STM32的NVIC和起始代码中的ISP

1.NVIC(嵌套向量中断控制器)

(1)数据手册中相关部分浏览
(2)地址映射时0地址映射到Flash或SRAM
(3)中断向量表可以被人为重新映射,一般用来IAP中
(4)STM32采用一维的中断向量表
(5)中断优先级设置有点复杂,后面细说

1.特征

2.系统嘀嗒(SysTick)校准值寄存器

3.向量表

在每一个中断函数在startup_stm32f10x_md.s中都有进行定义

2、起始代码中的ISR

(1)其实代码中定义了一个Vector数组
(2)WEAK声明的默认ISR
(3)用户根据需要提供自己真正有用的ISR
(4)中断要配置使能,ISR中要清挂起等,这一点和其他CPU一样

二、STM32的外部中断(EXTI)

1.EXTI 控制器的主要特性如下:

2.外部中断/事件控制器框图

3.外部中断与I/O 映像(AFIO的的中断)

AFIO中与中断相关的寄存器有4个

记得再使用之前一定要使能时钟!!!!!

我们有4个AFIO的中断寄存器,则一个寄存器中应该可以处理16个引脚。

最好使用引脚时,设置PA0,PA1....

使用AFIO中的EXTICRx寄存器进行操作

/**
  * @brief  Selects the GPIO pin used as EXTI Line.
  * @param  GPIO_PortSource: selects the GPIO port to be used as source for EXTI lines.
  *   This parameter can be GPIO_PortSourceGPIOx where x can be (A..G).
  * @param  GPIO_PinSource: specifies the EXTI line to be configured.
  *   This parameter can be GPIO_PinSourcex where x can be (0..15).
  * @retval None
  */
void GPIO_EXTILineConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource)
{
  uint32_t tmp = 0x00;
  /* Check the parameters */
  assert_param(IS_GPIO_EXTI_PORT_SOURCE(GPIO_PortSource));
  assert_param(IS_GPIO_PIN_SOURCE(GPIO_PinSource));
  
  tmp = ((uint32_t)0x0F) << (0x04 * (GPIO_PinSource & (uint8_t)0x03));
  AFIO->EXTICR[GPIO_PinSource >> 0x02] &= ~tmp;
  AFIO->EXTICR[GPIO_PinSource >> 0x02] |= (((uint32_t)GPIO_PortSource) << (0x04 * (GPIO_PinSource & (uint8_t)0x03)));
}

1.外部中断配置寄存器 1(AFIO_EXTICR1)

2.外部中断配置寄存器 2(AFIO_EXTICR2)

4.如何实际编程使用外部中断

(1)时钟设置并打开相应GPIO模块时钟
(2)将相应GPIO配置为浮空输入
(3)NVIC设置
(4)将外部中断线和配套的GPIO进行连接映射


(5)外部中断线使能触发
(6)准备好ISR,并在ISR处等待执行中断程序即可

(7)记得!!!!!!!!!执行完ISR后记得将中断清除。

5.外部中断 VS 外部事件中断

外部中断:需要CPU,中断处理程序的参与

外部事件中断:不需要CPU参与

我们一般使用外部中断,不使用外部事件中断,因为我们不知道该器件是否接受脉冲信号。

6.相关寄存器

1. 上升沿触发选择寄存器(EXTI_RTSR)

2.下降沿触发选择寄存器(EXTI_FTSR)

3.中断屏蔽寄存器(EXTI_IMR)

4.挂起寄存器(EXTI_PR)

三、标准库中NVIC(中断优先级)模块分析

因为中断处理是在CPU内部进行的,所以没有单独的.c和.h文件

NVIC在【misc.c】中

1.抢占优先级 VS 次优先级

当抢占优先级的不同时,抢占优先级小的先执行,然后在执行优先级大的。

当抢占优先级相同时,次优先级小的不能抢占次优先级大的

当相同抢占优先级的程序进行中断时,次优先级小的可以抢先执行,在执行次优先级大的。

//PreemptionPriority:抢优先级
  uint8_t NVIC_IRQChannelPreemptionPriority;  /*!< Specifies the pre-emption priority for the IRQ channel
                                                   specified in NVIC_IRQChannel. This parameter can be a value
                                                   between 0 and 15 as described in the table @ref NVIC_Priority_Table */
//次优先级【同一个抢占级别中进行判断的】
  uint8_t NVIC_IRQChannelSubPriority;         /*!< Specifies the subpriority level for the IRQ channel specified
                                                   in NVIC_IRQChannel. This parameter can be a value
                                                   between 0 and 15 as described in the table @ref NVIC_Priority_Table */

2.优先级组

/**
	pre-emption:抢占优先级
	subpriority:次优先级
*/
#define NVIC_PriorityGroup_0         ((uint32_t)0x700) /*!< 0 bits for pre-emption priority
                                                            4 bits for subpriority=》2的4次方*/
#define NVIC_PriorityGroup_1         ((uint32_t)0x600) /*!< 1 bits for pre-emption priority
                                                            3 bits for subpriority=>2的3次方*/
#define NVIC_PriorityGroup_2         ((uint32_t)0x500) /*!< 2 bits for pre-emption priority
                                                            2 bits for subpriority */
#define NVIC_PriorityGroup_3         ((uint32_t)0x400) /*!< 3 bits for pre-emption priority
                                                            1 bits for subpriority */
#define NVIC_PriorityGroup_4         ((uint32_t)0x300) /*!< 4 bits for pre-emption priority
                                                            0 bits for subpriority */

3.启动方式

RAM或者FLASH

/**
	启动方式:RAM或者FLASH
	从0x0000 0000到0x080 0000之间的地址是用来设置映射关系
	因为我们使用FLASH启动,所以将其映射到0x0800 0000
	
*/
#define NVIC_VectTab_RAM             ((uint32_t)0x20000000)
#define NVIC_VectTab_FLASH           ((uint32_t)0x08000000)
#define IS_NVIC_VECTTAB(VECTTAB) (((VECTTAB) == NVIC_VectTab_RAM) || \
                                  ((VECTTAB) == NVIC_VectTab_FLASH))

4.函数

1.NVIC_PriorityGroupConfig

在使用时一定设置使用哪一个优先级

/**
  * @brief  Configures the priority grouping: pre-emption priority and subpriority.
  * @param  NVIC_PriorityGroup: specifies the priority grouping bits length. 
  *   This parameter can be one of the following values:
  *     @arg NVIC_PriorityGroup_0: 0 bits for pre-emption priority
  *                                4 bits for subpriority
  *     @arg NVIC_PriorityGroup_1: 1 bits for pre-emption priority
  *                                3 bits for subpriority
  *     @arg NVIC_PriorityGroup_2: 2 bits for pre-emption priority
  *                                2 bits for subpriority
  *     @arg NVIC_PriorityGroup_3: 3 bits for pre-emption priority
  *                                1 bits for subpriority
  *     @arg NVIC_PriorityGroup_4: 4 bits for pre-emption priority
  *                                0 bits for subpriority
  * @retval None
  */
void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup)
{
  /* Check the parameters */
  assert_param(IS_NVIC_PRIORITY_GROUP(NVIC_PriorityGroup));
  
  /* Set the PRIGROUP[10:8] bits according to NVIC_PriorityGroup value */
  SCB->AIRCR = AIRCR_VECTKEY_MASK | NVIC_PriorityGroup;
}

2.NVIC_Init

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.NVIC_SetVectorTable

设置中断向量表,看要设置到RAM还是FLASH

void NVIC_SetVectorTable(uint32_t NVIC_VectTab, uint32_t Offset)
{ 
  /* Check the parameters */
  assert_param(IS_NVIC_VECTTAB(NVIC_VectTab));
  assert_param(IS_NVIC_OFFSET(Offset));  
   
  SCB->VTOR = NVIC_VectTab | (Offset & (uint32_t)0x1FFFFF80);
}

四、标准库中外部中断模块分析

1.EXTI_DeInit

 //完全去始化
void EXTI_DeInit(void)
{
  EXTI->IMR = 0x00000000;
  EXTI->EMR = 0x00000000;
  EXTI->RTSR = 0x00000000; 
  EXTI->FTSR = 0x00000000; 
  EXTI->PR = 0x000FFFFF;
}

2.EXTI_Init

将我们设置好的结构体变量写入到寄存器中

/**
  * @brief  Initializes the EXTI peripheral according to the specified
  *         parameters in the EXTI_InitStruct.
  * @param  EXTI_InitStruct: pointer to a EXTI_InitTypeDef structure
  *         that contains the configuration information for the EXTI peripheral.
  * @retval None
  */
void EXTI_Init(EXTI_InitTypeDef* EXTI_InitStruct)
{
  uint32_t tmp = 0;

  /* Check the parameters */
  assert_param(IS_EXTI_MODE(EXTI_InitStruct->EXTI_Mode));
  assert_param(IS_EXTI_TRIGGER(EXTI_InitStruct->EXTI_Trigger));
  assert_param(IS_EXTI_LINE(EXTI_InitStruct->EXTI_Line));  
  assert_param(IS_FUNCTIONAL_STATE(EXTI_InitStruct->EXTI_LineCmd));

  tmp = (uint32_t)EXTI_BASE;
     
  if (EXTI_InitStruct->EXTI_LineCmd != DISABLE)//表示要使能
  {
    /* Clear EXTI line configuration */
    EXTI->IMR &= ~EXTI_InitStruct->EXTI_Line;
    EXTI->EMR &= ~EXTI_InitStruct->EXTI_Line;
    
    tmp += EXTI_InitStruct->EXTI_Mode;

    *(__IO uint32_t *) tmp |= EXTI_InitStruct->EXTI_Line;

    /* Clear Rising Falling edge configuration */
    EXTI->RTSR &= ~EXTI_InitStruct->EXTI_Line;
    EXTI->FTSR &= ~EXTI_InitStruct->EXTI_Line;
    
    /* Select the trigger for the selected external interrupts */
    if (EXTI_InitStruct->EXTI_Trigger == EXTI_Trigger_Rising_Falling)
    {
      /* Rising Falling edge */
      EXTI->RTSR |= EXTI_InitStruct->EXTI_Line;
      EXTI->FTSR |= EXTI_InitStruct->EXTI_Line;
    }
    else
    {
      tmp = (uint32_t)EXTI_BASE;
      tmp += EXTI_InitStruct->EXTI_Trigger;

      *(__IO uint32_t *) tmp |= EXTI_InitStruct->EXTI_Line;
    }
  }
  else
  {
    tmp += EXTI_InitStruct->EXTI_Mode;

    /* Disable the selected external lines */
    *(__IO uint32_t *) tmp &= ~EXTI_InitStruct->EXTI_Line;
  }
}

3.EXTI_StructInit

如果用户不想自己设置中断值,则可以调用这个函数,这个函数中有默认值可以使用

void EXTI_StructInit(EXTI_InitTypeDef* EXTI_InitStruct)
{
  EXTI_InitStruct->EXTI_Line = EXTI_LINENONE;
  EXTI_InitStruct->EXTI_Mode = EXTI_Mode_Interrupt;
  EXTI_InitStruct->EXTI_Trigger = EXTI_Trigger_Falling;
  EXTI_InitStruct->EXTI_LineCmd = DISABLE;
}

4.EXTI_GenerateSWInterrupt

软件中断,可以对寄存器中其中一位进行中断操作

void EXTI_GenerateSWInterrupt(uint32_t EXTI_Line)
{
  /* Check the parameters */
  assert_param(IS_EXTI_LINE(EXTI_Line));
  
  EXTI->SWIER |= EXTI_Line;
}

5.EXTI_GetFlagStatus

共享中断:判断中断标志位是否真的置1了(判断是哪一个标志进行中断的)

/**
  * @brief  Checks whether the specified EXTI line flag is set or not.
  * @param  EXTI_Line: specifies the EXTI line flag to check.
  *   This parameter can be:
  *     @arg EXTI_Linex: External interrupt line x where x(0..19)
  * @retval The new state of EXTI_Line (SET or RESET).
  */
FlagStatus EXTI_GetFlagStatus(uint32_t EXTI_Line)
{
  FlagStatus bitstatus = RESET;
  /* Check the parameters */
  assert_param(IS_GET_EXTI_LINE(EXTI_Line));
  
  if ((EXTI->PR & EXTI_Line) != (uint32_t)RESET)
  {
    bitstatus = SET;
  }
  else
  {
    bitstatus = RESET;
  }
  return bitstatus;
}

6.EXTI_ClearITPendingBit(中断挂起)

中断进入后,就会有一个中断挂起

/**
  * @brief  Clears the EXTI's line pending bits.
  * @param  EXTI_Line: specifies the EXTI lines to clear.
  *   This parameter can be any combination of EXTI_Linex where x can be (0..19).
  * @retval None
  */
void EXTI_ClearITPendingBit(uint32_t EXTI_Line)
{
  /* Check the parameters */
  assert_param(IS_EXTI_LINE(EXTI_Line));
  
  EXTI->PR = EXTI_Line;
}

6.EXTI_ClearFlag

清除中断

void EXTI_ClearFlag(uint32_t EXTI_Line)
{
  /* Check the parameters */
  assert_param(IS_EXTI_LINE(EXTI_Line));
  
  EXTI->PR = EXTI_Line;
}

五、GPIO外部中断程序的移植和调试

0.GPIO外部中断的配置步骤

使用HAL_GPIO_Init一步到位(步骤2-步骤5)

1.EXTI的HAL库设置步骤(GPIO外部中断)

2.通用外设驱动模型

3.HAL库中断回调处理机制介绍

1.建立工程模板

STM32项目工程的搭建-CSDN博客

2.查看官方示例代码

以ARM3.0的按键示例程序作为参考,移植到PZ6806L开发板上。

stm32f10x_it.c

将我们在初始化文件(STM32F10x_md.c)中的中断函数进行覆盖重写。

startup_stm32f10x_md.s

这个文件中存放是有中断处理函数的定义

我们如果想要执行(使用)这个中断,则将在md文件中将函数名字复制出来,然后再stm32f10x_it.c文件中使用

stm32f10x_it.h

我们上面再stm32f10x_it.c中重写了一个函数,则要再这个.h文件中进行声明

main.c

RCC_Configuragtion

作用:将时钟设置为72MHZ,将相关的开关打开。

GPIO_Configuration

NVIC_Configuration

NVIC中断优先级的初始化

3.整个main函数的流程

1)初始化RCC

2)初始化GPIO

3)初始化NVIC

4)设置外部中断(将中断线和GPIO线连接起来)

5)外部中断线的模式选择(我们一般选择外部中断,不使用外部事件中断)

6)产生软件中断触发事件

4.开始移植

1.按键的接线问题

这个程序的执行结果是:按下按键一(KEY1),使得LED16(也就是4*4矩阵显示屏上最后一排灯亮起)

独立按键的JP1接到PB0-PB7

LED8-LED16的J34接到PA0-PA7

因为操作库函数的时候只能一位一位操作,所以我们只能选择其中一个引脚进行操作。

我们选择KEY1和LED16进行操作,分别对应PB0和PA7

2.关于中断几的选择

由上面可知我们KEY1对应的是PB0,由0可知应该选择EXIT0

确定好后,再stm32f10x.c和stm32f10x.h文件中进行重写和声明【我们可以再stm32f10x_md.c文件中查看应该调用哪一个函数】

3.EXTI0_IRQHandler的移植

注意点:本来我们应该再stm32f10x_it.c文件中去查找这个中断函数的初始化,但是普中科技的AMR3.0的官方代码将这个中断函数的初始化写再了exit.c文件中。

stm32f10x_it.c
  */
void EXTI0_IRQHandler(void)
{
	//检测制定的EXTI线路触发
	if(EXTI_GetITStatus(EXTI_Line0)==1)
	{
		/*
		delay_ms(10);
		if(KEY1==0)
		{
			led2=0;
		}
		*/
	}
	//清除EXTI线路挂起位
	EXTI_ClearITPendingBit(EXTI_Line0);
}
stm32f10x_it.h
//声明自己写的EXIT0
void EXTI0_IRQHandler(void);

4.RCC_Configuration的移植

1.RCC的使能
//RCC的配置
void RCC_Configuration(void){
	
	//因为起始代码中已经调用SystemInit将主时钟设置为72MHZ
	//所以我们这里RCC直接使能时钟就可以
	
	//使能GPIO端口
	//因为我们使用到的是PB0和PB8,所以只使用到GPIOB
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|
												RCC_APB2Periph_AFIO,ENABLE);
	
}
2.GPIO_Configuration的移植
//GPIO初始化
void CPIO_Configuration(void){
	
	GPIO_InitTypeDef GPIO_InitStructure;
	
	//PB0 -- Key1 -- EXIT2		PA7 ---LED16
	//PB0 -- Key1 -- EXIT2【按键是输入获取】
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;	  //配置浮空输入
  GPIO_Init(GPIOB, &GPIO_InitStructure);
	
	//PA7 ---LED16【LED的显示输出】
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;       //推挽输出
  GPIO_Init(GPIOA, &GPIO_InitStructure);
  GPIO_WriteBit(GPIOA, GPIO_Pin_7, Bit_RESET);			// 默认输出0让LED亮

}
3.NVIC优先级的移植

NVIC_IRQChannel:在misc.h中定义

void NVIC_Configuration(void)
{
  NVIC_InitTypeDef NVIC_InitStructure;
  
#ifdef  VECT_TAB_RAM  
  /* Set the Vector Table base location at 0x20000000 */ 
  NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0);   //分配中断向量表
#else  /* VECT_TAB_FLASH  */
	//表示从FLASH中启动
  /* Set the Vector Table base location at 0x08000000 */ 
  NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);   
#endif

  /* Configure one bit for preemption priority */
  // NVIC_PriorityGroup_1:2个抢占优先级,8个次优先级
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);  //设置中断优先级
  
  /* Enable the EXTI2 Interrupt */
  NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn; //中断通道
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority =  0;  //强占优先级
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;//次优先级
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;  //通道中断使能
  NVIC_Init(&NVIC_InitStructure);//初始化中断
}
4.main函数
//函数声明
//RCC的配置
void RCC_Configuration(void);
//GPIO初始化
void GPIO_Configuration(void);
void NVIC_Configuration(void);

//全局变量定义
EXTI_InitTypeDef EXTI_InitStructure;
ErrorStatus HSEStatartUpStatus;

int main(){
	
	//系统时钟配置
	RCC_Configuration();
	//NVIC配置
	NVIC_Configuration();
	//配置GPIO
	GPIO_Configuration();
	
	//将EXTI线0连接到PB0【处理按键中断】
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource0);
	
		/* Configure Key Button EXTI Line to generate an interrupt on falling edge */  
	//配置按钮中断线触发方式
	EXTI_InitStructure.EXTI_Line = EXTI_Line0;
	EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; //下降沿触发
	EXTI_InitStructure.EXTI_LineCmd = ENABLE; //中断线使能
  	EXTI_Init(&EXTI_InitStructure); //初始化中断

  	/* Generate software interrupt: simulate a falling edge applied on Key Button EXTI line */
 // 	EXTI_GenerateSWInterrupt(EXTI_Line0); //EXTI_Line2中断允许 到此中断配置完成,可以写中断处理函数。
        
  	while (1);
	
	
	return 0;
}
5.中断函数的处理(stm32f10x_it.c)

因为我们要在中断函数中对LED进行点亮/熄灭,所以需要对LED进行读取和写入。

所以要使用到我们的【GPIO_ReadInputDataBit】和【GPIO_WriteBit】

void EXTI0_IRQHandler(void)
{
	//检测制定的EXTI线路触发
	if(EXTI_GetITStatus(EXTI_Line0)==1)
	{
		//此时控制的是LED,LED对应的是PA0
		//我们想要对LED进行点亮/熄灭
		//则应该先将此时LED的状态位读取出来,然后在取反写进去
		GPIO_WriteBit(GPIOA,GPIO_Pin_0,(BitAction)((1-GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0))));
	}
	//清除EXTI线路挂起位
	EXTI_ClearITPendingBit(EXTI_Line0);
}
6.对LED的初始化

在对GPIO初始化的时候一起将lED一起点亮

	// 默认输出1让LED亮
  GPIO_WriteBit(GPIOA, GPIO_Pin_7, Bit_SET);	

3.完整代码

main.c

#include "stm32f10x.h"                  // Device header

/**
	使用库函数对STM32进行GPIO的外部中断
	按下KEY1对LED16进行点亮/熄灭
*/


//函数声明
//RCC的配置
void RCC_Configuration(void);
//GPIO初始化
void GPIO_Configuration(void);
void NVIC_Configuration(void);

//全局变量定义
EXTI_InitTypeDef EXTI_InitStructure;
ErrorStatus HSEStatartUpStatus;

int main(){
	
	//系统时钟配置
	RCC_Configuration();
	//NVIC配置
	NVIC_Configuration();
	//配置GPIO
	GPIO_Configuration();
	
	//将EXTI线0连接到PB0【处理按键中断】
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource0);
	
		/* Configure Key Button EXTI Line to generate an interrupt on falling edge */  
	//配置按钮中断线触发方式
	EXTI_InitStructure.EXTI_Line = EXTI_Line0;
	EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; //下降沿触发
	EXTI_InitStructure.EXTI_LineCmd = ENABLE; //中断线使能
  EXTI_Init(&EXTI_InitStructure); //初始化中断

  /* Generate software interrupt: simulate a falling edge applied on Key Button EXTI line */
	//人为产生中断
	//如果不想要一进来就产生中断,则应该注释掉
	//EXTI_Line0中断允许 到此中断配置完成,可以写中断处理函数。
 EXTI_GenerateSWInterrupt(EXTI_Line0); 
        
  	while (1);
	
	
	return 0;
}


//RCC的配置
void RCC_Configuration(void){
	
	//因为起始代码中已经调用SystemInit将主时钟设置为72MHZ
	//所以我们这里RCC直接使能时钟就可以
	
	//使能GPIO端口
	//因为我们使用到的是PB0和PB8,所以只使用到GPIOB
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|
												RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO,ENABLE);
	
}

//GPIO初始化
void CPIO_Gonfiguration(void){
	
	GPIO_InitTypeDef GPIO_InitStructure;
	
	//PB0 -- Key1 -- EXIT2		PA7 ---LED16
	//PB0 -- Key1 -- EXIT2【按键是输入获取】
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;	  //配置浮空输入
  GPIO_Init(GPIOB, &GPIO_InitStructure);

	
	//PA7 ---LED16【LED的显示输出】
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;       //推挽输出
  GPIO_Init(GPIOA, &GPIO_InitStructure);
	// 默认输出1让LED亮
  GPIO_WriteBit(GPIOA, GPIO_Pin_7, Bit_SET);			

}

void NVIC_Configuration(void)
{
  NVIC_InitTypeDef NVIC_InitStructure;
  
#ifdef  VECT_TAB_RAM  
  /* Set the Vector Table base location at 0x20000000 */ 
  NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0);   //分配中断向量表
#else  /* VECT_TAB_FLASH  */
	//表示从FLASH中启动
  /* Set the Vector Table base location at 0x08000000 */ 
  NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);   
#endif

  /* Configure one bit for preemption priority */
  // NVIC_PriorityGroup_1:2个抢占优先级,8个次优先级
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);  //设置中断优先级
  
  /* Enable the EXTI2 Interrupt */
  NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn; //中断通道
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority =  0;  //强占优先级
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;//次优先级
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;  //通道中断使能
  NVIC_Init(&NVIC_InitStructure);//初始化中断
}



stm32f10x_it.c
void EXTI0_IRQHandler(void)
{
	//检测制定的EXTI线路触发
	if(EXTI_GetITStatus(EXTI_Line0)==1)
	{
		//此时控制的是LED,LED对应的是PA0
		//我们想要对LED进行点亮/熄灭
		//则应该先将此时LED的状态位读取出来,然后在取反写进去
		GPIO_WriteBit(GPIOA,GPIO_Pin_0,(BitAction)((1-GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0))));
	}
	//清除EXTI线路挂起位
	EXTI_ClearITPendingBit(EXTI_Line0);
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

leetcode 146. LRU 缓存

2023.10.26 本题核心就是要将map中&#xff0c;最近最少操作的那个key给剔除掉&#xff0c;于是我们可以使用双端链表LinkedList 来维护每个元素的操作情况&#xff0c;最近操作的元素就将其移至表头&#xff0c;越久没操作的元素&#xff0c;自然就会沉到表尾。 一旦缓存满了…

作为前端开发,你应该知道的这十几个在线免费工具

​偶然刷到知乎一位前端大佬 表歌 多篇优秀实用的文章&#xff0c;真的发现宝藏了 以下内容就是他在知乎分享的十几个在线免费工具 1. 页面设计检查清单&#xff1a;https://www.checklist.design/ 页面设计检查清单 通过清单可以检查一些常用容易忽略的设计要素。 2. 背景色…

vscode远程连接ubuntu

修改环境变量&#xff0c;改使用git自带的ssh工具 openssh: C:\Windows\System32\OpenSSH\ssh.exeGit ssh: C:\Program Files\Git\usr\bin\ssh.exe vscode安装插件remote-ssh 重开软件&#xff0c;在左侧拓展入口下方&#xff0c;进入远程资源管理器 点击设置&#xff0c;进…

第二章Maven的使用

文章目录 Maven核心概念坐标Maven实战创建Java项目实战命令行创建一个Maven版的初始化Java项目实战Maven中编写代码实战执行 Maven 的构建命令 Maven核心概念&#xff1a;约定的目录结构各个目录的作用约定目录结构的意义约定大于配置 Maven实战创建 Maven 版的 Web 工程实战命…

装了固态硬盘Win10开机很慢的解决方法

在Win10电脑中&#xff0c;用户反映自己装了固态硬盘后&#xff0c;电脑开机变得很慢&#xff0c;想知道解决此问题的方法。接下来小编给大家详细介绍关于解决装了固态硬盘Win10电脑开机很慢的问题&#xff0c;解决后Win10电脑开机速度就能变得更快。 装了固态硬盘Win10开机很慢…

OpenCV #以图搜图:均值哈希算法(Average Hash Algorithm)原理与实验

1. 介绍 均值哈希算法&#xff08;Average Hash Algorithm&#xff09; 是哈希算法的一种&#xff0c;主要用来做相似图片的搜索工作。 2. 原理 均值哈希算法&#xff08;aHash&#xff09;首先将原图像缩小成一个固定大小的像素图像&#xff0c;然后将图像转换为灰度图像&am…

何为自制力?如何提高自制力?

什么是自制力&#xff1f; 自制力也即是自我控制能力&#xff0c;是一个人如何去抵御外部诱惑力&#xff0c;从而坚持自己的原本计划&#xff0c;坚定去完成目标。除了外部诱惑力&#xff0c;也可以指的是面对困境&#xff0c;不良情绪等外部因素。 自制力是自我管理能力的体…

Python-股票市场用于算法交易的人类反馈强化学习 (RLHF)

ChatGPT 的成功使人类反馈强化学习 (RLHF) 技术成为人们关注的焦点。RLHF 是一种机器学习方法,它结合了强化学习 (RL) 和人类反馈 (HF) 来改进学习过程。这篇文章将使您对 RLHF 有一个全面的了解。它描述了 RLHF 在算法交易(algo transactions)中的应用,并提供了可执行的 P…

机器学习第一周

一、概述 机器学习大致会被划分为两类&#xff1a;监督学习&#xff0c;无监督学习 1.1 监督学习 监督学习其实就是&#xff0c;给计算机一些输入x和正确的输出y&#xff08;训练数据集&#xff09;&#xff0c;让他总结x->y的映射关系&#xff0c;从而给他其他的输入x&a…

设计模式(五)—— 建造者模式/生成器模式

先简单记一下&#xff0c;以后再来认真写 还是造房子那个例子&#xff0c;一个房子分为①打地基 ② 砌墙 ③封顶三步&#xff0c;如果不用设计模式去写的话。就是一个超类&#xff0c;然后多个子类继承超类去重写 但是这样有两个缺点&#xff1a; &#xff08;1&#xff09;产…

高效技巧揭秘:Java轻松批量插入或删除Excel行列操作

摘要&#xff1a;本文由葡萄城技术团队原创并首发。转载请注明出处&#xff1a;葡萄城官网&#xff0c;葡萄城为开发者提供专业的开发工具、解决方案和服务&#xff0c;赋能开发者。 前言 在职场生活中&#xff0c;对Excel工作表的行和列进行操作是非常普遍的需求。一般情况下…

电脑扬声器未插入?4个方法帮你恢复声音!

“太奇怪了吧&#xff0c;我的电脑扬声器一直显示未插入&#xff0c;我使用电脑的时候也是一直都没有声音。这是为什么呢&#xff1f;我应该怎么解决这个问题呀&#xff1f;” 我们使用电脑播放音频或视频时&#xff0c;都需要用到电脑扬声器。如果扬声器无法播放声音&#xff…

NLP入门——语言结构/语言建模

一、Linguistics 语言学 wordsmorphology 形态学&#xff1a;词的构成和内部结构研究。如英语的dog、dogs和dog-catcher有相当的关系morpheme 语素&#xff1a;最小的语法单位&#xff0c;是最小的音义结合体lexeme 词位&#xff1a;词的意义的基本抽象单位&#xff0c;是一组…

基于机器视觉的手势检测和识别算法 计算机竞赛

0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 基于深度学习的手势检测与识别算法 该项目较为新颖&#xff0c;适合作为竞赛课题方向&#xff0c;学长非常推荐&#xff01; &#x1f9ff; 更多资料, 项目分享&#xff1a; https://gitee.com/dancheng…

低代码软件的价格考量:成本效益与投资回报

数字化转型的今天&#xff0c;我们常听到“低代码”这个概念&#xff0c;那低代码软件价格到底如何呢&#xff1f;很多厂商并没有公布软件价格情况&#xff0c;让很多企业在采购的时候也是一头雾水。当然&#xff0c;市场上也存在一些厂商公开透明价格&#xff0c;比如Zoho Cre…

STM32 HAL库串口使用printf

STM32 HAL库串口使用printf 背景配置说明在usart.h中添加在usart.c中添加在工程中选中微库&#xff1a; 测试 背景 在我们使用CubeMX生成好STM32 HAL库工程之后&#xff0c;我们想使用printf函数来打印一些信息&#xff0c;配置如下&#xff1a; 配置说明 在usart.h中添加 …

使用了lua-resty-http库进行 爬虫

lua-resty-http是一个基于OpenResty的HTTP客户端库&#xff0c;用于在Lua中进行HTTP请求和响应的处理。它提供了简单易用的接口&#xff0c;可以方便地进行网页抓取和爬虫开发。 使用lua-resty-http进行爬虫&#xff0c;需要先安装OpenResty和lua-resty-http库&#xff0c;并将…

电子学会C/C++编程等级考试2023年05月(三级)真题解析

C/C等级考试&#xff08;1~8级&#xff09;全部真题・点这里 第1题&#xff1a;找和为K的两个元素 在一个长度为n(n < 1000)的整数序列中&#xff0c;判断是否存在某两个元素之和为k。 输入 第一行输入序列的长度n和k&#xff0c;用空格分开。 第二行输入序列中的n个整数&am…

sqoop和flume简单安装配置使用

1. Sqoop 1.1 Sqoop介绍 Sqoop 是一个在结构化数据和 Hadoop 之间进行批量数据迁移的工具 结构化数据可以是MySQL、Oracle等关系型数据库 把关系型数据库的数据导入到 Hadoop 与其相关的系统 把数据从 Hadoop 系统里抽取并导出到关系型数据库里 底层用 MapReduce 实现数据 …

NCP1256ESN65T1G具有多种保护功能 一款低功率离线电流模式PWM控制器

NCP1256ESN65T1G 包括构建几瓦到几十瓦成本高效开关模式电源所需的一切功能。该零件采用微型 TSOP-6 封装&#xff0c;供电范围高达 30 V&#xff0c;具有带抖动的 65 kHz 或 100 kHz 开关电路&#xff0c;在峰值电流模式控制下运行。当辅助侧功率开始降低时&#xff0c;该控制…