***************************************************************************************************************************************
開發闆 :奮鬥STM32
CPU :STM32F103
開發環境:keil uVsion4
****************************************************************************************************************************************
前言:本文主要是通過按鍵中斷,實作當按下按鍵時,LED燈滅,釋放按鍵時,LED燈亮。(不過我設定LED的起始狀态為亮,也就是上電就點亮了LED燈。)
我的開發闆按鍵,LED所對應的GPIO管腳原理圖如下:

我寫的按鍵中斷程式實作的功能是:按下按鍵K2,LED3由亮變滅,釋放按鍵LED3又變亮。(按鍵K2對應PC2管腳,LED3對應PD3管腳)。
測試代碼:
#include "misc.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_exti.h"
#include "stm32f10x_rcc.h"
#define LED_ON GPIO_SetBits(GPIOD, GPIO_Pin_3);
//unsigned char flag=0;
//unsigned char num=0;
void LED_Config(void);
void EXTI_PC2_Config(void);
void RCC_Config(void);
//void KEY_Dither(void);
//void delay_nms(u16 time);
int main(void)
{
// unsigned char a = 0;
RCC_Config();
LED_Config();
EXTI_PC2_Config();
LED_ON;
while(1)
{
//KEY_Dither();
//if(num==1&&a==0){GPIO_ResetBits(GPIOD,GPIO_Pin_6);a=1;}
//else if(num==1&&a==1){GPIO_SetBits(GPIOD,GPIO_Pin_6);a=0;}
}
}
/*void KEY_Dither(void)
{
num=0;
if(flag==1)
{
delay_nms(12000);
if(GPIO_ReadInputDataBit(GPIOD,GPIO_Pin_6)==0)
{
delay_nms(12000);
if(GPIO_ReadInputDataBit(GPIOD,GPIO_Pin_6)==0)
{
while(GPIO_ReadInputDataBit(GPIOD,GPIO_Pin_6)==0)
num=1;
goto n_exit;
}
}
else ;
n_exit:;
flag=0;
}
}
void delay_nms(u16 time)
{
u16 i=0;
while(time--)
{
i=12000; //自己定義
while(i--) ;
}
}
*/
void RCC_Config(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB |RCC_APB2Periph_GPIOD,ENABLE);
SystemInit();
}
void LED_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/*led config*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOD, &GPIO_InitStructure);
}
void EXTI_PC2_Config(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
EXTI_InitTypeDef EXTI_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
/*config for NVIC*/
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
NVIC_InitStructure.NVIC_IRQChannel = EXTI2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
/* key for exti */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOC, GPIO_PinSource2);
/*EXIT line(PC2) mode config */
EXTI_InitStructure.EXTI_Line = EXTI_Line2;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
}
void EXTI2_IRQHandler(void)
{
if (EXTI_GetITStatus(EXTI_Line2) != RESET)
{
// flag= 1;//按鍵按下标志
/*LED取反*/
GPIO_WriteBit(GPIOD, GPIO_Pin_3,
(BitAction)((1-GPIO_ReadOutputDataBit(GPIOD, GPIO_Pin_3))));
EXTI_ClearITPendingBit(EXTI_Line2);
}
}
************************************************************************************************************************************
說明:我寫的這個程式隻是實作了按鍵按下燈由亮變滅的簡單功能,但是測試發現,這個按鍵抖動太嚴重,輕輕的觸摸按鍵,燈會閃閃的亮,有時
候碰一下按鍵,還沒有按下按鍵時,LED燈就熄滅了。是以用delay_nms()延時函數進行去抖,代碼中注釋掉的代碼是為了按鍵去抖,不過這個去抖效果不是很好,還是會有抖動現象,但相比之前會好一點!不過官方提供了一個延時函數,可以調用官方寫好的延時函數,一般10ms的時間可以去抖。
************************************************************************************************************************************************
寫這個程式主要是完成相應的配置工作,步驟如下:
(1)初始化系統時鐘和
初始化外部時鐘(時鐘配置)
void RCC_Config(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB |RCC_APB2Periph_GPIOD,ENABLE);
SystemInit(); //系統時鐘初始化
}
*****************************************************************************************************************************************************************************
說明:我們可以不用加SystemInit();不加這個函數也沒影響,因為startup_stm32f10x_hd.s這個檔案已經幫我們做了這些事情。
*****************************************************************************************************************************************************************************
(3)配置LED
void LED_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/*led config*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//推挽輸出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOD, &GPIO_InitStructure);
}
(4)配置中斷優先級
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
NVIC_InitStructure.NVIC_IRQChannel = EXTI2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
*********************************************************************************************************************************************************************************
說明:這個中斷優先級的設定可以随便設定,原因是我建立的工程中隻用到了按鍵中斷,沒有其他中斷,當然如果有多個中斷,就得按照中斷向量表
以及中斷優先級設定規則來設,具體規則可以參考網上的資料,有很多,可以看看,這裡我就不說明了。這裡我設定的是第一組中斷,搶占優先級是
0,響應優先級也是0。
************************************************************************************************************************************************************************************
(5)配置外部中斷線
/*EXIT line(PC2) mode config */
EXTI_InitStructure.EXTI_Line = EXTI_Line2;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;//中斷模式
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;//下降沿觸發
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
*************************************************************************************************************************************************************************************
說明:這個中斷模式有兩種,一是Event,二是Interrupt,因為這裡是中斷,是以我們設為
Interrupt
,因為是按鍵Key2,則這裡中斷線為EXTI_Line2,如果按鍵是5-9則這裡就要統一寫成EXTI9_5_IRQn。
**************************************************************************************************************************************************************************************
(6)中斷處理函數
void EXTI2_IRQHandler(void)
{
if (EXTI_GetITStatus(EXTI_Line2) != RESET) //判斷按鍵是否按下
{
/*LED反轉*/
GPIO_WriteBit(GPIOD, GPIO_Pin_6,
(BitAction)((1-GPIO_ReadOutputDataBit(GPIOD, GPIO_Pin_6))));
EXTI_ClearITPendingBit(EXTI_Line2); //清除中斷标志位
}
}
****************************************************************************************************************************************************************************************
說明:這裡的中斷處理函數我們通常最好是放在 stm32f10x_it.c這個檔案,這是官方提供的一個用來放所有外部中斷處理函數的檔案,當主程式在執行程式時,如果發生中斷,cpu會立即跳到這裡來執行中斷處理函數,這裡因為隻有按鍵中斷,還展現不出這樣做的好處,如果是一個大工程,用到多個中斷時,把中斷函數統一放在這個檔案中的話,可以大大優化代碼。
***************************************************************************************************************************************************************************************