STM32之按鍵作爲外部中斷控制led燈

基礎概念

STM32F4 的每個 IO 都可以作爲外部中斷的中斷輸入口,這點也是 STM32F4 的強大之處。 STM32F407 的中斷控制器支持 22 個外部
中斷/事件請求。每個中斷設有狀態位,每個中斷/事件都有獨立的觸發和屏蔽設置。 STM32F407的 22 個外部中斷爲:
EXTI 線 0~15:對應外部 IO 口的輸入中斷。
EXTI 線 16:連接到 PVD 輸出。
EXTI 線 17:連接到 RTC 鬧鐘事件。
EXTI 線 18:連接到 USB OTG FS 喚醒事件。
EXTI 線 19:連接到以太網喚醒事件。
EXTI 線 20:連接到 USB OTG HS(在 FS 中配置)喚醒事件。
EXTI 線 21:連接到 RTC 入侵和時間戳事件。
EXTI 線 22:連接到 RTC 喚醒事件。

從上面可以看出, STM32F4 供 IO 口使用的中斷線只有 16 個,但是 STM32F4 的 IO 口卻
遠遠不止 16 個,那麼 STM32F4 是怎麼把 16 箇中斷線和 IO 口一一對應起來的呢?於是 STM32就這樣設計, GPIO 的管教 GPIOx.0~GPIOx.15(x=A,B,C,D,E, F,G,H,I)分別對應中斷線 0~15。這
樣每個中斷線對應了最多 9 個 IO 口,以線 0 爲例:它對應了 GPIOA.0、 GPIOB.0、 GPIOC.0、GPIOD.0、 GPIOE.0、 GPIOF.0、 GPIOG.0,GPIOH.0,GPIOI.0。而中斷線每次只能連接到 1 個 IO口上,這樣就需要通過配置來決定對應的中斷線配置到哪個 GPIO 上了。下面我們看看 GPIO
跟中斷線的映射關係圖:
在這裏插入圖片描述

基本步驟
1) 使能 IO 口時鐘, 初始化 IO 口爲輸入。
2) 使能 SYSCFG 時鐘, 設置 IO 口與中斷線的映射關係。
3)初始化線上中斷,設置觸發條件等。
4)配置中斷分組(NVIC),並使能中斷。
5)編寫中斷服務函數。

1) 使能 IO 口時鐘, 初始化 IO 口爲輸入
首先,我們要使用 IO 口作爲中斷輸入,所以我們要使能相應的 IO 口時鐘,以及初始化相應的 IO 口爲輸入模式,我們使用按鍵爲外部中斷,此處應設置按鍵的IO口。
在exti.c文件下 void EXTIX_Init(void) 函數中輸入

    key_init();
	

2) 使能 SYSCFG 時鐘, 設置 IO 口與中斷線的映射關係。
使能外部中斷所必須的時鐘SYSCFG,接下來,我們配置 GPIO 與中斷線的映射關係。 在庫函數中,配置 GPIO 與中斷線的映射
關係的函數 SYSCFG_EXTILineConfig ()來實現的:

void SYSCFG_EXTILineConfig(uint8_t EXTI_PortSourceGPIOx, uint8_t EXTI_PinSourcex);

該函數將 GPIO 端口與中斷線映射起來。
此部分代碼:

RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG,ENABLE);//使能SYSCFG時鐘
SYSCFG_EXTILineConfig (EXTI_PortSourceGPIOE, EXTI_PinSource4);//GPIO端口指按鍵的IO口,第二個參數是中斷線,因爲這裏的按鍵是GPIOE_Pin4,故這裏中斷線對應爲4.

3)初始化線上中斷,設置觸發條件等。
中斷線上中斷的初始化是通過函數 EXTI_Init()實現的。這裏我們本來是在 EXTI_Init()裏實現初始化,但因爲還要使能時鐘還要設置中斷優先級等,整個中斷初始化放在 void EXTIX_Init(void) 函數裏。
故這裏只需要寫入原本 EXTI_Init()裏該有的內容即可

	EXTI_InitTypeDef EXTI_InitStruct;
	
	EXTI_InitStruct.EXTI_Line=EXTI_Line4;//選擇中斷線
	EXTI_InitStruct.EXTI_LineCmd=ENABLE;//使能
	EXTI_InitStruct.EXTI_Mode=EXTI_Mode_Interrupt;//選擇中斷模式
	EXTI_InitStruct.EXTI_Trigger=EXTI_Trigger_Falling;//選擇下降沿觸發中斷
	EXTI_Init(&EXTI_InitStruct);

4)配置中斷分組(NVIC),並使能中斷
設置 NVIC 中斷優先級:

	NVIC_InitTypeDef NVIC_InitStructure;
	
	NVIC_InitStructure.NVIC_IRQChannel=EXTI4_IRQn;//使能按鍵外部中斷
	NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;//使能外部中斷通道
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0x01;//搶佔優先級1
	NVIC_InitStructure.NVIC_IRQChannelSubPriority=0x02;//響應優先級2
	NVIC_Init(&NVIC_InitStructure);//中斷優先級分組初始化

這裏的優先級應該是有多箇中斷的時候需要,只有一箇中斷還需要設置優先級嗎?

5)編寫中斷服務函數。

void EXTI4_IRQHandler(void)
{
	delay_ms(5);
	if(key0==0)
	{
		 
		 LED1 =0;
		for(int i=0;i<5;i++)	 
			{
				 LED0 =1;
				 delay_ms(500);
				 LED0=0;
				 delay_ms(500);
			}
	}
	EXTI_ClearITPendingBit(EXTI_Line4);//清除 LINE4 上的中斷標誌位
}

整個的效果是,剛開始led0亮,進入中斷後led0閃爍五次,led1常亮。
exti.h文件

#ifndef EXIT_H
#define EXIT_H
#include "sys.h"

void EXTIX_Init(void);

#endif

led.c部分

#include "led.h" 
void LED_Init(void)
{    	 
  GPIO_InitTypeDef  GPIO_InitStructure;

  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
  
 
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
  GPIO_Init(GPIOA, &GPIO_InitStructure);
  GPIO_ResetBits(GPIOA, GPIO_Pin_7);

}

led.h部分

#ifndef __LED_H
#define __LED_H
#include "sys.h"


#define LED0 PAout(6)	// DS0
#define LED1 PAout(7)	// DS1	 

void LED_Init(void);	 				    
#endif

按鍵初始化的代碼解釋參考這裏
key.c部分

#include "key.h"
#include "delay.h" 
#include "led.h" 
void key_init(void)
	
{
	GPIO_InitTypeDef  GPIO_InitStructure;

  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE);
 
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4| GPIO_Pin_3;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;

  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
  GPIO_Init(GPIOE, &GPIO_InitStructure);
 }

key.h部分

#ifndef KEY_H
#define KEY_H
#include "sys.h"

#define key0 PEin(4) 
#define key1 PEin(3) 
void key_init(void);
#endif

main.c 文件

#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "key.h"
#include "exits.h"
int main(void)
{ 
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//設置系統中斷優先級分組 2
	delay_init(168);		
	LED_Init();	
    key_init();	
    EXTIX_Init(); 
	LED0=0;
	LED1=1;
 
	
	while(1)
	{
	}
}

不懂main.c中中斷優先級分組是幹什麼的

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章