1. 程式人生 > >stm32中斷學習篇(2)——以外部中斷為例與多箇中斷的使用

stm32中斷學習篇(2)——以外部中斷為例與多箇中斷的使用

上一篇簡單寫了一下中斷的理論,給了一個定時器的例子。
這一篇主要寫一下外部中斷的例子。這個例子中使用了兩個外部中斷,使用多個的話道理差不多。

還是對照著理論把程式寫出來。

配置GPIO的部分就不說了。程式在後面給出,有詳細註釋。
直接開始說配置NVIC和EXTI。

Stm32的這些配置都是以結構體的形式進行的。
EXTI配置的是EXTI_InitTypeDef這個結構體,其定義如下:
*typedef struct
{
uint32_t EXTI_Line; /!< Specifies the EXTI lines to be enabled or disabled. This parameter can be any combination of @ref EXTI_Lines

/

EXTIMode_TypeDef EXTI_Mode; /*!< Specifies the mode for the EXTI lines.
This parameter can be a value of @ref EXTIMode_TypeDef */
EXTITrigger_TypeDef EXTI_Trigger; /*!< Specifies the trigger signal active edge for the EXTI lines.
This parameter can be a value of @ref EXTIMode_TypeDef */
FunctionalState EXTI_LineCmd; /*!< Specifies the new state of the selected EXTI lines.
This parameter can be set either to ENABLE or DISABLE */
}EXTI_InitTypeDef;*

// 首先要清除線上的掛起位:
EXTI_ClearITPendingBit(EXTI_Line1);
EXTI_ClearITPendingBit(EXTI_Line2);

// 選擇外部中斷線路:
EXTI_InitStructure.EXTI_Line=EXTI_Line1;
EXTI_InitStructure.EXTI_Line=EXTI_Line2;

// 設定中斷模式為外部中斷觸發:
EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt;

// 設定中斷觸發方式:
EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Falling;

// 中斷使能:
EXTI_InitStructure.EXTI_LineCmd=ENABLE;

// 之後要使這些配置生效:
EXTI_Init(&EXTI_InitStructure);

// 並載入到相應的IO上:
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource1);

至此中斷配置結束。
下面開始配置NVIC。

這也是一個結構體,同樣的:
*typedef struct
{
uint8_t NVIC_IRQChannel; /*!< Specifies the IRQ channel to be enabled or disabled.
This parameter can be a value of @ref IRQn_Type
(For the complete STM32 Devices IRQ Channels list, please
refer to stm32f10x.h file) */
uint8_t NVIC_IRQChannelPreemptionPriority; /*!< Specifies the pre-emption priority
for the IRQ channel
specified in NVIC_IRQChannel. This parameter can be a value
between 0 and 15 as described in the table
@ref NVIC_Priority_Table */
uint8_t NVIC_IRQChannelSubPriority; /*!< Specifies the subpriority level
for the IRQ channel specified
in NVIC_IRQChannel. This parameter can be a value
between 0 and 15 as described in the table
@ref NVIC_Priority_Table */
FunctionalState NVIC_IRQChannelCmd; /*!< Specifies whether the IRQ channel
defined in NVIC_IRQChannel
will be enabled or disabled.
This parameter can be set either to ENABLE or DISABLE */
} NVIC_InitTypeDef;*

// 首先初始化:
NVIC_InitTypeDef NVIC_InitStructure;

// 設定優先順序:
// 搶先優先順序0個,子優先順序4位(16個)
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);

// 將中斷掛到外部中斷線上:
NVIC_InitStructure.NVIC_IRQChannel=EXTI1_IRQn;

// 設定搶先優先順序和子優先順序,這裡只用到了子優先順序:
NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;

// 使能外部中斷通道請求:
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;

// 使配置生效:
NVIC_Init(&NVIC_InitStructure);

下面開始寫中斷處理函式,多箇中斷處理函式的函式體要分開寫。
// 先判斷是否有中斷申請:
if(EXTI_GetITStatus(EXTI_Line1)!=RESET)

// 之後就可以隨意新增想要進行的中斷動作了。
// 動作結束後,要清除標誌位
EXTI_ClearFlag(EXTI_Line1);

Main函式中呼叫上述四個函式,這樣中斷程式就結束了。

最後給出原始碼:

/*程式名:外部中斷點led燈*/
/*功能:       PA1下降沿觸發點亮D2(PB8)
                    PA2上升沿觸發點亮D3(PB9)*/
/*日期:       2016.05.02*/
/*作者:       穆沛*/

#include"stm32f10x.h"
//配置系統時鐘************************************************************
void RCC_Configuration(void)
{
    /* TIM2 clock enable */ 
 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); 

 /* GPIOB clock enable */ 
 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); 

}
//配置GPIO函式************************************************
//功能:配置GPIO的輸入輸出模式
void GPIO_Configuration(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;                     //定義一個IO埠引數結構體
    RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB , ENABLE);  //使能PB埠時鐘                                                 
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_14 | GPIO_Pin_15;//初始化PB8.9.14.15埠
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  //翻轉速率50Mhz
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;   //推免輸出方式
    GPIO_Init(GPIOB, &GPIO_InitStructure);             //初始化PB8.9.14.15
    GPIO_SetBits(GPIOB,GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_14 | GPIO_Pin_15);//PB8.9.14.15設定高,燈滅

}

//外部中斷函式*************************************************************************************
void EXTI_Configuration(void)
{
    EXTI_InitTypeDef EXTI_InitStructure;                  //初始化外部中斷暫存器

    EXTI_ClearITPendingBit(EXTI_Line1);                   //清除線1 IO口中斷清除掛起位(清除中斷標誌位)
    EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt;     //設定外部中斷觸發(另一種是事件觸發)
    EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Falling; //設定中斷觸發方式:下降沿觸發方式
    EXTI_InitStructure.EXTI_Line=EXTI_Line1;              //選擇中斷線路為1(即選擇那個IO作為中斷輸入)
    EXTI_InitStructure.EXTI_LineCmd=ENABLE;               //使能外部中斷
    EXTI_Init(&EXTI_InitStructure);                       //初始化
    GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource1); //將GPIOA1掛到中斷上



    EXTI_ClearITPendingBit(EXTI_Line2);                   //清除線2 IO口中斷清除掛起位(清除中斷標誌位)
    EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt;     
    EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Rising; //設定中斷觸發方式:上升沿觸發方式
    EXTI_InitStructure.EXTI_Line=EXTI_Line2;              //選擇中斷線路為2
    EXTI_InitStructure.EXTI_LineCmd=ENABLE;               //使能外部中斷
    EXTI_Init(&EXTI_InitStructure);                       //初始化
    GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource2); //將GPIOA2掛到中斷上

}

//中斷分組函式***************************************************************
void NIVC_Configuration(void)
{
    NVIC_InitTypeDef NVIC_InitStructure;                  //初始化中斷分組函式

//NVIC_PriorityGroupConfig:設定優先順序分組(下面一句)
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);        //設定優先順序:搶先優先順序0個,子優先順序4位(16個)
    NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;        // 使能設定的外部中斷通道請求

    NVIC_InitStructure.NVIC_IRQChannel=EXTI1_IRQn;     //將中斷掛到PA1腳外部中斷線1上
    NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;     //設定子優先順序1
    NVIC_Init(&NVIC_InitStructure);                      //初始化



    NVIC_InitStructure.NVIC_IRQChannel=EXTI2_IRQn;     //將中斷掛到PA2腳外部中斷線2上
    NVIC_InitStructure.NVIC_IRQChannelSubPriority=2;     //設定子優先順序2,要低於前面的子優先順序1
    NVIC_Init(&NVIC_InitStructure);                      //初始化


}


//中斷服務函式********************************************************
void EXTI1_IRQHandler(void)
{
    if(EXTI_GetITStatus(EXTI_Line1)!=RESET)//有中斷申請
    {
        //新增中斷處理函式
        GPIO_ResetBits(GPIOB,GPIO_Pin_8);     //點亮led
        EXTI_ClearFlag(EXTI_Line1);          //清除標誌中斷位
        EXTI_ClearITPendingBit(EXTI_Line1);  //清除外部中斷線1的掛起位
    }
}

void EXTI2_IRQHandler(void)
{
    if(EXTI_GetITStatus(EXTI_Line2)!=RESET)
    {
        //新增中斷處理函式
        GPIO_ResetBits(GPIOB,GPIO_Pin_9); 
        EXTI_ClearFlag(EXTI_Line2);          
        EXTI_ClearITPendingBit(EXTI_Line2);  //清除外部中斷線2的掛起位
    }
}


//主函式***********************************************************************
int main(void)
{
    RCC_Configuration();                   //呼叫系統時鐘函式
    GPIO_Configuration();                  //呼叫GPIO
    NIVC_Configuration();
    EXTI_Configuration();
    while(1);
}