STM32之LED按键中断

继LED轮询之后https://blog.csdn.net/panrenqiu/article/details/79776083,今天写一个LED按键中断程序来记录一下学习情况。

***************************************************************************************************************************************

开发板   :奋斗STM32

CPU        :STM32F103

开发环境:keil uVsion4

****************************************************************************************************************************************

前言:本文主要是通过按键中断,实现当按下按键时,LED灯灭,释放按键时,LED灯亮。(不过我设置LED的起始状态为亮,也就是上电就点亮了LED灯。)

下面看main.c


#include "stm32f10x.h"
#include "led.h"
#include "exti.h" 
 
int main(void) 
{ 
    init_led_gpio();
	  turn_led(LED1,ON);
    /*exti line config */
	
	  EXTI_PC_Config();
	
  while(1) 
  { 
      ;  
  } 
}  

led.c

#include "led.h"

led_gpio_t        leds_gpio[MAX_LED] =
{
		{LED1, GPIOB, GPIO_Pin_5}, /* LED1 用的GPB5 */
		{LED2, GPIOD, GPIO_Pin_6}, /* LED2 用的GPD6 */
		{LED3, GPIOD, GPIO_Pin_3}, /* LED3 用的GPD3 */		
};


void init_led_gpio(void)
{
	int                i;
	GPIO_InitTypeDef   GPIO_InitStructure;

	/* 使能PB和PD组 GPIO的时钟 */
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOD , ENABLE);	
	
	/*设置 PB5(LED1), PD6(LED2), PD3(LED3)为 GPIO 输出推免模式,口线翻转速度为50MHz */
	for(i=0; i<MAX_LED; i++)
	{
		/*设置 PB5(LED1)为 GPIO 输出推免模式,口线翻转速度为50MHz */
		GPIO_InitStructure.GPIO_Pin = leds_gpio[i].pin;				     
		GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
		GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
		GPIO_Init(leds_gpio[i].group, &GPIO_InitStructure);						
  }
}

void turn_led(int which, int cmd)
{
   if(which<0 || which> MAX_LED )
		 return;
	 
	 if(OFF == cmd)
		 GPIO_ResetBits(leds_gpio[which].group, leds_gpio[which].pin);
	 else
		 GPIO_SetBits(leds_gpio[which].group, leds_gpio[which].pin);
}

exti.c

#include "stm32f10x.h"
#include "exti.h"
#include "led.h"

void EXTI_PC_Config(void)
{ 
    EXTI_InitTypeDef EXTI_InitStructure;
    GPIO_config(); 
    NVIC_Configuration();	
    
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC|RCC_APB2Periph_AFIO, ENABLE);
   
  EXTI_InitStructure.EXTI_Line = EXTI_Line5;  
  EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; 
  EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; 
  EXTI_InitStructure.EXTI_LineCmd = ENABLE; 
  EXTI_Init(&EXTI_InitStructure); 
}
static void NVIC_Configuration(void)
{
	NVIC_InitTypeDef NVIC_InitStructure;
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);  
  NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn ;   
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; 
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; 
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;   
  NVIC_Init(&NVIC_InitStructure); 
} 
   
void GPIO_config(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	/* EXTI line gpio config (PE) */  
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;   
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 
  GPIO_Init(GPIOC, &GPIO_InitStructure);  
  GPIO_EXTILineConfig(GPIO_PortSourceGPIOC, GPIO_PinSource5);
}
  void EXTI9_5_IRQHandler(void) 
{ 
    static uint8_t        led1_status = OFF; 
     
    if(EXTI_GetITStatus(EXTI_Line5) != RESET) 
    { 
        led1_status ^= 1;     
        turn_led(LED1, led1_status); 
//        EXTI_ClearITPendingBit(EXTI_Line5); 
  } 
}   

我写的按键中断程序实现的功能是:按下按键K1,LED1由亮变灭,释放按键LED1又变亮。(按键K1对应PC5管脚,LED1对应PB5管脚)。
下面我们来具体分析本文的代码

1)初始化时钟和配置LED 

void init_led_gpio(void)
{
	int                i;
	GPIO_InitTypeDef   GPIO_InitStructure;

	/* 使能PB和PD组 GPIO的时钟 */
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOD , ENABLE);	
	
	/*设置 PB5(LED1), PD6(LED2), PD3(LED3)为 GPIO 输出推免模式,口线翻转速度为50MHz */
	for(i=0; i<MAX_LED; i++)
	{
		/*设置 PB5(LED1)为 GPIO 输出推免模式,口线翻转速度为50MHz */
		GPIO_InitStructure.GPIO_Pin = leds_gpio[i].pin;				     
		GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
		GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
		GPIO_Init(leds_gpio[i].group, &GPIO_InitStructure);						
  }
}

2.配置中断优先级


static void NVIC_Configuration(void)
{
	NVIC_InitTypeDef NVIC_InitStructure;
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);  
  NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn ;   
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; 
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; 
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;   
  NVIC_Init(&NVIC_InitStructure); 
} 

这个中断优先级的设置可以随便设置,原因是我创建的工程中只用到了按键中断,没有其他中断,当然如果有多个中断,就得按照中断向量表来设置
3. 配置外部中断线

EXTI_InitStructure.EXTI_Line = EXTI_Line5;  
  EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; 
  EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; 
  EXTI_InitStructure.EXTI_LineCmd = ENABLE; 
  EXTI_Init(&EXTI_InitStructure); 

4.中断处理函数

void EXTI9_5_IRQHandler(void) 
{ 
    static uint8_t        led1_status = OFF; 
     
    if(EXTI_GetITStatus(EXTI_Line5) != RESET) 
    { 
        led1_status ^= 1;     
        turn_led(LED1, led1_status); 
//        EXTI_ClearITPendingBit(EXTI_Line5); 
  } 
}   
这里的中断处理函数我们通常最好是放在 stm32f10x_it.c这个文件,这是官方提供的一个用来放所有外部中断处理函数的文件,当主程序在执行程序时,如果发生中断,cpu会立即跳到这里来执行中断处理函数,这里因为只有按键中断,还体现不出这样做的好处,如果是一个大工程,用到多个中断时,把中断函数统一放在这个文件中的话,可以大大优化代码,当然这里也可以放在exti.c文件中。

猜你喜欢

转载自blog.csdn.net/panrenqiu/article/details/79818801