上一篇简单写了一下中断的理论,给了一个定时器的例子。
这一篇主要写一下外部中断的例子。这个例子中使用了两个外部中断,使用多个的话道理差不多。
还是对照着理论把程序写出来。
配置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);
}