day14:外部中断
工程结构:


=========================================================
bsp_exti_key.c
#include "./key/bsp_exti_key.h"
/* 外部中断处理 */
static void NVIC_Config(void) // 用static修饰函数,表示只能在本文件中使用
{
NVIC_InitTypeDef NVIC_InitStruct;
/* ------------- 第一步:配置中断优先级分组 ------------- */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); // 表示主优先级用1个位表示,子优先级用3个位表示,共1个位
/* KEY1 */
/* ------------- 第二步:配置NVIC的初始化结构体 ------------- */
NVIC_InitStruct.NVIC_IRQChannel = KEY1_EXTI_IRQN;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1; // 主优先级用1个位表示
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0; // 子优先级用3个位表示,2^3=8,即数字0-8都可以
/* ------------- 第三步:调用NVIC的初始化函数把配置好的结构体成员写到寄存器里面 ------------- */
NVIC_Init(&NVIC_InitStruct); // 初始化优先级
/* KEY2 */
/* ------------- 第二步:配置NVIC的初始化结构体 ------------- */
NVIC_InitStruct.NVIC_IRQChannel = KEY2_EXTI_IRQN;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1; // 主优先级用1个位表示
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1; // 子优先级用3个位表示,2^3=8,即数字0-8都可以
/* ------------- 第三步:调用NVIC的初始化函数把配置好的结构体成员写到寄存器里面 ------------- */
NVIC_Init(&NVIC_InitStruct); // 初始化优先级
}
/* KEY的GPIO口的初始化 */
void Exti_Key_Config(void)
{
/* 外设结构体 */
GPIO_InitTypeDef GPIO_InitStruct;
EXTI_InitTypeDef EXTI_InitStruct;
// 初始化中断处理函数
NVIC_Config();
/* ------------- 第一步:初始化要连接到EXTI的GPIO ------------- */
/* 打开外设的时钟:KEY1和KEY2都打开 */
RCC_APB2PeriphClockCmd(KEY1_EXTI_GPIO_CLK|KEY2_EXTI_GPIO_CLK, ENABLE);
/* KEY1 */
GPIO_InitStruct.GPIO_Pin = KEY1_EXTI_GPIO_PIN;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(KEY1_EXTI_GPIO_PORT, &GPIO_InitStruct);
/* KEY2 */
GPIO_InitStruct.GPIO_Pin = KEY2_EXTI_GPIO_PIN;
GPIO_Init(KEY2_EXTI_GPIO_PORT, &GPIO_InitStruct);
/* ------------- 第二步:初始化EXTI外设 ------------- */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); // 打开AFIO的时钟
/* KEY1 */
GPIO_EXTILineConfig(KEY1_EXTI_GPIO_PORTSOURCE, KEY1_EXTI_GPIO_PINSOURCE); // 选择输入线
EXTI_InitStruct.EXTI_Line = KEY1_EXTI_EXTI_LINE;
EXTI_InitStruct.EXTI_LineCmd = ENABLE; // 使能
EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt; // 中断模式
EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Rising; // 触发方式:上升沿触发
EXTI_Init(&EXTI_InitStruct); // 初始化KEY1的EXTI
/* KEY2 */
GPIO_EXTILineConfig(KEY2_EXTI_GPIO_PORTSOURCE, KEY2_EXTI_GPIO_PINSOURCE); // 选择输入线
EXTI_InitStruct.EXTI_Line = KEY2_EXTI_EXTI_LINE;
EXTI_InitStruct.EXTI_LineCmd = ENABLE; // 使能
EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt; // 中断模式
EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Falling; // 触发方式:上升沿触发
EXTI_Init(&EXTI_InitStruct); // 初始化KEY1的EXTI
}
bsp_exti_key.h
#ifndef __BSP_EXTI_KEY_H__ #define __BSP_EXTI_KEY_H__ #include "stm32f10x.h" /* KEY1的端口成员 */ #define KEY1_EXTI_GPIO_CLK RCC_APB2Periph_GPIOA #define KEY1_EXTI_GPIO_PORT GPIOA #define KEY1_EXTI_GPIO_PIN GPIO_Pin_0 /* KEY1的输入线 */ #define KEY1_EXTI_GPIO_PORTSOURCE GPIO_PortSourceGPIOA #define KEY1_EXTI_GPIO_PINSOURCE GPIO_PinSource0 #define KEY1_EXTI_EXTI_LINE EXTI_Line0 /* KEY1的NVIC中断控制处理 */ #define KEY1_EXTI_IRQN EXTI0_IRQn /* KEY1的中断服务函数 */ #define KEY1_EXTI_IRQHANDLER EXTI0_IRQHandler /* KEY2的端口成员 */ #define KEY2_EXTI_GPIO_CLK RCC_APB2Periph_GPIOC #define KEY2_EXTI_GPIO_PORT GPIOC #define KEY2_EXTI_GPIO_PIN GPIO_Pin_13 /* KEY2的输入线 */ #define KEY2_EXTI_GPIO_PORTSOURCE GPIO_PortSourceGPIOC #define KEY2_EXTI_GPIO_PINSOURCE GPIO_PinSource13 #define KEY2_EXTI_EXTI_LINE EXTI_Line13 /* KEY2的NVIC中断控制处理 */ #define KEY2_EXTI_IRQN EXTI15_10_IRQn /* KEY的中断初始化函数 */ void Exti_Key_Config(void); /* KEY2的中断服务函数 */ #define KEY2_EXTI_IRQHANDLER EXTI15_10_IRQHandler #endif /* __BSP_EXTI_KEY_H__ */
stm32f10x_it.c
/**
******************************************************************************
* @file Project/STM32F10x_StdPeriph_Template/stm32f10x_it.c
* @author MCD Application Team
* @version V3.5.0
* @date 08-April-2011
* @brief Main Interrupt Service Routines.
* This file provides template for all exceptions handler and
* peripherals interrupt service routine.
******************************************************************************
* @attention
*
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
* <h2><center>© COPYRIGHT 2011 STMicroelectronics</center></h2>
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "stm32f10x_it.h"
#include "./key/bsp_exti_key.h"
#include "./led/bsp_led.h"
/** @addtogroup STM32F10x_StdPeriph_Template
* @{
*/
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
/******************************************************************************/
/* Cortex-M3 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 SVCall exception.
* @param None
* @retval None
*/
void SVC_Handler(void)
{
}
/**
* @brief This function handles Debug Monitor exception.
* @param None
* @retval None
*/
void DebugMon_Handler(void)
{
}
/**
* @brief This function handles PendSVC exception.
* @param None
* @retval None
*/
void PendSV_Handler(void)
{
}
/**
* @brief This function handles SysTick Handler.
* @param None
* @retval None
*/
void SysTick_Handler(void)
{
}
/* KEY1中断服务函数 */
void KEY1_EXTI_IRQHANDLER(void)
{
if(EXTI_GetITStatus(KEY1_EXTI_EXTI_LINE) != RESET) // 产生中断
{
LED1_TOGGLE; // 让LED的状态反转
}
/* 清除中断标志位 */
EXTI_ClearITPendingBit(KEY1_EXTI_EXTI_LINE);
}
/* KEY2中断服务函数 */
void KEY2_EXTI_IRQHANDLER(void)
{
if(EXTI_GetITStatus(KEY2_EXTI_EXTI_LINE) != RESET) // 产生中断
{
LED1_TOGGLE; // 让LED的状态反转
}
/* 清除中断标志位 */
EXTI_ClearITPendingBit(KEY2_EXTI_EXTI_LINE);
}
/******************************************************************************/
/* STM32F10x 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_stm32f10x_xx.s). */
/******************************************************************************/
/**
* @brief This function handles PPP interrupt request.
* @param None
* @retval None
*/
/*void PPP_IRQHandler(void)
{
}*/
/**
* @}
*/
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
stm32f10x_it.h
/**
******************************************************************************
* @file Project/STM32F10x_StdPeriph_Template/stm32f10x_it.h
* @author MCD Application Team
* @version V3.5.0
* @date 08-April-2011
* @brief This file contains the headers of the interrupt handlers.
******************************************************************************
* @attention
*
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
* <h2><center>© COPYRIGHT 2011 STMicroelectronics</center></h2>
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __STM32F10x_IT_H
#define __STM32F10x_IT_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "stm32f10x.h"
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/* Exported macro ------------------------------------------------------------*/
/* Exported functions ------------------------------------------------------- */
void NMI_Handler(void);
void HardFault_Handler(void);
void MemManage_Handler(void);
void BusFault_Handler(void);
void UsageFault_Handler(void);
void SVC_Handler(void);
void DebugMon_Handler(void);
void PendSV_Handler(void);
void SysTick_Handler(void);
#ifdef __cplusplus
}
#endif
#endif /* __STM32F10x_IT_H */
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
bsp_led.c
/* 和LED功能模块相关的程序头文件 */
#include "./led/bsp_led.h" /*绝对路径,也可在Options for target中设置头文件*/
/*GPIO初始化*/
void LED_GPIO_Config(void)
{
/*外设结构体*/
GPIO_InitTypeDef GPIO_InitStruct_D4;
/*第一步:打开外设的时钟,看stm32f10x_rcc.c这个文件的RCC_APB2PeriphClockCmd函数介绍*/
RCC_APB2PeriphClockCmd(GPIO_CLK_D4, ENABLE);
/*第二步:配置外设的初始化结构体*/
GPIO_InitStruct_D4.GPIO_Pin = GPIO_PIN_D4; // PC2的那盏LED灯(D4)的引脚
GPIO_InitStruct_D4.GPIO_Mode = GPIO_Mode_Out_PP; // 推挽输出模式
GPIO_InitStruct_D4.GPIO_Speed = GPIO_Speed_10MHz; // 引脚速率
/*第三步:调用外设初始化函数,把配置好的结构体成员写到寄存器里面*/
GPIO_Init(GPIO_PORT_D4, &GPIO_InitStruct_D4);
}
bsp_led.h
/* 和LED功能模块相关的程序 */
#ifndef __BSP_LED_H__
#define __BSP_LED_H__
#include "stm32f10x.h"
/*宏定义*/
#define GPIO_CLK_D4 RCC_APB2Periph_GPIOC // 时钟
#define GPIO_PORT_D4 GPIOC // C端口
#define GPIO_PIN_D4 GPIO_Pin_2 // PC2引脚
/*
digitalTOGGLE(p,i)是参数宏定义,p表示LED的端口号,ODR是数据输出寄存器,
查stm32f10x的官方中文手册的第8.2章的ODR寄存器,要点亮LED,根据原理图,要输出低电平0,
C语言中,^表示异或,即a^b表示a和b不同时输出为1,相同时输出为0,比如0^1=1,1^1=0,0^0=0,
这里为什么操作ODR,p是什么?查看stm32f10x.h文件,搜索GPIO_TypeDef就会明白,
i是LED的引脚对应的位电平,经过digitalTOGGLE(p,i) {p->ODR ^= i;}之后,
第一次p为0,i一直为1,第一次异或结果输出1,第二次输出0,第三次输出1,这样间断输出010101,灯不断亮灭
*/
#define digitalTOGGLE(p,i) {p->ODR ^= i;}
#define LED1_TOGGLE digitalTOGGLE(GPIO_PORT_D4,GPIO_PIN_D4)
/*配置GPIO*/
void LED_GPIO_Config(void);
#endif /*__BSP_LED_H__*/
main.c
/* 实验内容:
* 按下KEY1(上升沿触发),LED灯亮,松开KEY1,灯灭
* 按下KEY2(下降沿触发),LED不亮,松开KEY2,灯亮
*/
/*
* 外部中断的编程要点:
* 1、初始化要连接到EXTI的GPIO
* 2、初始化EXTI用于产生中断/事件
* 3、初始化NVIC,用于处理中断
* 4、编写中断服务函数
* 5、编写main函数
*/
#include "stm32f10x.h"
#include "./key/bsp_exti_key.h"
#include "./led/bsp_led.h"
int main(void)
{
/*GPIO初始化,在程序来到main函数的时候,系统时钟已经配置成72MHz*/
LED_GPIO_Config();
/* KEY的外部中断初始化,等待外部中断的到来,然后去执行中断服务函数 */
Exti_Key_Config();
while(1)
{
}
}
实验现象:
将程序烧录到单片机中,按reset复位键。D4灯亮,按下k1,灯灭,再按,灯亮,如此循环(上升沿触发)
按下k2,灯不亮,松开后灯亮,再按下,灯不灭,松开后灯灭,如此循环(下降沿触发)

浙公网安备 33010602011771号