實驗效果:用外部中斷,實作PA1上接按鍵,選擇上升沿觸發中斷,中斷PB1上閃爍的LED,
先來看看配置外部中斷的整體代碼,然后再一個函式一個函式的解釋
[color=#00FFFF]#include "exti.h"
/*
初始化總中斷NVIC
*/
static void NVIC_Configur(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
NVIC_InitStructure.NVIC_IRQChannel=EXTI1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
/*************************/
/*
初始化GPIO口,GPIOA_PIN1
*/
void GPIO_Configur(void)
{
GPIO_InitTypeDef GPIO_InitStructure ; //命名GPIO初始化結構體
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//使能時鐘
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_1;//選擇PIN
GPIO_InitStructure.GPIO_Mode= GPIO_Mode_IN_FLOATING; //懸浮輸入
GPIO_Init(GPIOA,&GPIO_InitStructure);//呼叫初始化函式
}
/**************************/
/*
告訴GPIO那個引腳作為外部中斷引腳
*/
void AFIO_Configur(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//使能AFIO的時鐘
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource1);
}
/******************************/
/*
配置EXTI
*/
void EXTI_Configur(void)
{
NVIC_Configur();
GPIO_Configur();
AFIO_Configur();
EXTI_InitTypeDef EXTI_InitStructure;//命名ETTI初始化結構體
EXTI_InitStructure.EXTI_Line=EXTI_Line1;
EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Rising;
EXTI_InitStructure.EXTI_LineCmd=ENABLE;
EXTI_Init(&EXTI_InitStructure);
}[/color]
****************************************************************************************************
****************************************************************************************************
****************************************************************************************************
先來看看第一個函式
static void NVIC_Configur(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
NVIC_InitStructure.NVIC_IRQChannel=EXTI1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_Init(&NVIC_InitStructure);
}[/align]
為什么要撰寫這段函式呢?
先來看看NVIC的全稱(Nested vectoredinterrupt controller)即嵌套向量中斷控制器
由于STM32的中斷系統非常強大,每個GPIO都能產生中斷,所以需要一個能管理這些中斷的控制器
下面是32的中斷和事件,我只放出了一部分,還有很多可以在STM參考手冊上看


那NVIC到底是怎么管理這些中斷的,我們從函式一個一個看
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
32的中斷優先級是可以自己設定的,所以我們要先給他配置優先級,所以這是給他的優先級選組的函式,為什么要選組先這個表
左邊NVIC_IRQChannelPreemptionPriority是主優先級,右邊NVIC_IRQChannelSubPriority是次優先級
每個組都有對應的主次優先級的選擇范圍,32會先比較主優先級,如果主優先級都一樣,會比較次優先級,如果主次都一樣,會用32自己配置的優先級。
NVIC_InitStructure.NVIC_IRQChannel=EXTI1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
這四段函式,開始配置NVIC結構體的成員。
第一段函式,是選擇你要用的中斷的名字 ,名字在stm32f10x.h檔案中找(隨便補充一下,關于NVIC的函式可以在misc.h中找到)
EXTI1有0-15個,分別對應16個IO口,我們要用PA1,所以就選EXTI1

第二,三段函式,就是選擇中斷的主次優先級
第四段使能NVIC
然后初始化結構體,命名初始化,這些庫函式套路程式就不解釋了
配置GPIO,凡是要用GPIO都要配置它,要注意輸入的時候懸浮輸入和不用配置頻率
void GPIO_Configur(void)
{
GPIO_InitTypeDef GPIO_InitStructure ; //命名GPIO初始化結構體
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//使能時鐘
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_1;//選擇PIN
GPIO_InitStructure.GPIO_Mode= GPIO_Mode_IN_FLOATING; //懸浮輸入
GPIO_Init(GPIOA,&GPIO_InitStructure);//呼叫初始化函式
}
/**************************/
/*
告訴GPIO那個引腳作為外部中斷引腳
*/
void AFIO_Configur(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//使能AFIO的時鐘
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource1);
}
PS:記得使能AFIO的時鐘
最后一步配置外部中斷EXTI
void EXTI_Configur(void)
{
NVIC_Configur();
GPIO_Configur();
AFIO_Configur();
EXTI_InitTypeDef EXTI_InitStructure;//命名ETTI初始化結構體
EXTI_InitStructure.EXTI_Line=EXTI_Line1;//初始化那個EXTI
EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt;//選擇中斷模式
EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Rising;//選擇上升沿觸發
EXTI_InitStructure.EXTI_LineCmd=ENABLE;
EXTI_Init(&EXTI_InitStructure);
}
然后在主函式中,寫中斷服務函式
在51中撰寫中斷服務函式的名字可以直接撰寫,只要后面加個入口標志就行了
但是32已經有編好的中斷服務函式,在啟動檔案里面可以找到

void EXTI1_IRQHandler(void)
{
if(EXTI_GetITStatus(EXTI_Line1)==1) /*如果一條線上有PA0 PB0,如何判斷是那個觸發的中斷?
{ 先判斷總線,再判斷IO口的電平(操作暫存器) */
Delay(3000000);
EXTI_ClearFlag(EXTI_Line1);/*清除觸發標志*/
}
}
呼叫函式EXTI_GetITStatus(),如果有外部中斷被觸發,函式會回傳一個1
/*如果一條線上有PA0 PB0,如何判斷是那個觸發的中斷?這是野火教學視頻留下的一個問題
我覺得 先判斷總線,再判斷IO口的電平(操作暫存器) 就可以了*/
這個題目就是讓我們明白,不要只會呼叫庫函式,還要懂得,這些庫函式操作了那些暫存器。
還有就是EXTI_ClearFlag(EXTI_Line1);/*清除觸發標志*/,這個函式,EXTI_GetITStatus()回傳一個1本質是吧掛起暫存器置1了
然后它不會自動清0;所以要用EXTI_Clear
uj5u.com熱心網友回復:
博主,這貼很良心,新手小白的我看了后,很快就懂了,望日更。uj5u.com熱心網友回復:
博主,這貼很良心,新手小白的我看了后,很快就懂了,望日更。轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/272389.html
標籤:單片機/工控
上一篇:VerilogHDL:用三個2:4譯碼器instance和一組三輸入與門組成一個6:64譯碼器
下一篇:點亮LED燈
