stm32专题七:EXTI(一)外部中断/事件控制器框图

       stm32的每一个GPIO都可以产生中断,这些中断由EXTI这个外设管理。EXTI读取GPIO引脚的电平变化,然后交给NVIC。

外部中断EXTI的结构框图,标号20表示类似的信号线路有20根

stm32专题七:EXTI(一)外部中断/事件控制器框图_第1张图片

       共有20根输入线,其中EXTI0~EXTI15为GPIO引脚,每个GPIO的相同Pin(如Pin0)都接在一起,结构如下

stm32专题七:EXTI(一)外部中断/事件控制器框图_第2张图片

       总结如下

stm32专题七:EXTI(一)外部中断/事件控制器框图_第3张图片

       这些输入线由寄存器AFIO_EXTICR(外部中断配置寄存器)来控制,其中AFIO_EXTICR0管理EXTI0~EXTI3,AFIO_EXTICR1管理EXTI4~EXTI7,依此类推。

stm32专题七:EXTI(一)外部中断/事件控制器框图_第4张图片

       外部中断的检测过程:

       当检测到上升沿/下降沿时,如果我们设置了软件中断事件寄存器EXTI_WSIER,则会将挂起寄存器EXTI_PR的相应位置1。两个均为1(边沿检测和软件中断事件寄存器),则或门电路的输出为1。此时若设置中断屏蔽寄存器为1(开放中断请求),则与门电路的输出为1,中断请求进入到NVIC。

stm32专题七:EXTI(一)外部中断/事件控制器框图_第5张图片

       事件模式:

       当设置事件屏蔽寄存器开放事件请求时,下半部分电路与门的输出为1,然后脉冲发生器就会产生一个脉冲。这个脉冲是在单片机的内部,可以触发ADC开始转换,还可以触发定时器开始计时。

标准库中的EXTI初始化结构体

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 */
   
// EXTI模式,事件或中断  
EXTIMode_TypeDef EXTI_Mode;       /*!< Specifies the mode for the EXTI lines.
                                         This parameter can be a value of @ref EXTIMode_TypeDef */

// EXTI触发方式,上升沿或下降沿或上升下降沿都检测  
EXTITrigger_TypeDef EXTI_Trigger; /*!< Specifies the trigger signal active edge for the EXTI lines.
                                         This parameter can be a value of @ref EXTIMode_TypeDef */

// EXTI输入线使能  
FunctionalState EXTI_LineCmd;     /*!< Specifies the new state of the selected EXTI lines.
                                         This parameter can be set either to ENABLE or DISABLE */ 
}EXTI_InitTypeDef;

       下面是EXTI初始化函数,其实就是往EXTI寄存器的对应位写1,很简单

/**
  * @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输入线的中断和事件屏蔽寄存器
    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保存的是EXTI的基地址
      tmp = (uint32_t)EXTI_BASE;
      // tmp指向EXTI的边沿触发寄存器
      tmp += EXTI_InitStruct->EXTI_Trigger;

      // 对该地址取值(指针操作),往对应的位写1
      *(__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;
  }
}

       选择输入线对应的GPIO,操作的是AFIO_EXTICR寄存器,源码如下,其实也很简单,就是根据端口GPIO_PORT和GPIO_PIN设置AFIO->EXTICR寄存器,要养成多看源码的习惯。

/**
  * @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)));
}

 

你可能感兴趣的:(stm32专栏)