[STM32F4] STM32F401的外部中断EXTI

[复制链接]
1253|18
 楼主| yellow555 发表于 2023-11-23 23:08 | 显示全部楼层 |阅读模式
stm32f401 EXTI
EXTI就是External interrupt/event controller, 外部事件和中断控制器, 包含21条边沿检测线. 每条线可以独立设置触发事件(上升沿, 下降沿或两者同时). 一个等待寄存器维护中断请求的状态.

当动作发生(例如按键按下)时, 如果电平状态由低变高, 会在输入线产生一个上升沿信号, 这个信号到达边沿检测电路后, 会被上升沿触发选择寄存器(EXTI_RTSR)检测并触发, 输出有效信号, 否则输出无效信号0. 反之如果电平由高变低, 则会被下降沿触发选择寄存器(EXTI_FTSR)检测触发.

EXTI可以在外部连线上检测到比内部APB2时钟周期更短的脉冲. stm32f4系列最多有81个GPIO可以连接到16个外部中断线. IO口和中断线的映射是多对一的, 例如EXTI0, 可以对应PA0, PB0, PC0等, 实际用到某个I/O引脚时, 通过配置决定具体哪个引脚对应EXTI0.

 楼主| yellow555 发表于 2023-11-23 23:09 | 显示全部楼层
在stm32f4xx_exti.h中定义了0 - 23的中断线

  1. #define EXTI_Line0       ((uint32_t)0x00001)     /*!< External interrupt line 0 */
  2. #define EXTI_Line1       ((uint32_t)0x00002)     /*!< External interrupt line 1 */
  3. #define EXTI_Line2       ((uint32_t)0x00004)     /*!< External interrupt line 2 */
  4. #define EXTI_Line3       ((uint32_t)0x00008)     /*!< External interrupt line 3 */
  5. #define EXTI_Line4       ((uint32_t)0x00010)     /*!< External interrupt line 4 */
  6. #define EXTI_Line5       ((uint32_t)0x00020)     /*!< External interrupt line 5 */
  7. #define EXTI_Line6       ((uint32_t)0x00040)     /*!< External interrupt line 6 */
  8. #define EXTI_Line7       ((uint32_t)0x00080)     /*!< External interrupt line 7 */
  9. #define EXTI_Line8       ((uint32_t)0x00100)     /*!< External interrupt line 8 */
  10. #define EXTI_Line9       ((uint32_t)0x00200)     /*!< External interrupt line 9 */
  11. #define EXTI_Line10      ((uint32_t)0x00400)     /*!< External interrupt line 10 */
  12. #define EXTI_Line11      ((uint32_t)0x00800)     /*!< External interrupt line 11 */
  13. #define EXTI_Line12      ((uint32_t)0x01000)     /*!< External interrupt line 12 */
  14. #define EXTI_Line13      ((uint32_t)0x02000)     /*!< External interrupt line 13 */
  15. #define EXTI_Line14      ((uint32_t)0x04000)     /*!< External interrupt line 14 */
  16. #define EXTI_Line15      ((uint32_t)0x08000)     /*!< External interrupt line 15 */
  17. #define EXTI_Line16      ((uint32_t)0x10000)     /*!< External interrupt line 16 Connected to the PVD Output */
  18. #define EXTI_Line17      ((uint32_t)0x20000)     /*!< External interrupt line 17 Connected to the RTC Alarm event */
  19. #define EXTI_Line18      ((uint32_t)0x40000)     /*!< External interrupt line 18 Connected to the USB OTG FS Wakeup from suspend event */                                    
  20. #define EXTI_Line19      ((uint32_t)0x80000)     /*!< External interrupt line 19 Connected to the Ethernet Wakeup event */
  21. #define EXTI_Line20      ((uint32_t)0x00100000)  /*!< External interrupt line 20 Connected to the USB OTG HS (configured in FS) Wakeup event  */
  22. #define EXTI_Line21      ((uint32_t)0x00200000)  /*!< External interrupt line 21 Connected to the RTC Tamper and Time Stamp events */                                               
  23. #define EXTI_Line22      ((uint32_t)0x00400000)  /*!< External interrupt line 22 Connected to the RTC Wakeup event */
  24. #define EXTI_Line23      ((uint32_t)0x00800000)  /*!< External interrupt line 23 Connected to the LPTIM Wakeup event */
 楼主| yellow555 发表于 2023-11-23 23:09 | 显示全部楼层
在stm32f4xx.h中, 有这些中断的常量, 注意: Line虽然是各自独立的, 但是IRQn不是, Handler也不是
 楼主| yellow555 发表于 2023-11-23 23:10 | 显示全部楼层
  1. EXTI0_IRQn                  = 6,      /*!< EXTI Line0 Interrupt                                              */
  2.   EXTI1_IRQn                  = 7,      /*!< EXTI Line1 Interrupt                                              */
  3.   EXTI2_IRQn                  = 8,      /*!< EXTI Line2 Interrupt                                              */
  4.   EXTI3_IRQn                  = 9,      /*!< EXTI Line3 Interrupt                                              */
  5.   EXTI4_IRQn                  = 10,     /*!< EXTI Line4 Interrupt                                              */
  6.   EXTI9_5_IRQn                = 23,     /*!< External Line[9:5] Interrupts                                     */
  7.   EXTI15_10_IRQn              = 40,     /*!< External Line[15:10] Interrupts                                   */
 楼主| yellow555 发表于 2023-11-23 23:11 | 显示全部楼层
可以看到, 对于EXTI0到EXTI4(Line0到Line4), 都是单独的常量, 而Line5到Line9, Line10到Line15都是合用的.
对应的, 有以下的中断处理方法, 通过这些方法将自己的中断逻辑关联到对应的中断事件上去

  1. EXTI0_IRQHandler
  2. EXTI1_IRQHandler
  3. EXTI2_IRQHandler
  4. EXTI3_IRQHandler
  5. EXTI4_IRQHandler
  6. EXTI9_5_IRQHandler
  7. EXTI15_10_IRQHandler
 楼主| yellow555 发表于 2023-11-23 23:11 | 显示全部楼层
初始化的步骤

  1. ##### How to use this driver #####
  2. ==================================================

  3. [..] In order to use an I/O pin as an external interrupt source, follow steps
  4.       below:
  5.    (#) Configure the I/O in input mode using GPIO_Init()
  6.    (#) Select the input source pin for the EXTI line using SYSCFG_EXTILineConfig()
  7.    (#) Select the mode(interrupt, event) and configure the trigger
  8.        selection (Rising, falling or both) using EXTI_Init()
  9.    (#) Configure NVIC IRQ channel mapped to the EXTI line using NVIC_Init()

  10. [..]     
  11.    (@) SYSCFG APB clock must be enabled to get write access to SYSCFG_EXTICRx
  12.        registers using RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
 楼主| yellow555 发表于 2023-11-23 23:11 | 显示全部楼层
使能I/O口时钟, 初始化I/O口为输入
 楼主| yellow555 发表于 2023-11-23 23:11 | 显示全部楼层
使能SYSCFG时钟, 设置I/O口与中断线的映射关系
 楼主| yellow555 发表于 2023-11-23 23:11 | 显示全部楼层
初始化中断线(EXTI线编号, 中断模式是中断还是事件, 触发方式是下降沿触发、上升沿触发还是任意电平触发, 是否使能中断线)
 楼主| yellow555 发表于 2023-11-23 23:12 | 显示全部楼层
配置嵌套中断向量控制器NVIC
 楼主| yellow555 发表于 2023-11-23 23:12 | 显示全部楼层
编写中断服务函数 对应各个中断线分别有EXTI0_IRQHandler(), EXTI1_IRQHandler(), ... EXTI9_5_IRQHandler(), EXTI15_10_IRQHandler().
 楼主| yellow555 发表于 2023-11-23 23:12 | 显示全部楼层
官方的代码例子
This example shows how to configure external interrupt lines.
 楼主| yellow555 发表于 2023-11-23 23:12 | 显示全部楼层
In this example, 2 EXTI lines (EXTI Line0 and Line15) are configured to generate an interrupt on each rising and falling edge, respectively.
 楼主| yellow555 发表于 2023-11-23 23:12 | 显示全部楼层
In the interrupt routine a LED connected to a specific GPIO pin is toggled.
 楼主| yellow555 发表于 2023-11-23 23:12 | 显示全部楼层
  1. static void EXTILine0_Config(void);
  2. static void EXTILine13_15_Config(void);

  3. /* Private functions ---------------------------------------------------------*/

  4. /**
  5.   * [url=home.php?mod=space&uid=247401]@brief[/url]  Main program
  6.   * @param  None
  7.   * @retval None
  8.   */
  9. int main(void)
  10. {
  11.   /* Initialize LEDs mounted on EVAL board */
  12.   STM_EVAL_LEDInit(LED1);
  13.   STM_EVAL_LEDInit(LED2);

  14.   /* Configure EXTI Line0 (connected to PA0 pin) in interrupt mode */
  15.   EXTILine0_Config();

  16.   /* Configure EXTI Line13/15 (connected to PG13/15 pin) in interrupt mode
  17.      according to EVAL used */
  18.   EXTILine13_15_Config();

  19.   /* Generate software interrupt: simulate a falling edge applied on EXTI0 line */
  20.   EXTI_GenerateSWInterrupt(EXTI_Line0);

  21.   while (1)
  22.   {
  23.   }
  24. }

  25. /**
  26.   * @brief  Configures EXTI Line0 (connected to PA0 pin) in interrupt mode
  27.   * @param  None
  28.   * @retval None
  29.   */
  30. static void EXTILine0_Config(void)
  31. {
  32.   EXTI_InitTypeDef   EXTI_InitStructure;
  33.   GPIO_InitTypeDef   GPIO_InitStructure;
  34.   NVIC_InitTypeDef   NVIC_InitStructure;

  35.   /* Enable GPIOA clock */
  36.   RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
  37.   /* Enable SYSCFG clock */
  38.   RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
  39.   
  40.   /* Configure PA0 pin as input floating */
  41.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
  42.   GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
  43.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
  44.   GPIO_Init(GPIOA, &GPIO_InitStructure);

  45.   /* Connect EXTI Line0 to PA0 pin */
  46.   SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA, EXTI_PinSource0);

  47.   /* Configure EXTI Line0 */
  48.   EXTI_InitStructure.EXTI_Line = EXTI_Line0;
  49.   EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
  50.   EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;  
  51.   EXTI_InitStructure.EXTI_LineCmd = ENABLE;
  52.   EXTI_Init(&EXTI_InitStructure);

  53.   /* Enable and set EXTI Line0 Interrupt to the lowest priority */
  54.   NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;
  55.   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x0F;
  56.   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x0F;
  57.   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  58.   NVIC_Init(&NVIC_InitStructure);
  59. }

  60. /**
  61.   * @brief  Configures EXTI Line15 (connected to PG15 pin) in interrupt mode
  62.   * @param  None
  63.   * @retval None
  64.   */
  65. static void EXTILine13_15_Config(void)
  66. {
  67.   EXTI_InitTypeDef   EXTI_InitStructure;
  68.   GPIO_InitTypeDef   GPIO_InitStructure;
  69.   NVIC_InitTypeDef   NVIC_InitStructure;

  70. #ifdef USE_STM324x9I_EVAL
  71.   /* Enable GPIOC clock */
  72.   RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
  73. #else  
  74.   /* Enable GPIOG clock */
  75.   RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOG, ENABLE);
  76. #endif /* USE_STM324x9I_EVAL */
  77.   
  78.   /* Enable SYSCFG clock */
  79.   RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
  80.   
  81.   /* Configure PG15 pin as input floating */
  82.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
  83.   GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
  84. #ifdef USE_STM324x9I_EVAL
  85.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
  86.   GPIO_Init(GPIOC, &GPIO_InitStructure);
  87. #else
  88.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;
  89.   GPIO_Init(GPIOG, &GPIO_InitStructure);
  90. #endif /* USE_STM324x9I_EVAL */  

  91.   /* Connect EXTI Line15 to PG15 pin */
  92. #ifdef USE_STM324x9I_EVAL  
  93.   SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOC, EXTI_PinSource13);
  94. #else  
  95.   SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOG, EXTI_PinSource15);
  96. #endif /* USE_STM324x9I_EVAL */  

  97.   /* Configure EXTI Line15 */
  98. #ifdef USE_STM324x9I_EVAL  
  99.   EXTI_InitStructure.EXTI_Line = EXTI_Line13;
  100. #else  
  101.   EXTI_InitStructure.EXTI_Line = EXTI_Line15;
  102. #endif /* USE_STM324x9I_EVAL */  

  103.   EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
  104.   EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
  105.   EXTI_InitStructure.EXTI_LineCmd = ENABLE;
  106.   EXTI_Init(&EXTI_InitStructure);

  107.   /* Enable and set EXTI15_10 Interrupt to the lowest priority */
  108.   NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;
  109.   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x0F;
  110.   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x0F;
  111.   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

  112.   NVIC_Init(&NVIC_InitStructure);
  113. }
 楼主| yellow555 发表于 2023-11-23 23:12 | 显示全部楼层
处理中断的例子
中断处理, 涉及的就是三步: 1)消抖(如果是按键触发), 2)确认中断源, 3)清除中断标志位
 楼主| yellow555 发表于 2023-11-23 23:13 | 显示全部楼层
  1. // 1
  2. void EXTI4_IRQHandler( void )
  3. {
  4.   delay_ms( 10 ); /* 消抖 */
  5.   if ( GPIO_ReadInputDataBit( GPIOE, GPIO_Pin_4 ) == 0 ) {
  6.     GPIO_ResetBits(GPIOF,GPIO_Pin_9);//输出低电平,灯亮
  7.   }
  8.   /* 清除LINE4上的中断标志位 */
  9.   EXTI_ClearITPendingBit( EXTI_Line4 );
  10. }

  11. // 2
  12. void EXTI0_IRQHandler(void)
  13. {
  14.   if(EXTI_GetITStatus(EXTI_Line0) != RESET) {} // 确保产生了EXTI0线中断
  15.     LED_TOGGLE; // LED灯状态切换
  16.     EXTI_ClearITPendingBit(EXTI_Line0);// 清除中断标志位
  17.   }
  18. }

  19. // 3
  20. /* Set interrupt handlers */
  21. /* Handle PB12 interrupt */
  22. void EXTI15_10_IRQHandler(void) {
  23.   /* Make sure that interrupt flag is set */
  24.   if (EXTI_GetITStatus(EXTI_Line12) != RESET) {
  25.     /* Do your stuff when PB12 is changed */
  26.    
  27.    
  28.     /* Clear interrupt flag */
  29.     EXTI_ClearITPendingBit(EXTI_Line12);
  30.   }
  31. }
EmmaTT 发表于 2024-4-8 14:22 来自手机 | 显示全部楼层
消抖怎么少的占用资源啊
Pulitzer 发表于 2024-7-16 07:30 | 显示全部楼层

在信号线中串联小电阻其主要目的是对引脚的保护
童雨竹 发表于 2024-7-16 09:26 | 显示全部楼层

驱动脉冲变压器原边时,
您需要登录后才可以回帖 登录 | 注册

本版积分规则

40

主题

469

帖子

3

粉丝
快速回复 在线客服 返回列表 返回顶部