STM32学习记录——中断和事件

STM32学习记录——中断和事件

最近比较懒惰,突然有人让详述一下中断是什么,脑中又闪出那个解释:中断就是你在做某件事,突然被打断了要去做更重要的事,做完更重要的事之后再回来继续把被打断的事做完;
在学习单片机的时候,中断是一个必须要理解的知识点,在CPU执行程序时,发生了某种内部或者外部的随机事件(中断源),引起CPU暂时中断正在运行的程序,转去执行中断服务子程序或中断处理程序来处理发生的随机事件,处理完后又返回被中断的程序继续执行原来被中断的程序,这一过程就是中断;
STM32学习记录——中断和事件_第1张图片

关于中断向量表,下面深色的地方属于内核异常,内核异常不能被打断,优先级无法设置,其他的浅色部分都是外部中断,外部中断又有两种优先级:抢占优先级(父优先级/主优先级)和响应优先级(子优先级/次优先级 ):
1.抢占优先级高的能够打断低优先级的任务优先执行,甚至嵌套的打断;
2.响应优先级则在执行的时候不能被下一个响应优先级更高的任务打断;STM32学习记录——中断和事件_第2张图片
STM32学习记录——中断和事件_第3张图片
STM32学习记录——中断和事件_第4张图片

嵌套向量中断控制器——NVIC
NVIC几乎负责所有的中断,十分重要
首先有一个结构体:NVIC_InitTypeDef;配置这个结构体有一个专门的函数NVIC_Init(),只需要知道结构体里的成员具体是谁再去配置,最后再调用该函数即可,这些都是STM32的套路。
STM32学习记录——中断和事件_第5张图片
除此之外,还要注意的是NVIC只能配置16种中断优先级,其抢占优先级和响应优先级都是用一个4位的数字表示,上图中也有说明,只要找到了NVIC_InitTypeDef这个结构体,就会有对应的分配方式说明,我们只需要根据实际需求来配置即可。
这个分配接口函数是:
NVIC_PriorityGroupConfig();

STM32学习记录——中断和事件_第6张图片
关于配置GPIO的中断大概只需要三步即可
1.中断线的配置
2.对应GPIO引脚的配置
3.中断函数中添加中断里要做的事(中断里要实现什么功能,代码尽量越少越短越好)
下面通过我之前的按键控制灯状态切换的代码来展示:

//外部中断0服务程序  控制PA0按一次亮,再按一次灭
void EXTI0_IRQHandler(void)
{
	//使能APB2的GPIOA0
	*(volatile unsigned int *)0x40021000 |= 1<<2;
	
	*(volatile unsigned int *)0x40010800 &= ~(1<<0);
	*(volatile unsigned int *)0x40010800 &= ~(1<<2);
	*(volatile unsigned int *)0x40010800 |= (0x02<<2);//上拉下拉
	*(volatile unsigned int *)0x40010810 |= 1<<0;
	
	delay_ms(10);	//消抖
	if(1 == ( *(volatile unsigned int*)0x40010808 & (1<<0)))	//WK_UP按键 
	{
		LED0=!LED0;	
	}		 
	*(volatile unsigned int *)0x40010414=1<<0;  //清除LINE0上的中断标志位  
}

#define KEY1_INT_GPIO_PORT GPIOA


void NVIC_Configuration(void)
{
  NVIC_InitTypeDef NVIC_InitStructure;
  
  /* 配置NVIC为优先级组1 */
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
  
  /* 配置中断源:按键1 */
  NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;  //配置为EXTI0通道
  /* 配置抢占优先级 */
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
  /* 配置子优先级 */
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
  /* 使能中断通道 */
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure); //将上述配置参数传入中断初始化函数
}

void EXTI_Key_Config(void)
{
    GPIO_InitTypeDef GPIO_InitStructure; 
    EXTI_InitTypeDef EXTI_InitStructure;

    /*开启按键GPIO口的时钟*/
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO,ENABLE);
                                                
    /* 配置 NVIC 中断*/
    NVIC_Configuration();
/*--------------------------KEY1配置-----------------------------*/
    /* 选择按键用到的GPIO */   
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
  /* 配置为浮空输入 */ 
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  GPIO_Init(KEY1_INT_GPIO_PORT, &GPIO_InitStructure);

    /* 选择EXTI的信号源 */
  GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0); 
  EXTI_InitStructure.EXTI_Line = EXTI_Line0;
    
    /* EXTI为中断模式 */
  EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
    /* 上升沿中断 */
  EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
  /* 使能中断 */    
  EXTI_InitStructure.EXTI_LineCmd = ENABLE;
  EXTI_Init(&EXTI_InitStructure);
}

除了上面说的,我们还需要知道的是这个中断函数的名称必须是在标准库里的,这个名称在startup_stm32f10x_hd.s或者startup_stm32f10x_md.s文件里面(这个取决于你的单片机的容量)
STM32学习记录——中断和事件_第7张图片
结合上图和前面的代码就可以知道EXTI0_IRQHandler 就是中断线0的中断函数
以上就是STM32中断和事件部分的理解和配置了,这期间或许理解还不到位或者还没见识到更高级的处理,需要大家多多指出和相互交流,本文不足之处希望大家多多指出,非常感谢。

你可能感兴趣的:(STM32学习)