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);
}

你可能感兴趣的:(嵌入式)