stm32_exti(含NVIC)配置及庫函數(shù)講解
STM32有76個中斷,包括16個內(nèi)核中斷和60個可屏蔽中斷,具有16級可編程的中斷優(yōu)先級。而我們常用的就是這60個可屏蔽中斷,所以我們就只針對這60個可屏蔽中斷進行介紹。
本文引用地址:http://m.butianyuan.cn/article/201611/317026.htm關(guān)于中斷的設(shè)置,在STM32的PDF文檔中是找不到關(guān)于NVIC相關(guān)寄存器的說明的,是讓大家摸不著門道嗎?還是故裝高深?最后在《CM3權(quán)威指南》上找到NVIC相關(guān)寄存器,下面重點介紹這幾個寄存器。
ISER[2]:ISER全稱是InterruptSet-EnableRegisters,這是一個中斷使能寄存器組。上面說了STM32的可屏蔽中斷只有60個,這里用了2個32位的寄存器,總共可以表示64個中斷。而STM32只用了其中的前60個。ISER[0]的bit0~bit31分別對應(yīng)中斷0~31。ISER[1]的bit0~bit27對應(yīng)中斷32~59;這樣總共60個中斷就分別對應(yīng)上了。你要使能某個中斷,必須設(shè)置相應(yīng)的ISER位為1,使該中斷被使能(這里僅僅是使能,還要配合中斷分組、屏蔽、IO口映射等設(shè)置才算是一個完整的中斷設(shè)置)。具體每一位對應(yīng)哪個中斷,請參考stm32f10x_nvic.h里面的第36行處。
/* IRQ Channels --------------------------------------------------------------*/
#define WWDG_IRQChannel ((u8)0x00) /* Window WatchDog Interrupt */
#define PVD_IRQChannel ((u8)0x01) /* PVD through EXTI Line detection Interrupt */
#define TAMPER_IRQChannel ((u8)0x02) /* Tamper Interrupt */
#define RTC_IRQChannel ((u8)0x03) /* RTC global Interrupt */
#define FLASH_IRQChannel ((u8)0x04) /* FLASH global Interrupt */
#define RCC_IRQChannel ((u8)0x05) /* RCC global Interrupt */
#define EXTI0_IRQChannel ((u8)0x06) /* EXTI Line0 Interrupt */
#define EXTI1_IRQChannel ((u8)0x07) /* EXTI Line1 Interrupt */
#define EXTI2_IRQChannel ((u8)0x08) /* EXTI Line2 Interrupt */
#define EXTI3_IRQChannel ((u8)0x09) /* EXTI Line3 Interrupt */
#define EXTI4_IRQChannel ((u8)0x0A) /* EXTI Line4 Interrupt */
#define DMA1_Channel1_IRQChannel ((u8)0x0B) /* DMA1 Channel 1 global Interrupt */
#define DMA1_Channel2_IRQChannel ((u8)0x0C) /* DMA1 Channel 2 global Interrupt */
#define DMA1_Channel3_IRQChannel ((u8)0x0D) /* DMA1 Channel 3 global Interrupt */
#define DMA1_Channel4_IRQChannel ((u8)0x0E) /* DMA1 Channel 4 global Interrupt */
#define DMA1_Channel5_IRQChannel ((u8)0x0F) /* DMA1 Channel 5 global Interrupt */
#define DMA1_Channel6_IRQChannel ((u8)0x10) /* DMA1 Channel 6 global Interrupt */
#define DMA1_Channel7_IRQChannel ((u8)0x11) /* DMA1 Channel 7 global Interrupt */
#define ADC1_2_IRQChannel ((u8)0x12) /* ADC1 et ADC2 global Interrupt */
#define USB_HP_CAN_TX_IRQChannel ((u8)0x13) /* USB High Priority or CAN TX Interrupts */
#define USB_LP_CAN_RX0_IRQChannel ((u8)0x14) /* USB Low Priority or CAN RX0 Interrupts */
#define CAN_RX1_IRQChannel ((u8)0x15) /* CAN RX1 Interrupt */
#define CAN_SCE_IRQChannel ((u8)0x16) /* CAN SCE Interrupt */
#define EXTI9_5_IRQChannel ((u8)0x17) /* External Line[9:5] Interrupts */
#define TIM1_BRK_IRQChannel ((u8)0x18) /* TIM1 Break Interrupt */
#define TIM1_UP_IRQChannel ((u8)0x19) /* TIM1 Update Interrupt */
#define TIM1_TRG_COM_IRQChannel ((u8)0x1A) /* TIM1 Trigger and Commutation Interrupt */
#define TIM1_CC_IRQChannel ((u8)0x1B) /* TIM1 Capture Compare Interrupt */
#define TIM2_IRQChannel ((u8)0x1C) /* TIM2 global Interrupt */
#define TIM3_IRQChannel ((u8)0x1D) /* TIM3 global Interrupt */
#define TIM4_IRQChannel ((u8)0x1E) /* TIM4 global Interrupt */
#define I2C1_EV_IRQChannel ((u8)0x1F) /* I2C1 Event Interrupt */
#define I2C1_ER_IRQChannel ((u8)0x20) /* I2C1 Error Interrupt */
#define I2C2_EV_IRQChannel ((u8)0x21) /* I2C2 Event Interrupt */
#define I2C2_ER_IRQChannel ((u8)0x22) /* I2C2 Error Interrupt */
#define SPI1_IRQChannel ((u8)0x23) /* SPI1 global Interrupt */
#define SPI2_IRQChannel ((u8)0x24) /* SPI2 global Interrupt */
#define USART1_IRQChannel ((u8)0x25) /* USART1 global Interrupt */
#define USART2_IRQChannel ((u8)0x26) /* USART2 global Interrupt */
#define USART3_IRQChannel ((u8)0x27) /* USART3 global Interrupt */
#define EXTI15_10_IRQChannel ((u8)0x28) /* External Line[15:10] Interrupts */
#define RTCAlarm_IRQChannel ((u8)0x29) /* RTC Alarm through EXTI Line Interrupt */
#define USBWakeUp_IRQChannel ((u8)0x2A) /* USB WakeUp from suspend through EXTI Line Interrupt */
#define TIM8_BRK_IRQChannel ((u8)0x2B) /* TIM8 Break Interrupt */
#define TIM8_UP_IRQChannel ((u8)0x2C) /* TIM8 Update Interrupt */
#define TIM8_TRG_COM_IRQChannel ((u8)0x2D) /* TIM8 Trigger and Commutation Interrupt */
#define TIM8_CC_IRQChannel ((u8)0x2E) /* TIM8 Capture Compare Interrupt */
#define ADC3_IRQChannel ((u8)0x2F) /* ADC3 global Interrupt */
#define FSMC_IRQChannel ((u8)0x30) /* FSMC global Interrupt */
#define SDIO_IRQChannel ((u8)0x31) /* SDIO global Interrupt */
#define TIM5_IRQChannel ((u8)0x32) /* TIM5 global Interrupt */
#define SPI3_IRQChannel ((u8)0x33) /* SPI3 global Interrupt */
#define UART4_IRQChannel ((u8)0x34) /* UART4 global Interrupt */
#define UART5_IRQChannel ((u8)0x35) /* UART5 global Interrupt */
#define TIM6_IRQChannel ((u8)0x36) /* TIM6 global Interrupt */
#define TIM7_IRQChannel ((u8)0x37) /* TIM7 global Interrupt */
#define DMA2_Channel1_IRQChannel ((u8)0x38) /* DMA2 Channel 1 global Interrupt */
#define DMA2_Channel2_IRQChannel ((u8)0x39) /* DMA2 Channel 2 global Interrupt */
#define DMA2_Channel3_IRQChannel ((u8)0x3A) /* DMA2 Channel 3 global Interrupt */
#define DMA2_Channel4_5_IRQChannel ((u8)0x3B) /* DMA2 Channel 4 and DMA2 Channel 5 global Interrupt */
例如:EXTI9所對應(yīng)的中斷號為23。
ICER[2]:全稱是InterruptClear-EnableRegisters,是一個中斷除能寄存器組。該寄存器組與ISER的作用恰好相反,是用來清除某個中斷的使能的。這里要與專門設(shè)置一個ICER來清除中斷位,而不是向ISER寫0來清除,是因為NVIC的這些寄存器都是寫1有效的,寫0無效的。具體為什么這么設(shè)計,請看《CM3權(quán)威指南》第125頁。
ISPR[2]:全稱是InterruptSet-PendingRegisters,是一個中斷掛起控制寄存器組。每一位對應(yīng)的中斷和ISER是一樣的。通過置1,可以將正在進行的中斷掛起,而執(zhí)行同級或更高級別的中斷。寫0是無效的。
ICPR[2]:全稱是:InterruptClear-PendingRegisters,是一個中斷解掛控制寄存器組。其作用與ISPR相反,對應(yīng)位也和ISER是一樣的。通過設(shè)置1,可以將掛起的中斷解掛。寫0無效。
IABR[2]:全稱是ActiveBitRegisters,是一個中斷激活標志位寄存器組。對應(yīng)位所代表的的中斷和ISER一樣,如果為1,則表示該位所對應(yīng)的中斷正在被執(zhí)行。這是一個只讀寄存器,通過它可以知道當(dāng)前在執(zhí)行的中斷是哪一個。在中斷執(zhí)行完了由硬件自動清零。
IPR[15]:全稱是InterruptPriorityRegisters,是一個中斷優(yōu)先級控制的寄存器組。這個寄存器組相當(dāng)重要!STM32的中斷分組與這個寄存器組密切相關(guān)。IPR寄存器組由15個32bit的寄存器組成,每個可屏蔽中斷占用8bit,這樣總共可以表示15*4=60個可屏蔽中斷。剛好和STM32的可屏蔽中斷數(shù)相等。IPR[0]的[31~24],[23~16],[15~8],[7~0]分別對應(yīng)中斷3~0,以此類推,總共對應(yīng)60個外部中斷。而每個可屏蔽中斷占用的8bit并沒有全部使用,而是只用了高4位。這4位,又分為搶占優(yōu)先級和子優(yōu)先級。搶占優(yōu)先級在前,子優(yōu)先級在后。而這兩個優(yōu)先級各占幾個位又要根據(jù)SCB->AIRCR中中斷分組的設(shè)置來決定。
這里簡單介紹一下STM32的中斷分組:STM32將中斷分為5各組,組0~4。該分組的設(shè)置是由SCB->AIRCR 寄存器的bit10~8來定義的。具體的分配關(guān)系如下表所示:
例如:PB9對應(yīng)中斷線EXTI9,NVIC_Priority Group=1,Preemption Priority=1,SubPriority=7,則IAR中的IP5的PRI_23=0xF0。stm32的固件庫中有兩個非常重要的結(jié)構(gòu)體,如下
/*------------------------ Nested Vectored Interrupt Controller --------------*/
typedef struct
{
vu32 ISER[2]; //對應(yīng)IAR中 SETENA0 和 SETENA1
u32 RESERVED0[30];
vu32 ICER[2]; //對應(yīng)IAR中 CLRENA0 和 CLRENA1
u32 RSERVED1[30];
vu32 ISPR[2]; //對應(yīng)IAR中 SETPEND0 和 SETPEND1
u32 RESERVED2[30];
vu32 ICPR[2]; //對應(yīng)IAR中 CLRPEND0 和 CLRPEND1
u32 RESERVED3[30];
vu32 IABR[2]; //對應(yīng)IAR中 ACTIVE0 和 ACTIVE1
u32 RESERVED4[62];
vu32 IPR[15]; //對應(yīng)IAR中 IP0 到 IP15
} NVIC_TypeDef;
它們對應(yīng)ARM手冊中的名稱為
ISER=InterruptSet-EnableRegisters
ICER=InterruptClear-EnableRegisters
ISPR=InterruptSet-PendingRegister
ICPR=InterruptClear-PendingRegister
IABR=ActiveBitRegister
IPR=InterruptPriorityRegisters
typedef struct
{
vuc32 CPUID; //對應(yīng)IAR中 CPUIDBR
vu32 ICSR; //對應(yīng)IAR中 ICSR
vu32 VTOR; //對應(yīng)IAR中 VTOR
vu32 AIRCR; //對應(yīng)IAR中 AIRCR
vu32 SCR; //對應(yīng)IAR中 SCR
vu32 CCR; //對應(yīng)IAR中 CCR
vu32 SHPR[3]; //對應(yīng)IAR中 SHPR0~SHPR2
vu32 SHCSR; //對應(yīng)IAR中 SHCSR
vu32 CFSR; //對應(yīng)IAR中 CFSR
vu32 HFSR; //對應(yīng)IAR中 HFSR
vu32 DFSR; //對應(yīng)IAR中 DFSR
vu32 MMFAR; //對應(yīng)IAR中 MMFAR
vu32 BFAR; //對應(yīng)IAR中 BFAR
vu32 AFSR; //對應(yīng)IAR中
} SCB_TypeDef;
它們對應(yīng)ARM手冊中的名稱為
CPUID=CPUIDBaseRegister
ICSR=InterruptControlStateRegister
VTOR=VectorTableOffsetRegister
AIRCR=ApplicationInterrupt/ResetControlRegister
SCR=SystemControlRegister
CCR=ConfigurationControlRegister
SHPR=SystemHandlersPriorityRegister
SHCSR=SystemHandlerControlandStateRegister
CFSR=ConfigurableFaultStatusRegisters
HFSR=HardFaultStatusRegister
DFSR=DebugFaultStatusRegister
MMFAR=MemManageAddressRegister
BFAR=BusFaultAddressRegister
AFSR=AuxiliaryFaultStatusRegister
UserButton硬件連接如下圖所示:當(dāng)按鍵被按下,PB9檢測到低電平,相反PB9被3.3V電源拉高。
LED硬件連接如下圖所示:高電平點亮LED。
本實驗要實現(xiàn)的功能是:按User鍵,用中斷的方式點亮LED1。
預(yù)備知識:80個通用I/O端口以下圖的方式連接到19個外部中斷/事件線上:
另外三種其他的外部中斷/事件控制器的連接如下:
EXTI16 連接到PVD輸出
EXTI17 連接到RTC鬧鐘事件
EXTI18 連接到USB喚醒事件
涉及到AFIO_EXTICR1~AFIO_EXTICR4寄存器,如下所示
第一步:配置系統(tǒng)時鐘。見STM32F103xRCC寄存器配置
/* Enable GPIOC and GPIOB clock */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
/* Enable AFIO clock */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
注意:別忘了將AFIO時鐘打開。
第二步:配置中斷向量表。本章重點!
void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
#ifdef VECT_TAB_RAM
/* Set the Vector Table base location at 0x20000000 */
NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0);
#else /* VECT_TAB_FLASH */
/* Set the Vector Table base location at 0x08000000 */
NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);
#endif
/* Configure one bit for preemption priority */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
/* Enable the EXTI9_5 Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQChannel;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
該函數(shù)完成兩個功能
1.決定將程序下載到RAM中還是FLASH中
2.配置中斷分組。(NVIC中斷分組只能設(shè)置一次)
3.選擇中斷通道號,搶占式優(yōu)先級和響應(yīng)優(yōu)先級,使能中斷
第三步:配置GPIO的模式。輸入模式還是輸出模式。點亮LED已講過。
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/* Configure PC.06 as Output push-pull */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOC, &GPIO_InitStructure);
/* Configure PB.09 as input floating (EXTI Line 9) */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //輸入懸空模式
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
第四步:外部中斷線配置,本章重點!
void EXTI_Configuration(void)
{
EXTI_InitTypeDef EXTI_InitStructure;
/* Connect EXTI Line9 to PB.09 */
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource9);
/* Configure EXTI Line9 to generate an interrupt on falling edge */
EXTI_InitStructure.EXTI_Line = EXTI_Line9;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; //下降沿觸發(fā)
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
}
該函數(shù)完成兩個功能
1.將PB9管腳用作外部中斷
2.選擇中斷線,中斷模式(中斷還是事件),觸發(fā)模式(電平還是跳變沿),使能
exti.c文件完整代碼如下:
/* Includes ------------------------------------------------------------------*/
#include "stm32f10x_lib.h"
/* Private function prototypes -----------------------------------------------*/
void RCC_Configuration(void);
void NVIC_Configuration(void);
void GPIO_Configuration(void);
void EXTI_Configuration(void);
void Delay(vu32 nCount);
/*******************************************************************************
* Function Name : main
* Description : Main program.
* Input : None
* Return : None
*******************************************************************************/
int main(void)
{
#ifdef DEBUG
debug();
#endif
/* Configure the system clocks */
RCC_Configuration();
/* NVIC Configuration */
NVIC_Configuration();
/* Configure the GPIO ports */
GPIO_Configuration();
/* Configure the EXTILine */
EXTI_Configuration();
/* Generate software interrupt: simulate a falling edge applied on EXTI line 9 */
EXTI_GenerateSWInterrupt(EXTI_Line9); //只能產(chǎn)生一次
/* Infinite loop */
while (1)
{
}
}
/*******************************************************************************
* Function Name : RCC_Configuration
* Description : Configures the different system clocks.
* Input : None
* Return : None
*******************************************************************************/
void RCC_Configuration(void)
{
ErrorStatus HSEStartUpStatus;
/* RCC system reset(for debug purpose) */
RCC_DeInit();
/* Enable HSE */
RCC_HSEConfig(RCC_HSE_ON);
/* Wait till HSE is ready */
HSEStartUpStatus = RCC_WaitForHSEStartUp();
if (HSEStartUpStatus == SUCCESS)
{
/* Enable Prefetch Buffer */
FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
/* Flash 2 wait state */
FLASH_SetLatency(FLASH_Latency_2);
/* HCLK = SYSCLK */
RCC_HCLKConfig(RCC_SYSCLK_Div1);
/* PCLK2 = HCLK */
RCC_PCLK2Config(RCC_HCLK_Div1);
/* PCLK1 = HCLK/2 */
RCC_PCLK1Config(RCC_HCLK_Div2);
/* PLLCLK = 8MHz * 9 = 72 MHz */
RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);
/* Enable PLL */
RCC_PLLCmd(ENABLE);
/* Wait till PLL is ready */
while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET) {}
/* Select PLL as system clock source */
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
/* Wait till PLL is used as system clock source */
while(RCC_GetSYSCLKSource() != 0x08) {}
}
/* Enable GPIOC and GPIOB clock */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
/* Enable AFIO clock */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
}
/*******************************************************************************
* Function Name : NVIC_Configuration
* Description : Configures Vector Table base location.
* Input : None
* Return : None
*******************************************************************************/
void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
#ifdef VECT_TAB_RAM
/* Set the Vector Table base location at 0x20000000 */
NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0);
#else /* VECT_TAB_FLASH */
/* Set the Vector Table base location at 0x08000000 */
NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);
#endif
/* Configure one bit for preemption priority */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
/* Enable the EXTI9_5 Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQChannel;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
/*******************************************************************************
* Function Name : GPIO_Configuration
* Description : Configures the different GPIO ports.
* Input : None
* Return : None
*******************************************************************************/
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/* Configure PC.06 as Output push-pull */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOC, &GPIO_InitStructure);
/* Configure PB.09 as input floating (EXTI Line 9) */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //輸入懸空模式
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
/*******************************************************************************
* Function Name : EXTI_Configuration
* Description : Configures the EXTILine.
* Input : None
* Return : None
*******************************************************************************/
void EXTI_Configuration(void)
{
EXTI_InitTypeDef EXTI_InitStructure;
/* Connect EXTI Line9 to PB.09 */
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource9);
/* Configure EXTI Line9 to generate an interrupt on falling edge */
EXTI_InitStructure.EXTI_Line = EXTI_Line9;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; //下降沿觸發(fā)
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
}
/*******************************************************************************
* Function Name : Delay
* Description : Inserts a delay time.
* Input : nCount: specifies the delay time length.
* Return : None
*******************************************************************************/
void Delay(vu32 nCount)
{
for(; nCount != 0; nCount--);
}
#ifdef DEBUG
/*******************************************************************************
* Function Name : assert_failed
* Description : Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* Input : - file: pointer to the source file name
* - line: assert_param error line source number
* Return : None
*******************************************************************************/
void assert_failed(u8* file, u32 line)
{
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %drn", file, line) */
/* Infinite loop */
while (1)
{
}
}
#endif
stm32f10x_it.c有關(guān)EXTI9代碼如下
void EXTI9_5_IRQHandler(void)
{
if (EXTI_GetITStatus(EXTI_Line9) != RESET)
{
/* Toggle PC6 pin */
GPIO_WriteBit(GPIOC, GPIO_Pin_6, (BitAction)((1 - GPIO_ReadOutputDataBit(GPIOC, GPIO_Pin_6))));
/* Clear the EXTI line 9 pending bit */
EXTI_ClearITPendingBit(EXTI_Line9);
}
}
評論