STM32入门学习之EXTI外部中断(STM32F030F4P6基于CooCox IDE)

下面的代码,是把PA0当做一个按键口,芯片内部上拉,按键闭合时,IO口被拉低,触发中断。

#include "stm32_lib/inc/stm32f0xx_rcc.h"
#include "stm32_lib/inc/stm32f0xx_exti.h"
#include "stm32_lib/inc/stm32f0xx_gpio.h"
#include "stm32_lib/inc/stm32f0xx_syscfg.h"
#include "stm32_lib/inc/stm32f0xx_misc.h"

int main(void)
{
		//时钟使能
		RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA,ENABLE);
		RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);

		//外部按键GPIO初始华,PA0
		GPIO_InitTypeDef GPIO_InitStructure;
		GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0;
		GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN;
		GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_UP;//上拉
		GPIO_InitStructure.GPIO_Speed=GPIO_Speed_2MHz;
		GPIO_Init(GPIOA,&GPIO_InitStructure);

		//将EXTI0指向PA0
		SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA,EXTI_PinSource0);
		//EXTI0中断线配置
		EXTI_InitTypeDef EXTI_InitStructure;
		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);

		//EXTI0中断向量配置
		NVIC_InitTypeDef NVIC_InitStructure;
		NVIC_InitStructure.NVIC_IRQChannel=EXTI0_1_IRQn;
		NVIC_InitStructure.NVIC_IRQChannelPriority=0x01;
		NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
		NVIC_Init(&NVIC_InitStructure);

		while(1){

		}
}

void EXTI0_1_IRQHandler(void){
	if(EXTI_GetITStatus(EXTI_Line0)!=RESET)
	{
		//中断处理
	}
	//退出中断时注意清除标志位
	EXTI_ClearFlag(EXTI_Line0);
}



先补充概念1,同GPIO、USART、NVIC等一样,我们再使用EXTI是首先要定义一个EXTI_InitTypeDef

我们可通过EXTI的头文件查看,库是怎么定义EXTI_InitTypeDef

typedef struct
{
  uint32_t EXTI_Line;<span style="white-space:pre">			</span>//线               
  EXTIMode_TypeDef EXTI_Mode;       <span style="white-space:pre">	</span>//模式
  EXTITrigger_TypeDef EXTI_Trigger; <span style="white-space:pre">	</span>//触发类型
  FunctionalState EXTI_LineCmd;     <span style="white-space:pre">	</span>//使能
}EXTI_InitTypeDef;

关于EXTI_Line,继续看头文件

#define EXTI_Line0       ((uint32_t)0x00000001)  /*!< External interrupt line 0  */
#define EXTI_Line1       ((uint32_t)0x00000002)  /*!< External interrupt line 1  */
#define EXTI_Line2       ((uint32_t)0x00000004)  /*!< External interrupt line 2  */
#define EXTI_Line3       ((uint32_t)0x00000008)  /*!< External interrupt line 3  */
#define EXTI_Line4       ((uint32_t)0x00000010)  /*!< External interrupt line 4  */
#define EXTI_Line5       ((uint32_t)0x00000020)  /*!< External interrupt line 5  */
#define EXTI_Line6       ((uint32_t)0x00000040)  /*!< External interrupt line 6  */
#define EXTI_Line7       ((uint32_t)0x00000080)  /*!< External interrupt line 7  */
#define EXTI_Line8       ((uint32_t)0x00000100)  /*!< External interrupt line 8  */
#define EXTI_Line9       ((uint32_t)0x00000200)  /*!< External interrupt line 9  */
#define EXTI_Line10      ((uint32_t)0x00000400)  /*!< External interrupt line 10 */
#define EXTI_Line11      ((uint32_t)0x00000800)  /*!< External interrupt line 11 */
#define EXTI_Line12      ((uint32_t)0x00001000)  /*!< External interrupt line 12 */
#define EXTI_Line13      ((uint32_t)0x00002000)  /*!< External interrupt line 13 */
#define EXTI_Line14      ((uint32_t)0x00004000)  /*!< External interrupt line 14 */
#define EXTI_Line15      ((uint32_t)0x00008000)  /*!< External interrupt line 15 */
#define EXTI_Line16      ((uint32_t)0x00010000)  /*!< External interrupt line 16 
                                                      Connected to the PVD Output */
#define EXTI_Line17      ((uint32_t)0x00020000)  /*!< Internal interrupt line 17 
                                                      Connected to the RTC Alarm 
                                                      event */
#define EXTI_Line19      ((uint32_t)0x00080000)  /*!< Internal interrupt line 19
                                                      Connected to the RTC Tamper
                                                      and Time Stamp events */
#define EXTI_Line21      ((uint32_t)0x00200000)  /*!< Internal interrupt line 21
                                                      Connected to the Comparator 1
                                                      event */
#define EXTI_Line22      ((uint32_t)0x00400000)  /*!< Internal interrupt line 22
                                                      Connected to the Comparator 2
                                                      event */
#define EXTI_Line23      ((uint32_t)0x00800000)  /*!< Internal interrupt line 23
                                                      Connected to the I2C1 wakeup
                                                      event */
#define EXTI_Line25      ((uint32_t)0x02000000)  /*!< Internal interrupt line 25
                                                      Connected to the USART1 wakeup
                                                      event */
#define EXTI_Line27      ((uint32_t)0x08000000)  /*!< Internal interrupt line 27
                                                      Connected to the CEC wakeup
                                                      event */

这里定义了N多EXTI_Line,其中Line0-Line15表示GPIOX_Pin_N的中断。如何区分GPIOX呢?这也就是概念2要补充的了。这里通过SYSCFG_EXTILineConfig函数来配置。

//将EXTI0指向PA0
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA,EXTI_PinSource0);

继续看头文件,了解EXTI的MODE


typedef enum
{
  EXTI_Mode_Interrupt = 0x00,
  EXTI_Mode_Event = 0x04
}EXTIMode_TypeDef;

一个是Interrupt中断,一个是Event事件。

中断,系统最多只能给其配置个中断向量入口,然后执行相应的软件程序。

而事件,系统中存在硬件电路,可配置其连接至需要触发硬件电路中,如触发AD转换,或者引起DMA操作等。


关于EXTITrigger_TypeDef,经常使用示波器的朋友们想必已经很清楚了,上升沿触发、下降沿触发、上升下降兼触发。

typedef enum
{
  EXTI_Trigger_Rising = 0x08,
  EXTI_Trigger_Falling = 0x0C,
  EXTI_Trigger_Rising_Falling = 0x10
}EXTITrigger_TypeDef;


NVIC中的IRQChannel为什么是EXTI0_1_IRQN呢?

这个可以再stm32f0xx.h头文件找到

EXTI0_1_IRQn对应线0和1的中断

EXTI2_3_IRQn对应线2和3的中断

EXTI4_15_IRQn对应线4-15的中断

#if defined (STM32F0XX_MD) || defined (STM32F030X8)
/******  STM32F0XX_MD and STM32F030X8 specific Interrupt Numbers *************************************/
  WWDG_IRQn                   = 0,      /*!< Window WatchDog Interrupt                               */
  PVD_IRQn                    = 1,      /*!< PVD through EXTI Line detect Interrupt                  */
  RTC_IRQn                    = 2,      /*!< RTC through EXTI Line Interrupt                         */
  FLASH_IRQn                  = 3,      /*!< FLASH Interrupt                                         */
  RCC_IRQn                    = 4,      /*!< RCC Interrupt                                           */
  EXTI0_1_IRQn                = 5,      /*!< EXTI Line 0 and 1 Interrupts                            */
  EXTI2_3_IRQn                = 6,      /*!< EXTI Line 2 and 3 Interrupts                            */
  EXTI4_15_IRQn               = 7,      /*!< EXTI Line 4 to 15 Interrupts  

好了,问题来了,居然EXTI0_1_IRQn包含两个中断,那怎么区分呢?

if(EXTI_GetITStatus(EXTI_Line0)!=RESET)

这下应该知道中断函数里为什么加这句的原因了吧。

猜你喜欢

转载自blog.csdn.net/mrlixirong/article/details/49833541