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,灯不亮,松开后灯亮,再按下,灯不灭,松开后灯灭,如此循环(下降沿触发)

 

posted @ 2018-05-29 23:41  半生戎马,共话桑麻、  阅读(353)  评论(0)    收藏  举报
levels of contents