引言
在以前的课程中,我们学习过使用KEY来控制LED小灯的亮灭,那是通过检测IO口电平的方式实现的;而我们这节课需要通过中断的方式来进行检测。
建立工程
套用野火 “1-书籍配套例程\5-GPIO输出—使用固件库点亮LED灯” 的模板, 完成初始工程的建立。
之后我们在“USER”文件夹中新建“KEY”文件夹, 再在“KEY”文件夹下建立“bsp_exti.c”及“bsp_exti.h”文件。
打开Keil, 我们将“bsp_exti.c”文件添加到工程中的USER中去,再在“Options for Target”中把“bsp_exti.h”的路径添加进去,具体不再赘述。
编写代码
对于bsp_exti.h文件, 在野火的例程中使用了大量的宏将所需的参数取了别名, 方便我们进行移植,所以我们就将其直接复制过来。
/*********************** bsp_exti.h程序源代码 *************************/
#ifndef _BSP_EXTI_H
#define _BSP_EXTI_H
#include "stm32f4xx.h"
//引脚定义
/*******************************************************/
#define KEY1_INT_GPIO_PORT GPIOA
#define KEY1_INT_GPIO_CLK RCC_AHB1Periph_GPIOA
#define KEY1_INT_GPIO_PIN GPIO_Pin_0
#define KEY1_INT_EXTI_PORTSOURCE EXTI_PortSourceGPIOA
#define KEY1_INT_EXTI_PINSOURCE EXTI_PinSource0
#define KEY1_INT_EXTI_LINE EXTI_Line0
#define KEY1_INT_EXTI_IRQ EXTI0_IRQn
#define KEY1_IRQHandler EXTI0_IRQHandler
#define KEY2_INT_GPIO_PORT GPIOC
#define KEY2_INT_GPIO_CLK RCC_AHB1Periph_GPIOC
#define KEY2_INT_GPIO_PIN GPIO_Pin_13
#define KEY2_INT_EXTI_PORTSOURCE EXTI_PortSourceGPIOC
#define KEY2_INT_EXTI_PINSOURCE EXTI_PinSource13
#define KEY2_INT_EXTI_LINE EXTI_Line13
#define KEY2_INT_EXTI_IRQ EXTI15_10_IRQn
#define KEY2_IRQHandler EXTI15_10_IRQHandler
/*******************************************************/
void EXTI_Key_Config(void);
#endif /* _BSP_EXTI_H */
/*********************** bsp_exti.c程序源代码 *************************/
#include "bsp_exti.h"
/* Go to line 36*/
/**
* @brief 配置嵌套向量中断控制器NVIC
* @note 关于NVIC抢占优先级与子优先级的分配,可以参考STM32F4xx_StdPeriph_Driver\misc.c文件中
* 的 How to configure Interrupts using driver 里面有详细的使用方法
* @param 无
* @retval 无
*/
static void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
/* 配置NVIC为优先级组1 */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
/* 配置中断源:按键1 */
NVIC_InitStructure.NVIC_IRQChannel = KEY1_INT_EXTI_IRQ;
/* 配置抢占优先级:1 */
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; //参考misc.c
/* 配置子优先级:1 */
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //参考misc.c
/* 使能中断通道 */
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
/* 配置中断源:按键2,其他使用上面相关配置 */
NVIC_InitStructure.NVIC_IRQChannel = KEY2_INT_EXTI_IRQ;
NVIC_Init(&NVIC_InitStructure);
}
/* Go to line 66 */
/**
* @brief Configure Nested Vector Interrupt Controller(NVIC)
* @param None
* @retval None
*/
void EXTI_Key_Config(void)
{
/* initialize GPIO, EXTI structure */
GPIO_InitTypeDef GPIO_InitStructure;
EXTI_InitTypeDef EXTI_InitStructure;
/* Step 1: Initialize the GPIO which will connect to the EXTI */
/* Enable KEY_GPIO clock*/
RCC_AHB1PeriphClockCmd(KEY1_INT_GPIO_CLK | KEY2_INT_GPIO_CLK, ENABLE);
/* Enable SYSCFG clock */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE); //如果使用外部中断则需要开启该时钟
/* Configure KEY1 */
GPIO_InitStructure.GPIO_Pin = KEY1_INT_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(KEY1_INT_GPIO_PORT, &GPIO_InitStructure);
/* Configure KEY2 */
GPIO_InitStructure.GPIO_Pin = KEY2_INT_GPIO_PIN;
GPIO_Init(KEY2_INT_GPIO_PORT, &GPIO_InitStructure);
/* Step 2: Configure the NVIC */
NVIC_Configuration(); //Go to line 5
/* Step 3: Configure the EXTI */
/* KEY1 */
/* Connect EXTI interrupt source to KEY1 pin*/
SYSCFG_EXTILineConfig(KEY1_INT_EXTI_PORTSOURCE, KEY1_INT_EXTI_PINSOURCE); //改为KEY1的源, 然后再配置
/* Initialize EXTI structure */
EXTI_InitStructure.EXTI_Line = KEY1_INT_EXTI_LINE;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
EXTI_Init(&EXTI_InitStructure);
/* KEY2 */
/* Connect EXTI interrupt source to KEY2 pin*/
SYSCFG_EXTILineConfig(KEY2_INT_EXTI_PORTSOURCE, KEY2_INT_EXTI_PINSOURCE); //改为KEY2的源, 然后再配置
/* Initialize EXTI structure */
EXTI_InitStructure.EXTI_Line = KEY2_INT_EXTI_LINE;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
EXTI_Init(&EXTI_InitStructure);
/* Step 4: Write interrupt service function */
/* Go to "stm32f4xx_it.c" */
}
stm32f4xx_it.c 中,上半部分是去响应事件的函数, 是内核的东西;下半部分是去响应外部中断的函数, 我们编写代码的话应该由此编写。
/*********************** stm32f4xx_it.c程序源代码 *************************/
/**
******************************************************************************
* @file FMC_SDRAM/stm32f4xx_it.c
* @author MCD Application Team
* @version V1.0.1
* @date 11-November-2013
* @brief Main Interrupt Service Routines.
* This file provides template for all exceptions handler and
* peripherals interrupt service routine.
******************************************************************************
* @attention
*
* <h2><center>© COPYRIGHT 2013 STMicroelectronics</center></h2>
*
* Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/software_license_agreement_liberty_v2
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "stm32f4xx_it.h"
#include "bsp_exti.h"
#include "bsp_led.h"
/** @addtogroup STM32F429I_DISCOVERY_Examples
* @{
*/
/** @addtogroup FMC_SDRAM
* @{
*/
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
/******************************************************************************/
/* Cortex-M4 Processor Exceptions Handlers */
/******************************************************************************/
/**
* @brief This function handles NMI exception.
* @param None
* @retval None
*/
void NMI_Handler(void)
{
}
/**
* @brief This function handles Hard Fault exception.
* @param None
* @retval None
*/
void HardFault_Handler(void)
{
/* Go to infinite loop when Hard Fault exception occurs */
while (1)
{}
}
/**
* @brief This function handles Memory Manage exception.
* @param None
* @retval None
*/
void MemManage_Handler(void)
{
/* Go to infinite loop when Memory Manage exception occurs */
while (1)
{}
}
/**
* @brief This function handles Bus Fault exception.
* @param None
* @retval None
*/
void BusFault_Handler(void)
{
/* Go to infinite loop when Bus Fault exception occurs */
while (1)
{}
}
/**
* @brief This function handles Usage Fault exception.
* @param None
* @retval None
*/
void UsageFault_Handler(void)
{
/* Go to infinite loop when Usage Fault exception occurs */
while (1)
{}
}
/**
* @brief This function handles Debug Monitor exception.
* @param None
* @retval None
*/
void DebugMon_Handler(void)
{}
/**
* @brief This function handles SVCall exception.
* @param None
* @retval None
*/
void SVC_Handler(void)
{}
/**
* @brief This function handles PendSV_Handler exception.
* @param None
* @retval None
*/
void PendSV_Handler(void)
{}
/**
* @brief This function handles SysTick Handler.
* @param None
* @retval None
*/
void SysTick_Handler(void)
{}
/******************************************************************************/
/* STM32F4xx Peripherals Interrupt Handlers */
/* Add here the Interrupt Handler for the used peripheral(s) (PPP), for the */
/* available peripheral interrupt handler's name please refer to the startup */
/* file (startup_stm32f429_439xx.s). */
/******************************************************************************/
/**
* @}
*/
void KEY1_IRQHandler(void)
{
//确保是否产生了EXTI Line中断
if(EXTI_GetITStatus(KEY1_INT_EXTI_LINE) != RESET)
{
// LED1 取反
LED1_TOGGLE; //定义在bsp_led.h中
//清除中断标志位
EXTI_ClearITPendingBit(KEY1_INT_EXTI_LINE);
}
}
void KEY2_IRQHandler(void)
{
//确保是否产生了EXTI Line中断
if(EXTI_GetITStatus(KEY2_INT_EXTI_LINE) != RESET)
{
// LED2 取反
LED2_TOGGLE;
//清除中断标志位
EXTI_ClearITPendingBit(KEY2_INT_EXTI_LINE);
}
}
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
/*********************** main.c程序源代码 *************************/
#include "stm32f4xx.h"
#include "bsp_exti.h"
#include "bsp_led.h"
void Delay(__IO u32 nCount);
/**
* @brief KEY1点击一次使得LED1电平翻转一次,
* KEY2点击一次使得LED2电平翻转一次。
* @param 无
* @retval 无
*/
int main(void)
{
/* LED 端口初始化 */
LED_GPIO_Config();
/* KEY的EXTI初始化 */
EXTI_Key_Config();
/* 控制LED灯 */
while (1)
{
}
}
void Delay(__IO uint32_t nCount) //简单的延时函数
{
for(; nCount != 0; nCount--);
}
/*********************************************END OF FILE**********************/