基於STM32F13ZET6實現外部中斷

和往常一樣,我會提供完成項目同時,提供小編在實踐時的情況以及自己認爲更好的算法心得!歡迎閱讀,我的博客前面完成了幾個簡單的實驗,相信大家對軟件的配置和基本模式已經熟悉,就不再贅述!
開始
之前用while循環編寫的按鍵識別,現在終於到了中斷識別按鍵了,跟之前的按鍵實驗一樣(正點原子精英版),功能不變,識別原理改爲了中斷,我們分別用KEY0控制DS0(LED0),用KEY1控制DS1(LED1),KEY_UP控制BEEP(蜂鳴器)的狀態反轉!
STM32的開發板IO口都可以作爲中斷輸入引腳,但是中斷線只有16根,所以在選擇時有一些侷限:開發板的IO有GPIOA,B,C,D,E,F,G;每種IO有16個引腳,同一個GPIO(如A),1-16個引腳都可以同時被使用爲中斷,如圖:
在這裏插入圖片描述
十六根中斷線同一時間只能選擇一根,所以開發板的所有IO都可以進行中斷是針對不同時間的!
所以在初始化時要選擇哪個IO是終端模式,這時候要用到IO選擇初始化函數void GPIO_EXTILineConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource),選擇某一IO可以這樣配置:GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource2)
這裏需要說明一下,STM32 的 IO 口外部中斷函數只有 6 個,
分別爲:
在這裏插入圖片描述
中斷線 0-4 每個中斷線對應一箇中斷函數,中斷線 5-9 共用中斷函數 EXTI9_5_IRQHandler,中斷線 10-15 共用中斷函數EXTI15_10_IRQHandler
在中斷函數裏,判斷中斷(可不判斷)的條件,如果是判斷line1發生了中斷,可以這樣編寫EXTI_GetITStatus(EXTI_Line3)!=RESET(值爲0)或者EXTI_GetITStatus(EXTI_Line3)==SET(值爲1)
中斷結束時,要清除中斷標誌位,這一步是必須的!EXTI_ClearITPendingBit(EXTI_Line1)
整個格式可以這樣:
void EXTI3_IRQHandler(void)
{
if(EXTI_GetITStatus(EXTI_Line1)!=RESET)//判斷line上的中斷是否發生
{
中斷邏輯…
EXTI_ClearITPendingBit(EXTI_Line1); //清除line1上的中斷標誌位
} }

跟上面的另一種相同的寫法還有另一種
void EXTI3_IRQHandler(void)
{
if(EXTI_GetFlagStatus)//判斷line上的中斷是否發生,參數自行補齊
{
中斷邏輯…
EXTI_ClearFlag; //清除line1上的中斷標誌位 ,參數自行補齊
} }

下面就開始代碼編寫:
外部中斷定義頭文件exti.h
#ifndef EXTI_H
#define EXTI_H
#include “sys.h”
void exti_init(void);
#endif
很簡單,沒什麼好解釋的
外部中斷源文件exti.c
#include “sys.h”
#include “delay.h”
#include “key.h”
#include “led.h”
#include “exti.h”
#include “beep.h”

void exti_init(void)
{
EXTI_InitTypeDef EXTI_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
KEY_Init();
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);

GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource3);
EXTI_InitStructure.EXTI_Line=EXTI_Line3;
EXTI_InitStructure.EXTI_LineCmd=ENABLE;
EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Falling;
EXTI_Init(&EXTI_InitStructure);

GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource4);
EXTI_InitStructure.EXTI_Line=EXTI_Line4;
EXTI_InitStructure.EXTI_LineCmd=ENABLE;
EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Falling;
EXTI_Init(&EXTI_InitStructure);

GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource0);
EXTI_InitStructure.EXTI_Line=EXTI_Line0;
EXTI_InitStructure.EXTI_LineCmd=ENABLE;
EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Rising;
EXTI_Init(&EXTI_InitStructure);

NVIC_InitStructure.NVIC_IRQChannel= EXTI3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0x02;
NVIC_InitStructure.NVIC_IRQChannelSubPriority=0x02;
NVIC_Init(&NVIC_InitStructure);

NVIC_InitStructure.NVIC_IRQChannel= EXTI4_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0x02;
NVIC_InitStructure.NVIC_IRQChannelSubPriority=0x00;
NVIC_Init(&NVIC_InitStructure);

NVIC_InitStructure.NVIC_IRQChannel= EXTI0_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0x02;
NVIC_InitStructure.NVIC_IRQChannelSubPriority=0x03;
NVIC_Init(&NVIC_InitStructure);

}
void EXTI3_IRQHandler(void)
{
if(EXTI_GetITStatus(EXTI_Line3)!=RESET)
{
static unsigned char i;
i++;

	delay_ms(20);
	if(KEY1==0&&i==1)
		{
			LED1=!LED1;	
		}
	else 
	{
		i=0;
		EXTI_ClearITPendingBit(EXTI_Line3);
	}
}

}
void EXTI4_IRQHandler(void)
{
static unsigned char i;
i++;
delay_ms(10);
if(KEY00&&i1)
{
LED0=!LED0;
}
else
{
i=0;
EXTI_ClearITPendingBit(EXTI_Line4);
}
}
void EXTI0_IRQHandler(void)
{
static unsigned char i;
i++;
delay_ms(10);
if(WK_UP1&&i1)
{
BEEP=!BEEP;
}
else
{
i=0;
EXTI_ClearITPendingBit(EXTI_Line0);
}
}
原文件裏的KEY_Init();的順序很重要,注意別出錯,小編當時就錯了!我們直接使用案件裏面的程序,就直接引用,EXTI主要是初始化IO中斷通道,開啓中斷,自然而然需要初始化中斷,重點在中斷函數,如果採用正點原子程序,跟我的還是有點差別的,我也不知道是不是我的開發板問題?(滑稽),控制led時不穩定,自己定義了個靜態變量,來計算中斷來的個數,我的邏輯就是,在接收到一次中斷後下一次相同中斷來到我拋棄掉第三次來的時候才響應,這樣的好處是可以非常好的控制外設,按鍵識別的很穩定
在EXTI3中加入了中斷標誌位判斷,其他中斷函數沒有加上,爲了證明可加可不加!最好還是加上,養成好習慣!
外部中斷主函數main.c
#include “led.h”
#include “delay.h”
#include “sys.h”
#include “stdio.h”
#include “key.h”
#include “exti.h”
#include “beep.h”
int main(void)
{
delay_init();
LED_Init();
exti_init();
KEY_Init();
BEEP_Init();
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
while(1)
{
delay_ms(1000);
}
}
沒什麼好講的,實現都在中斷函數裏,主函數就一個死循環!
其他
中斷優先級是我們需要了解的,大家不要忽略,我在編譯的時候遇到過這樣的問題,明明庫函數在我的文件當中,還能找得到,卻提示我有庫函數缺失,這時候我在添加源文件的USER裏添加了stm32f10x_exti.c解決了這一問題,在裏面我沒有找到此源文件的存在,所以大家經常在這裏面找問題
希望能夠幫助大家,如果你們還有更好的方法希望可以說出你的想法!
謝謝

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