六、EXTI及中断

发布时间 2024-01-10 01:30:54作者: 7七柒

四、EXIT外部中断

中断系统

  • 中断:在主程序运行过程中,出现了特定的中断触发条件(中断源),使得CPU暂停当前正在运行的程序,转而去处理中断程序,处理完成后又返回原来被暂停的位置继续运行

  • 中断优先级:当有多个中断源同时申请中断时,CPU会根据中断源的轻重缓急进行裁决,优先响应更加紧急的中断源

  • 中断嵌套:当一个中断程序正在运行时,又有新的更高优先级的中断源申请中断,CPU再次暂停当前中断程序,转而去处理新的中断程序,处理完成后依次进行返回

执行流程

image

中断向量表

  • STM32拥有68个可屏蔽中断通道,包含EXTI、TIM、ADC、USART、SPI、I2C、RTC等多个外设

  • 使用NVIC统一管理中断,每个中断通道都拥有16个可编程的优先等级,可对优先级进行分组,进一步设置抢占优先级和响应优先级

灰色部分是Cortex-M3内核里面的中断,非灰色部分是STM32外设的中断

image

image

image

NVIC

NVIC介绍

NVIC的名称叫做嵌套中断向量控制器

用来统一分配中断优先级和管理中断,一共可以分为16个优先级

属于内核外设

NVIC基本结构

image

NVIC优先级分组

  • NVIC的中断优先级由优先级寄存器的4个bit位(0~15)决定,这4个bit位可以进行切分,分为高n位的抢占优先级和低4-n位的响应优先级
  • 抢占优先级高的可以打断其他正在进行的中断,也就是中断嵌套
  • 响应优先级高的可以排在其他中断前面,但是不能打断其他中断程序
  • 抢占优先级和响应优先级均相同的按中断号排队
分组方式 抢占优先级 响应优先级
分组0 0个bit位,取值为0 4个bit位,取值为0~15
分组1 1个bit位,取值为0~1 3个bit位,取值为0~7
分组2 2个bit位,取值为0~3 2个bit位,取值为0~3
分组3 3个bit位,取值为0~7 1个bit位,取值为0~1
分组4 4个bit位,取值为0~15 0个bit位,取值为0

举例:比如选了分组1,那么抢占优先级有1个bit位,只能选01;而响应优先级有3个bit位,就可以选07。注意:值越小,优先级越高。

EXTI

EXTI简介

EXTI(Extern Interrupt)外部中断

EXTI可以监测指定GPIO口的电平信号,当其指定的GPIO口产生电平变化时,EXTI将立即向NVIC发出中断申请,经过NVIC裁决后即可中断CPU主程序,使CPU执行EXTI对应的中断程序

  • 支持的触发方式:上升沿、下降沿、双边沿、软件触发
  • 支持的GPIO口:所有GPIO口,但相同的Pin不能同时触发中断(例如PA1和PB1不能同时触发,PA12和PC12不能同时触发)
  • 通道数:16个GPIO_Pin,外加PVD输出、RTC闹钟、USB唤醒、以太网唤醒
  • 触发响应方式:中断响应、事件响应(响应其他外设。例如触发ADC转换、DMA等)

EXTI基本流程

image

AFIO在中断中的作用

  • AFIO主要用于引脚复用功能的选择和重定义

  • 在STM32中,AFIO主要完成两个任务:复用功能引脚重映射、中断引脚选择

这里要说的就是AFIO的中断引脚选择

他会根据我们的配置从相同的Pin中选一个出来输入EXTI中(从PA0~PG0中选一个引脚输入EXTI0)

image

EXTI框图

image

image

旋转编码器介绍

旋转编码器简介

image

光栅式:第一张图片

使用的硬件是对射红外传感器,对射红外传感器中间被遮挡时发出高电平,没有被遮挡时发出低电平。再通过有孔洞的光栅进行转动,时而被遮挡时而没有被遮挡,就会发出一串方波,我们就可以通过这串方波来判断旋转的速度

机械触点式:第二和第三张图片,第三张为拆解图

当旋转轴旋转时,下面带有金属触点的圆盘也会跟着转动,他能让两侧触点的通断产生一个90度的相位差,可以由此判断旋转方向

机械触点式电路

image

image

AFIO重映射引脚

/**
  * @作用  更改指定引脚的映射。
  * @参数  GPIO_Remap: 选择要重新映射的引脚。
  *   该参数可以是以下值之一:
  *     @arg GPIO_Remap_SPI1             : SPI1 Alternate Function mapping
  *     @arg GPIO_Remap_I2C1             : I2C1 Alternate Function mapping
  *     @arg GPIO_Remap_USART1           : USART1 Alternate Function mapping
  *     @arg GPIO_Remap_USART2           : USART2 Alternate Function mapping
  *     @arg GPIO_PartialRemap_USART3    : USART3 Partial Alternate Function mapping
  *     @arg GPIO_FullRemap_USART3       : USART3 Full Alternate Function mapping
  *     @arg GPIO_PartialRemap_TIM1      : TIM1 Partial Alternate Function mapping
  *     @arg GPIO_FullRemap_TIM1         : TIM1 Full Alternate Function mapping
  *     @arg GPIO_PartialRemap1_TIM2     : TIM2 Partial1 Alternate Function mapping
  *     @arg GPIO_PartialRemap2_TIM2     : TIM2 Partial2 Alternate Function mapping
  *     @arg GPIO_FullRemap_TIM2         : TIM2 Full Alternate Function mapping
  *     @arg GPIO_PartialRemap_TIM3      : TIM3 Partial Alternate Function mapping
  *     @arg GPIO_FullRemap_TIM3         : TIM3 Full Alternate Function mapping
  *     @arg GPIO_Remap_TIM4             : TIM4 Alternate Function mapping
  *     @arg GPIO_Remap1_CAN1            : CAN1 Alternate Function mapping
  *     @arg GPIO_Remap2_CAN1            : CAN1 Alternate Function mapping
  *     @arg GPIO_Remap_PD01             : PD01 Alternate Function mapping
  *     @arg GPIO_Remap_TIM5CH4_LSI      : LSI connected to TIM5 Channel4 input capture for calibration
  *     @arg GPIO_Remap_ADC1_ETRGINJ     : ADC1 External Trigger Injected Conversion remapping
  *     @arg GPIO_Remap_ADC1_ETRGREG     : ADC1 External Trigger Regular Conversion remapping
  *     @arg GPIO_Remap_ADC2_ETRGINJ     : ADC2 External Trigger Injected Conversion remapping
  *     @arg GPIO_Remap_ADC2_ETRGREG     : ADC2 External Trigger Regular Conversion remapping
  *     @arg GPIO_Remap_ETH              : Ethernet remapping (only for Connectivity line devices)
  *     @arg GPIO_Remap_CAN2             : CAN2 remapping (only for Connectivity line devices)
  *     @arg GPIO_Remap_SWJ_NoJTRST      : Full SWJ Enabled (JTAG-DP + SW-DP) but without JTRST
  *     @arg GPIO_Remap_SWJ_JTAGDisable  : JTAG-DP Disabled and SW-DP Enabled
  *     @arg GPIO_Remap_SWJ_Disable      : Full SWJ Disabled (JTAG-DP + SW-DP)
  *     @arg GPIO_Remap_SPI3             : SPI3/I2S3 Alternate Function mapping (only for Connectivity line devices)
  *                                        When the SPI3/I2S3 is remapped using this function, the SWJ is configured
  *                                        to Full SWJ Enabled (JTAG-DP + SW-DP) but without JTRST.   
  *     @arg GPIO_Remap_TIM2ITR1_PTP_SOF : Ethernet PTP output or USB OTG SOF (Start of Frame) connected
  *                                        to TIM2 Internal Trigger 1 for calibration (only for Connectivity line devices)
  *                                        If the GPIO_Remap_TIM2ITR1_PTP_SOF is enabled the TIM2 ITR1 is connected to 
  *                                        Ethernet PTP output. When Reset TIM2 ITR1 is connected to USB OTG SOF output.    
  *     @arg GPIO_Remap_PTP_PPS          : Ethernet MAC PPS_PTS output on PB05 (only for Connectivity line devices)
  *     @arg GPIO_Remap_TIM15            : TIM15 Alternate Function mapping (only for Value line devices)
  *     @arg GPIO_Remap_TIM16            : TIM16 Alternate Function mapping (only for Value line devices)
  *     @arg GPIO_Remap_TIM17            : TIM17 Alternate Function mapping (only for Value line devices)
  *     @arg GPIO_Remap_CEC              : CEC Alternate Function mapping (only for Value line devices)
  *     @arg GPIO_Remap_TIM1_DMA         : TIM1 DMA requests mapping (only for Value line devices)
  *     @arg GPIO_Remap_TIM9             : TIM9 Alternate Function mapping (only for XL-density devices)
  *     @arg GPIO_Remap_TIM10            : TIM10 Alternate Function mapping (only for XL-density devices)
  *     @arg GPIO_Remap_TIM11            : TIM11 Alternate Function mapping (only for XL-density devices)
  *     @arg GPIO_Remap_TIM13            : TIM13 Alternate Function mapping (only for High density Value line and XL-density devices)
  *     @arg GPIO_Remap_TIM14            : TIM14 Alternate Function mapping (only for High density Value line and XL-density devices)
  *     @arg GPIO_Remap_FSMC_NADV        : FSMC_NADV Alternate Function mapping (only for High density Value line and XL-density devices)
  *     @arg GPIO_Remap_TIM67_DAC_DMA    : TIM6/TIM7 and DAC DMA requests remapping (only for High density Value line devices)
  *     @arg GPIO_Remap_TIM12            : TIM12 Alternate Function mapping (only for High density Value line devices)
  *     @arg GPIO_Remap_MISC             : Miscellaneous Remap (DMA2 Channel5 Position and DAC Trigger remapping, 
  *                                        only for High density Value line devices)     
  * @参数  NewState: 端口引脚重新映射的状态。
  *   取值为:ENABLE或DISABLE。
  * @返回值 None
  */
void GPIO_PinRemapConfig(uint32_t GPIO_Remap, FunctionalState NewState)

EXTI相关函数

具体使用在库函数文件夹的:stm32f10x_exti.c/.h文件中

typedef struct
{
  uint32_t EXTI_Line;               /*!< 指定要启用或禁用的EXTI线。*/
  EXTIMode_TypeDef EXTI_Mode;       /*!< 指定EXTI线的模式。 */
  EXTITrigger_TypeDef EXTI_Trigger; /*!< 指定触发EXTI的信号沿 */
  FunctionalState EXTI_LineCmd;     /*!< 指定所选EXTI线的状态。 */ 
}EXTI_InitTypeDef;

// EXTI_Line可选的值
EXTI_Linex:其中x可以为0~19

// EXTI_Mode可选的值
typedef enum
{
  EXTI_Mode_Interrupt = 0x00,			// 中断响应
  EXTI_Mode_Event = 0x04				// 事件响应
}EXTIMode_TypeDef;

// EXTI_Trigger可选的值
typedef enum
{
  EXTI_Trigger_Rising = 0x08,			// 上升沿触发
  EXTI_Trigger_Falling = 0x0C,  		// 下降沿触发
  EXTI_Trigger_Rising_Falling = 0x10	// 上升、下降沿都可以触发
}EXTITrigger_TypeDef;

// EXTI_LineCmd可选的值
ENABLE									// 使能
DISABLE									// 失能
// 将EXTI外设寄存器初始化为其默认重置值。
void EXTI_DeInit(void);

// 根据指定初始化EXTI外设
void EXTI_Init(EXTI_InitTypeDef* EXTI_InitStruct);

// 用重置值填充每个EXTI_InitStruct成员。
void EXTI_StructInit(EXTI_InitTypeDef* EXTI_InitStruct);

// 产生一个软件中断。
void EXTI_GenerateSWInterrupt(uint32_t EXTI_Line);

// 检查是否设置了指定的EXTI行标志。主函数中检测指定的EXTI通道是否触发中断
FlagStatus EXTI_GetFlagStatus(uint32_t EXTI_Line);

// 清除EXTI的行挂起标志。主函数中清除指定的EXTI通道的中断标志位
void EXTI_ClearFlag(uint32_t EXTI_Line);

// 检查指定的EXTI中断线路是否触发中断。中断函数中检测指定的EXTI通道是否触发中断
ITStatus EXTI_GetITStatus(uint32_t EXTI_Line);

// 清除EXTI的行挂起位。中断函数中清除指定的EXTI通道的中断标志位
void EXTI_ClearITPendingBit(uint32_t EXTI_Line);

NVIC相关函数

具体使用在库函数文件夹的:misc.c/.h文件中

NVIC_PriorityGroupConfig填入typedef struct
{
  uint8_t NVIC_IRQChannel;                    /*!< 指定要启用或禁用的IRQ通道 */
  uint8_t NVIC_IRQChannelPreemptionPriority;  /*!< 指定IRQ通道的抢占优先级*/
  uint8_t NVIC_IRQChannelSubPriority;         /*!< 指定IRQ通道的响应优先级*/
  FunctionalState NVIC_IRQChannelCmd;         /*!< 定义的IRQ通道将被启用或禁用。*/   
} NVIC_InitTypeDef;

// NVIC_IRQChannel可选的值
/* 注意:这里只是STM32F10X_MD的中断通道,全部型号的在stm32f10x.h文件中 */
  ADC1_2_IRQn
  USB_HP_CAN1_TX_IRQn
  USB_LP_CAN1_RX0_IRQn
  CAN1_RX1_IRQn
  CAN1_SCE_IRQn
  EXTI9_5_IRQn
  TIM1_BRK_IRQn
  TIM1_UP_IRQn
  TIM1_TRG_COM_IRQn
  TIM1_CC_IRQn
  TIM2_IRQn
  TIM3_IRQn
  TIM4_IRQn
  I2C1_EV_IRQn
  I2C1_ER_IRQn
  I2C2_EV_IRQn
  I2C2_ER_IRQn
  SPI1_IRQn
  SPI2_IRQn
  USART1_IRQn
  USART2_IRQn
  USART3_IRQn
  EXTI15_10_IRQn
  RTCAlarm_IRQn
  USBWakeUp_IRQn 

// NVIC_IRQChannelPreemptionPriority可选的值
使用NVIC_PriorityGroupConfig函数进行优先级分组后确定

// NVIC_IRQChannelSubPriority可选的值
使用NVIC_PriorityGroupConfig函数进行优先级分组后确定

// NVIC_IRQChannelCmd可选的值
ENABLE									// 使能
DISABLE									// 失能
// 配置优先级分组:抢占优先级和响应优先级。
// 参数为 NVIC_PriortyGroupx:其中x为0~4,对应5个分组
void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup);

// 根据NVIC_InitTypeDef结构体成员属性的参数初始化NVIC外设。
void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct);

// 设置向量表位置和偏移量。
void NVIC_SetVectorTable(uint32_t NVIC_VectTab, uint32_t Offset);

// 选择系统进入低功耗模式的条件。
void NVIC_SystemLPConfig(uint8_t LowPowerMode, FunctionalState NewState);

外设的GPIO配置

image

image

image

image

image

stm32f10x_md的中断函数

	EXPORT  WWDG_IRQHandler            [WEAK]
    EXPORT  PVD_IRQHandler             [WEAK]
    EXPORT  TAMPER_IRQHandler          [WEAK]
    EXPORT  RTC_IRQHandler             [WEAK]
    EXPORT  FLASH_IRQHandler           [WEAK]
    EXPORT  RCC_IRQHandler             [WEAK]
    EXPORT  EXTI0_IRQHandler           [WEAK]
    EXPORT  EXTI1_IRQHandler           [WEAK]
    EXPORT  EXTI2_IRQHandler           [WEAK]
    EXPORT  EXTI3_IRQHandler           [WEAK]
    EXPORT  EXTI4_IRQHandler           [WEAK]
    EXPORT  DMA1_Channel1_IRQHandler   [WEAK]
    EXPORT  DMA1_Channel2_IRQHandler   [WEAK]
    EXPORT  DMA1_Channel3_IRQHandler   [WEAK]
    EXPORT  DMA1_Channel4_IRQHandler   [WEAK]
    EXPORT  DMA1_Channel5_IRQHandler   [WEAK]
    EXPORT  DMA1_Channel6_IRQHandler   [WEAK]
    EXPORT  DMA1_Channel7_IRQHandler   [WEAK]
    EXPORT  ADC1_2_IRQHandler          [WEAK]
    EXPORT  USB_HP_CAN1_TX_IRQHandler  [WEAK]
    EXPORT  USB_LP_CAN1_RX0_IRQHandler [WEAK]
    EXPORT  CAN1_RX1_IRQHandler        [WEAK]
    EXPORT  CAN1_SCE_IRQHandler        [WEAK]
    EXPORT  EXTI9_5_IRQHandler         [WEAK]
    EXPORT  TIM1_BRK_IRQHandler        [WEAK]
    EXPORT  TIM1_UP_IRQHandler         [WEAK]
    EXPORT  TIM1_TRG_COM_IRQHandler    [WEAK]
    EXPORT  TIM1_CC_IRQHandler         [WEAK]
    EXPORT  TIM2_IRQHandler            [WEAK]
    EXPORT  TIM3_IRQHandler            [WEAK]
    EXPORT  TIM4_IRQHandler            [WEAK]
    EXPORT  I2C1_EV_IRQHandler         [WEAK]
    EXPORT  I2C1_ER_IRQHandler         [WEAK]
    EXPORT  I2C2_EV_IRQHandler         [WEAK]
    EXPORT  I2C2_ER_IRQHandler         [WEAK]
    EXPORT  SPI1_IRQHandler            [WEAK]
    EXPORT  SPI2_IRQHandler            [WEAK]
    EXPORT  USART1_IRQHandler          [WEAK]
    EXPORT  USART2_IRQHandler          [WEAK]
    EXPORT  USART3_IRQHandler          [WEAK]
    EXPORT  EXTI15_10_IRQHandler       [WEAK]
    EXPORT  RTCAlarm_IRQHandler        [WEAK]
    EXPORT  USBWakeUp_IRQHandler       [WEAK]

红外对射传感器计数案例

接线图

image

代码示例

#include "stm32f10x.h"                  // Device header
#include "OLED.h"

// 无符号16位整数,用来记录红外线被遮挡的次数
uint16_t count = 0;

int main()
{
	// 开启GPIOB和AFIO的外设时钟。EXTI和NVIC的时钟不用管
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
	
	// 定义GPIO_InitTypeDef类型的结构体
	GPIO_InitTypeDef GPIO_InitStructer;
	// 通过STM32F10xx参考手册可知,GPIO作为外部中断输入时,浮空、上拉、下拉输入都可以
	GPIO_InitStructer.GPIO_Mode = GPIO_Mode_IPD;					// 上拉输入
	GPIO_InitStructer.GPIO_Pin = GPIO_Pin_14;						// 选择引脚14
	GPIO_InitStructer.GPIO_Speed = GPIO_Speed_50MHz;				// 速度50MHz
	GPIO_Init(GPIOB, &GPIO_InitStructer);							// 根据结构体中的成员属性初始GPIOB
	
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource14);	// 将外部中断的14号线映射到GPIOB,即选择PB14为外部中断引脚
	
	// 定义EXTI_InitTypeDef类型的结构体
	EXTI_InitTypeDef EXTI_InitStructer;
	EXTI_InitStructer.EXTI_Line = EXTI_Line14;						// 要启用或禁用的EXTI通道,通道14
	EXTI_InitStructer.EXTI_LineCmd = ENABLE;						// 是否启用通道,启用
	EXTI_InitStructer.EXTI_Mode = EXTI_Mode_Interrupt;				// 中断响应还是事件响应,中断响应
	EXTI_InitStructer.EXTI_Trigger = EXTI_Trigger_Falling;			// 触发方式,上升沿、下降沿和双边沿,下降沿
	EXTI_Init(&EXTI_InitStructer);									// 根据结构体中的成员属性初始EXTI
	
	// 设置NVIC优先级分组,分组2,抢占优先级2个bit位,响应优先级2个bit位
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	
	// 定义NVIC_InitTypeDef类型的结构体
	NVIC_InitTypeDef NVIC_InitStructer;
	NVIC_InitStructer.NVIC_IRQChannel = EXTI15_10_IRQn;				// 选择中断通道,外部中断15~10
	NVIC_InitStructer.NVIC_IRQChannelCmd = ENABLE;					// 是否开启通道,开启
	NVIC_InitStructer.NVIC_IRQChannelPreemptionPriority = 1;		// 设置抢占优先级,1
	NVIC_InitStructer.NVIC_IRQChannelSubPriority = 1;				// 设置响应优先级,1
	NVIC_Init(&NVIC_InitStructer);									// 根据结构体中的成员属性初始化NVIC
	
	OLED_Init();
	OLED_ShowString(1,1,"Count:");
	while(1)
	{
		OLED_ShowNum(1, 7, count, 5);
	}
}

// 外部中断15~10通道的中断函数
void EXTI15_10_IRQHandler(void)
{
	// 判断是否是外部中断14号线触发的中断
	if(EXTI_GetITStatus(EXTI_Line14) == SET)
	{
		count++;
		// 清除外部中断14号线的中断标志位
		EXTI_ClearITPendingBit(EXTI_Line14);
	}
}

选择编码器计数案例

接线图

image

示例代码

#include "stm32f10x.h"                  // Device header
#include "OLED.h"

int16_t num = 0;

int main()
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE);
	
	GPIO_InitTypeDef GPIO_InitStructer;
	GPIO_InitStructer.GPIO_Mode = GPIO_Mode_IPD;
	GPIO_InitStructer.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;
	GPIO_InitStructer.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructer);
	
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource0);//将外部中断的0号线映射到GPIOB,即选择PB0为外部中断引脚
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource1);//将外部中断的1号线映射到GPIOB,即选择PB1为外部中断引脚
	
	EXTI_InitTypeDef EXTI_InitStructer;
	EXTI_InitStructer.EXTI_Line = EXTI_Line0 | EXTI_Line1;
	EXTI_InitStructer.EXTI_LineCmd = ENABLE;
	EXTI_InitStructer.EXTI_Mode = EXTI_Mode_Interrupt;
	EXTI_InitStructer.EXTI_Trigger = EXTI_Trigger_Falling;
	EXTI_Init(&EXTI_InitStructer);
	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	
	NVIC_InitTypeDef NVIC_InitStructer;
	NVIC_InitStructer.NVIC_IRQChannel = EXTI0_IRQn;
	NVIC_InitStructer.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStructer.NVIC_IRQChannelPreemptionPriority = 1;
	NVIC_InitStructer.NVIC_IRQChannelSubPriority = 1;
	NVIC_Init(&NVIC_InitStructer);
	
	NVIC_InitStructer.NVIC_IRQChannel = EXTI1_IRQn;
	NVIC_InitStructer.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStructer.NVIC_IRQChannelPreemptionPriority = 1;
	NVIC_InitStructer.NVIC_IRQChannelSubPriority = 2;
	NVIC_Init(&NVIC_InitStructer);
	
	OLED_Init();
	OLED_ShowString(1,1,"Num:");
	while(1)
	{
		OLED_ShowSignedNum(1,6,num,5);
	}
}

void EXTI0_IRQHandler(void)
{
	if(EXTI_GetITStatus(EXTI_Line0) == SET)
	{
		if(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) == 0)
		{
			 num--;
		}
		EXTI_ClearITPendingBit(EXTI_Line0);
	}
}

void EXTI1_IRQHandler(void)
{
	if(EXTI_GetITStatus(EXTI_Line1) == SET)
	{
		if(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_0) == 0)
		{
			num++;
		}
		EXTI_ClearITPendingBit(EXTI_Line1);
	}
}