STM32库函数 外部中断(或事件)部分代码细究

STM32库函数 外部中断(或事件)部分代码细究

一、外部中断相关函数

外部中断部分相对简单,库函数也相对较少,以下,根据函数名字基本可以看出其作用。

void EXTI_DeInit(void);
void EXTI_Init(EXTI_InitTypeDef* EXTI_InitStruct);
void EXTI_StructInit(EXTI_InitTypeDef* EXTI_InitStruct);
void EXTI_GenerateSWInterrupt(uint32_t EXTI_Line);
FlagStatus EXTI_GetFlagStatus(uint32_t EXTI_Line);
void EXTI_ClearFlag(uint32_t EXTI_Line);
ITStatus EXTI_GetITStatus(uint32_t EXTI_Line);
void EXTI_ClearITPendingBit(uint32_t EXTI_Line);

二、ST外部中断知识

对于互联型产品,外部中断/事件控制器由20个产生事件/中断请求的边沿检测器组成,对于其它
产品,则有19个能产生事件/中断请求的边沿检测器。每个输入线可以独立地配置输入类型(脉冲
或挂起)和对应的触发事件(上升沿或下降沿或者双边沿都触发)。每个输入线都可以独立地被屏
蔽。挂起寄存器保持着状态线的中断请求。

EXTI控制器的主要特性如下:
● 每个中断/事件都有独立的触发和屏蔽
● 每个中断线都有专用的状态位
● 支持多达20个软件的中断/事件请求
● 检测脉冲宽度低于APB2时钟宽度的外部信号。

外部中断/事件控制器框图, 如下所示
STM32库函数 外部中断(或事件)部分代码细究_第1张图片中断屏蔽寄存器(EXTI_IMR)
0:屏蔽
1:开放

STM32库函数 外部中断(或事件)部分代码细究_第2张图片
事件屏蔽寄存器(EXTI_EMR)
0:屏蔽
1:开放

STM32库函数 外部中断(或事件)部分代码细究_第3张图片上升沿触发选择寄存器(EXTI_RTSR)
0:禁止上升沿触发
1:允许上升沿触发

STM32库函数 外部中断(或事件)部分代码细究_第4张图片
下降沿触发选择寄存器(EXTI_FTSR)
0:禁止下降沿触发
1:允许下降沿触发

STM32库函数 外部中断(或事件)部分代码细究_第5张图片软件中断事件寄存器(EXTI_SWIER)
STM32库函数 外部中断(或事件)部分代码细究_第6张图片挂起寄存器(EXTI_PR)
0:没有中断产生
1:有中断产生

STM32库函数 外部中断(或事件)部分代码细究_第7张图片

外部中断通用I/O映像
STM32库函数 外部中断(或事件)部分代码细究_第8张图片
● EXTI线16连接到PVD输出
● EXTI线17连接到RTC闹钟事件
● EXTI线18连接到USB唤醒事件
● EXTI线19连接到以太网唤醒事件(只适用于互联型产品)

外部中断/事件寄存器映像
STM32库函数 外部中断(或事件)部分代码细究_第9张图片

三、示例代码1

中断初始化函数

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;
  }
}

EXTI_InitTypeDef
STM32库函数 外部中断(或事件)部分代码细究_第10张图片
EXTI_Line
STM32库函数 外部中断(或事件)部分代码细究_第11张图片EXTI_Mode
STM32库函数 外部中断(或事件)部分代码细究_第12张图片EXTI_Trigger
STM32库函数 外部中断(或事件)部分代码细究_第13张图片EXTI_LineCmd
STM32库函数 外部中断(或事件)部分代码细究_第14张图片初始化示例

	EXTI_InitTypeDef EXTI_InitStructure;   //EXTI_InitStructure 结构体定义
 
	EXTI_InitStructure.EXTI_Line = EXTI_Line3;  // 中断线3
	EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; //中断模式
	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; //上升沿触发
	EXTI_InitStructure.EXTI_LineCmd = ENABLE;   //中断线使能
	//以上理解为:依次为EXTI_InitStructure 结构体中的成员赋值
	EXTI_Init(&EXTI_InitStructure);   //调用中断初始化函数 (参数:结构体指针)

四、示例代码2

获取中断标志位

ITStatus EXTI_GetITStatus(uint32_t EXTI_Line)
{
     
  ITStatus bitstatus = RESET;
  uint32_t enablestatus = 0;
  /* Check the parameters */
  assert_param(IS_GET_EXTI_LINE(EXTI_Line));
  
  enablestatus =  EXTI->IMR & EXTI_Line;  //检查中断是否被屏蔽,即中断是否使能:0屏蔽,1:开放。
  if (((EXTI->PR & EXTI_Line) != (uint32_t)RESET) && (enablestatus != (uint32_t)RESET))
  //EXTI->PR & EXTI_Line  中断线上是否产生了中断        
  {
     
    bitstatus = SET;
  }
  else
  {
     
    bitstatus = RESET;
  }
  return bitstatus;
}

清除中断标志位

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

以上两个函数成对使用,用例如下

void EXTI3_IRQHandler(void)
{
     
     if(EXTI_GetITStatus(EXTI_Line3)!=RESET)//判断某个线上的中断是否发生
     {
     
       中断逻辑…
      EXTI_ClearITPendingBit(EXTI_Line3); //清除 LINE 上的中断标志位
     }
}

EXTI_TypeDef
STM32库函数 外部中断(或事件)部分代码细究_第15张图片在这里需要说明一下,
1、固件库还提供了两个函数用来判断外部中断状态以及清除外部状态标志位的函数 EXTI_GetFlagStatus 和 EXTI_ClearFlag,他们的作用和前面两个函数的作用类似。

2、只是在 EXTI_GetITStatus 函数中会先判断这种中断是否使能,使能了才去判断中断标志位,而EXTI_GetFlagStatus 直接用来判断状态标志位。

EXTI_GetFlagStatus

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;
}

五、中断函数

外部中断线有20个,可是中断函数却只有7个,分别是:
1、EXTI0_IRQHandler
2、EXTI1_IRQHandler
3、EXTI2_IRQHandler
4、 EXTI3_IRQHandler
5、EXTI4_IRQHandler
6、EXTI9_5_IRQHandler
7、EXTI15_10_IRQHandler
中断线 0-4 每个中断线对应一个中断函数, 中断线 5-9 共用中断函数 EXTI9_5_IRQHandler,中
断线 10-15 共用中断函数 EXTI15_10_IRQHandler。

1、同一个中断函数中 如何判断是哪个中断线上的中断
在同一个中断处理函数中,有多条中断线时常用到以下两个函数:
1、ITStatus EXTI_GetITStatus(uint32_t EXTI_Line) ;
中断服务函数的开头判断中断是否发生

2、void EXTI_ClearITPendingBit(uint32_t EXTI_Line);
清除某个中断线上的中断标志位

举例:

void EXTI9_5_IRQHandler(void)
{
     
     //中断线5
     if(EXTI_GetITStatus(EXTI_Line5)!=RESET)//判断中断线5上的中断是否发生
     {
     
       中断逻辑…
      EXTI_ClearITPendingBit(EXTI_Line5); //清除 LINE5 上的中断标志位
     }


      //中断线6
     if(EXTI_GetITStatus(EXTI_Line6)!=RESET)//判断中断线6上的中断是否发生
     {
     
       中断逻辑…
      EXTI_ClearITPendingBit(EXTI_Line6); //清除 LINE6 上的中断标志位
     }

        //中断线7
     if(EXTI_GetITStatus(EXTI_Line7)!=RESET)//判断中断线7上的中断是否发生
     {
     
       中断逻辑…
      EXTI_ClearITPendingBit(EXTI_Line7); //清除 LINE7 上的中断标志位
     }
                 .
                 .
                 .
                 .
   
}

2、同一个中断线,可以配置多个中断么?
答案:不可以
以中断线0为例
中断线0 有 A、B、C、D、E、F、G 7个端口,每个端口的0号管脚构成了一条中断线,可以看出来,这是一个多路选择器,7路输入,1路输出,意味着同一时刻这7个管脚只有一个能在中断线0上
STM32库函数 外部中断(或事件)部分代码细究_第16张图片总结:

1.同一pin口不可同时配置外部中断

2.不同pin口可以同时配置外部中断

3.共用中断服务函数,以中断标志位区分

4.外部中断的本质是某中断线得到信号触发,进入对应的中断服务函数的过程。

5.某一路中断线只能同时跟一个pin口搭上

六、中断处理函数应该放在工程文件的什么位置

stm32f10x_it.c 里面是用来编写中断服务函数,但是中断服务函数也可以随意编写在工程
里面的任意一个文件里面。
STM32库函数 外部中断(或事件)部分代码细究_第17张图片

你可能感兴趣的:(STM32)