• STM32(五):STM32指南者-按键控制灯开关实验


    一、采用轮询方式

    放在while(1)循环里,系统不停识别按键状态来控制彩灯

    在这里插入图片描述
    在这里插入图片描述

    1、bsp_key.h
    #ifndef __KEY_H
    #define	__KEY_H
    
    
    #include "stm32f10x.h"
    
    //  引脚定义:检测按键输入的GPIO端口、GPIO引脚号以及GPIO端口时钟封装起来;Key1:PA0;Key2:PC13(可查开发板规格书)
    #define    KEY1_GPIO_CLK     RCC_APB2Periph_GPIOA
    #define    KEY1_GPIO_PORT    GPIOA			   
    #define    KEY1_GPIO_PIN		 GPIO_Pin_0
    
    #define    KEY2_GPIO_CLK     RCC_APB2Periph_GPIOC
    #define    KEY2_GPIO_PORT    GPIOC		   
    #define    KEY2_GPIO_PIN		  GPIO_Pin_13
    
    
     /** 按键按下标置宏
    	*  按键按下为高电平,设置 KEY_ON=1, KEY_OFF=0
    	*  若按键按下为低电平,把宏设置成KEY_ON=0 ,KEY_OFF=1 即可
    	*/
    #define KEY_ON	1
    #define KEY_OFF	0
    
    void Key_GPIO_Config(void);//按键初始化函数
    uint8_t Key_Scan(GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin);
    
    
    #endif /* __KEY_H */
    
    
    
    2、bsp_key.c
    /**
      ******************************************************************************
      * @file    bsp_key.c
      * @author  fire
      * @version V1.0
      * @date    2013-xx-xx
      * @brief   按键应用bsp(扫描模式)
      ******************************************************************************
      * @attention
      *
      * 实验平台:野火 F103-指南者 STM32 开发板 
      * 论坛    :http://www.firebbs.cn
      * 淘宝    :https://fire-stm32.taobao.com
      *
      ******************************************************************************
      */ 
      
    #include "./Key/bsp_key.h"  
    
    /**
      * @brief  配置按键用到的I/O口
      * @param  无
      * @retval 无
      */
    void Key_GPIO_Config(void)
    {
    	GPIO_InitTypeDef GPIO_InitStructure;
    	
    	/*开启按键端口的时钟*/
    	RCC_APB2PeriphClockCmd(KEY1_GPIO_CLK|KEY2_GPIO_CLK,ENABLE);
    	
    	//选择按键的引脚
    	GPIO_InitStructure.GPIO_Pin = KEY1_GPIO_PIN; 
    	// 设置按键的引脚为浮空输入
    	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; // 由于引脚的默认电平受按键电路影响,所以设置成浮空输入。
    	//使用结构体初始化按键
    	GPIO_Init(KEY1_GPIO_PORT, &GPIO_InitStructure);
    	
    	//选择按键的引脚
    	GPIO_InitStructure.GPIO_Pin = KEY2_GPIO_PIN; 
    	//设置按键的引脚为浮空输入
    	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; 
    	//使用结构体初始化按键
    	GPIO_Init(KEY2_GPIO_PORT, &GPIO_InitStructure);	
    }
    
     /*
     * 函数名:Key_Scan
     * 描述  :检测是否有按键按下
     * 输入  :GPIOx:x 可以是 A,B,C,D或者 E
     *		     GPIO_Pin:待读取的端口位 	
     * 输出  :KEY_OFF(没按下按键)、KEY_ON(按下按键)
     */
    uint8_t Key_Scan(GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin)
    {			
    	/*检测是否有按键按下 */
    	if(GPIO_ReadInputDataBit(GPIOx,GPIO_Pin) == KEY_ON )  
    	{	 
    		/*等待按键释放 */
    		while(GPIO_ReadInputDataBit(GPIOx,GPIO_Pin) == KEY_ON);   //一次↓↑输出一次KEY_ON,否则当只有↓没有↑的时候一直在循环不输出
    		return 	KEY_ON;	 
    	}
    	else
    		return KEY_OFF;
    }
    /*********************************************END OF FILE**********************/
    
    
    3、main.c
    /**
      ******************************************************************************
      * @file    main.c
      * @author  fire
      * @version V1.0
      * @date    2013-xx-xx
      * @brief   测试led
      ******************************************************************************
      * @attention
      *
      * 实验平台:野火 F103-指南者 STM32 开发板 
      * 论坛    :http://www.firebbs.cn
      * 淘宝    :https://fire-stm32.taobao.com
      *
      ******************************************************************************
      */ 
    	
    #include "stm32f10x.h"
    #include "./Led/bsp_led.h"
    #include "./Key/bsp_key.h" 
    
    //#define SOFT_DELAY Delay(0x0FFFFF);
    
    //void Delay(__IO u32 nCount); 
    
    /**
      * @brief  主函数
      * @param  无  
      * @retval 无
      */
    int main(void)
    {	
    	/* LED 端口初始化 */
    	LED_GPIO_Config();	 
    
    	
    	/*初始化按键*/
      Key_GPIO_Config();
    	
    //	while (1)
    //	{
    //		LED1_ON;			  // 亮
    //		SOFT_DELAY;
    //		LED1_OFF;		   // 灭
    
    //		LED2_ON;			 // 亮
    //		SOFT_DELAY;
    //		LED2_OFF;		   // 灭
    
    //		LED3_ON;			 // 亮
    //		SOFT_DELAY;
    //		LED3_OFF;		   // 灭	 
    
    //		/*轮流显示 红绿蓝黄紫青白 颜色*/
    //		LED_RED;
    //		SOFT_DELAY;
    //		
    //		LED_GREEN;
    //		SOFT_DELAY;
    //		
    //		LED_BLUE;
    //		SOFT_DELAY;
    //		
    //		LED_YELLOW;
    //		SOFT_DELAY;
    //		
    //		LED_PURPLE;
    //		SOFT_DELAY;
    //				
    //		LED_CYAN;
    //		SOFT_DELAY;
    //		
    //		LED_WHITE;
    //		SOFT_DELAY;
    //		
    //		LED_RGBOFF;
    //		SOFT_DELAY;		
    //	}
    
    /* 轮询按键状态,若按键按下则反转LED */
    	while(1)                            
    	{	   
    		if( Key_Scan(KEY1_GPIO_PORT,KEY1_GPIO_PIN) == KEY_ON  )
    		{
    			/*LED1反转*/
    			LED1_TOGGLE;
    		} 
    
    		if( Key_Scan(KEY2_GPIO_PORT,KEY2_GPIO_PIN) == KEY_ON  )
    		{
    			/*LED2反转*/
    			LED2_TOGGLE;
    		}		
    	}
    
    
    
    }
    
    //void Delay(__IO uint32_t nCount)	 //简单的延时函数
    //{
    //	for(; nCount != 0; nCount--);
    //}
    /*********************************************END OF FILE**********************/
    
    

    烧进去就OK啦!

    二、采用中断方式

    1、中断概念

    参考:https://blog.csdn.net/p467616/article/details/115669632
    中断是啥
    中断可以这样比喻:你在做一件事情,然后电话打进来,你去做电话里要求你做的是,然后做完了又回来做刚才没做完的事情
    NVIC
    嵌套向量中断控制器,属于内核外设,管理着包括内核和片上所有外设的中断相关的功能。
    EXTI
    外部 中断/事件 控制器
    EXTI 有20个中断/事件线,每个GPIO都可以被设置为输入线,占用 EXTI0至EXTI15。
    在这里插入图片描述

    中断分组、主优先级、子优先级
    在这里插入图片描述一般来说先选定优先级分组,选好之后就不要改了,因为改分组可能会使程序错乱。然后配置主优先级和子优先级。

    编号越小,优先级越高:如果同一分组里,主优先级相同,子优先级越低,越先发生。如果是主优先级不同,那么主优先级越低,也越先发生。等一个发生完了,再接下一个发生…当然,如果一个优先级高的先发生了,这是来了个低的,是不会打断这个正在发生的。

    2、中断实验

    利用EXTI中断,按下按键(上升沿或下降沿)会触发中断,从而将灯开关的控制作为中断事件。
    在这里插入图片描述
    在这里插入图片描述

    1、bsp_exti.h
    #ifndef __EXTI_H
    #define	__EXTI_H
    #include "stm32f10x.h"
    
    //dym1:引脚定义
    //配置key1的GPIO引脚
    #define KEY1_INT_GPIO_PORT         GPIOA
    #define KEY1_INT_GPIO_CLK          (RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO)//除了开GPIO的端口时钟外,我们还打开了AFIO的时钟, 这是因为等下配置EXTI信号源的时候需要用到AFIO的外部中断控制寄存器AFIO_EXTICRx
    																																						 //故:使用 GPIO 之前必须开启 GPIO 端口的时钟;用到 EXTI 必须开启 AFIO 时钟。
    #define KEY1_INT_GPIO_PIN          GPIO_Pin_0
    //配置key1的中断
    #define KEY1_INT_EXTI_PORTSOURCE   GPIO_PortSourceGPIOA
    #define KEY1_INT_EXTI_PINSOURCE    GPIO_PinSource0
    #define KEY1_INT_EXTI_LINE         EXTI_Line0 //EXTI中断/事件线选择,可选EXTI0至EXTI19
    #define KEY1_INT_EXTI_IRQ          EXTI0_IRQn //配置向量控制器NVIC的中断向量
    																						  //注意:Line0-4为EXTIX_IRQn,Line5-9都为EXTI9_5_IRQn,Line10-15都为EXTI15_10_IRQn
    
    #define KEY1_IRQHandler            EXTI0_IRQHandler
    
    //配置key2的GPIO引脚
    #define KEY2_INT_GPIO_PORT         GPIOC
    #define KEY2_INT_GPIO_CLK          (RCC_APB2Periph_GPIOC|RCC_APB2Periph_AFIO)
    #define KEY2_INT_GPIO_PIN          GPIO_Pin_13
    
    #define KEY2_INT_EXTI_PORTSOURCE   GPIO_PortSourceGPIOC
    #define KEY2_INT_EXTI_PINSOURCE    GPIO_PinSource13
    #define KEY2_INT_EXTI_LINE         EXTI_Line13
    #define KEY2_INT_EXTI_IRQ          EXTI15_10_IRQn
    
    #define KEY2_IRQHandler            EXTI15_10_IRQHandler
    
    //dym3:配置 IO为EXTI中断口,并设置中断优先级
    void EXTI_Key_Config(void);
    
    
    #endif /* __EXTI_H */
    
    
    2、bsp_exti.c
    /**
      ******************************************************************************
      * @file    bsp_exti.c
      * @author  fire
      * @version V1.0
      * @date    2013-xx-xx
      * @brief   I/O线中断应用bsp
      ******************************************************************************
      * @attention
      *
      * 实验平台:野火 F103-指南者 STM32 开发板 
      * 论坛    :http://www.firebbs.cn
      * 淘宝    :https://fire-stm32.taobao.com
      *
      ******************************************************************************
      */
      
    #include "bsp_exti.h"
    
     /**
      * @brief  dym2:配置嵌套向量中断控制器NVIC
      * @param  无
      * @retval 无
      */
    static void NVIC_Configuration(void)
    {
      NVIC_InitTypeDef NVIC_InitStructure;
      
      /* 配置NVIC为优先级组1 */
    	/* 提示 NVIC_PriorityGroupConfig() 在整个工程只需要调用一次来配置优先级分组!!!*/
      NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
      
      /* 配置中断源:按键1 */
      NVIC_InitStructure.NVIC_IRQChannel = KEY1_INT_EXTI_IRQ;
      /* 配置主优先级 */
      NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
      /* 配置子优先级 */
      NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
      /* 使能中断通道 */
      NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
      NVIC_Init(&NVIC_InitStructure);
      
      /* 配置中断源:按键2,其他使用上面相关配置 */  
      NVIC_InitStructure.NVIC_IRQChannel = KEY2_INT_EXTI_IRQ;
      NVIC_Init(&NVIC_InitStructure);
    }
    
     /**
    	* @brief  dym3:配置 IO为EXTI中断口,并设置中断优先级
      * @param  无
      * @retval 无
      */
    void EXTI_Key_Config(void)
    {
    	GPIO_InitTypeDef GPIO_InitStructure; 
    	EXTI_InitTypeDef EXTI_InitStructure;
    
    	/*开启按键GPIO口的时钟*/
    	RCC_APB2PeriphClockCmd(KEY1_INT_GPIO_CLK,ENABLE);
      RCC_APB2PeriphClockCmd(KEY2_INT_GPIO_CLK,ENABLE);
    												
    	/* 配置 NVIC 中断*/
    	NVIC_Configuration();
    	
    /*--------------------------KEY1配置-----------------------------*/
    	/* 选择按键用到的GPIO */	
      GPIO_InitStructure.GPIO_Pin = KEY1_INT_GPIO_PIN;
      /* 配置为浮空输入 */	
      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
      GPIO_Init(KEY1_INT_GPIO_PORT, &GPIO_InitStructure);
    
    	/* 选择EXTI的信号源 */
      GPIO_EXTILineConfig(KEY1_INT_EXTI_PORTSOURCE, KEY1_INT_EXTI_PINSOURCE); 
      EXTI_InitStructure.EXTI_Line = KEY1_INT_EXTI_LINE;
    	
    	/* EXTI为中断模式 */
      EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
    	/* 上升沿中断 */
      EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
      /* 使能中断 */	
      EXTI_InitStructure.EXTI_LineCmd = ENABLE;
      EXTI_Init(&EXTI_InitStructure);
    	
      /*--------------------------KEY2配置-----------------------------*/
    	/* 选择按键用到的GPIO */	
      GPIO_InitStructure.GPIO_Pin = KEY2_INT_GPIO_PIN;
      /* 配置为浮空输入 */	
      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
      GPIO_Init(KEY2_INT_GPIO_PORT, &GPIO_InitStructure);
    
    	/* 选择EXTI的信号源 */
      GPIO_EXTILineConfig(KEY2_INT_EXTI_PORTSOURCE, KEY2_INT_EXTI_PINSOURCE); 
      EXTI_InitStructure.EXTI_Line = KEY2_INT_EXTI_LINE;
    	
    	/* EXTI为中断模式 */
      EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
    	/* 下降沿中断 */
      EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
      /* 使能中断 */	
      EXTI_InitStructure.EXTI_LineCmd = ENABLE;
      EXTI_Init(&EXTI_InitStructure);
    }
    /*********************************************END OF FILE**********************/
    
    
    3、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.
      *
      * 

    © COPYRIGHT 2011 STMicroelectronics

    ****************************************************************************** */
    /* Includes ------------------------------------------------------------------*/ #include "stm32f10x_it.h" #include "./Led/bsp_led.h" #include "./Key/bsp_exti.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) { } //dym4:配置中断函数!!!!! void KEY1_IRQHandler(void) { //确保是否产生了EXTI Line中断 if(EXTI_GetITStatus(KEY1_INT_EXTI_LINE) != RESET) { // LED1 取反 LED1_TOGGLE; //清除中断标志位 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); } } /******************************************************************************/ /* 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****/
    4、main.c
    /**
      ******************************************************************************
      * @file    main.c
      * @author  fire
      * @version V1.0
      * @date    2013-xx-xx
      * @brief   按键测试(中断模式/EXTI模式)
      ******************************************************************************
      * @attention
      *
      * 实验平台:野火 F103-指南者 STM32 开发板 
      * 论坛    :http://www.firebbs.cn
      * 淘宝    :https://fire-stm32.taobao.com
      *
      ******************************************************************************
      */ 
    
    #include "stm32f10x.h"
    #include "./Led/bsp_led.h"
    #include "./Key/bsp_key.h" 
    #include "./Key/bsp_exti.h" 
    
    
    /**
      * @brief  主函数
      * @param  无
      * @retval 无
      */ 
    int main(void)
    {
    	/* LED 端口初始化 */
    	LED_GPIO_Config();
    	  	
    	/* 初始化EXTI中断,按下按键会触发中断,
      *  触发中断会进入stm32f4xx_it.c文件中的函数
    	*  KEY1_IRQHandler和KEY2_IRQHandler,处理中断,反转LED灯。
    	*/
    	EXTI_Key_Config(); 
    	
    	/* 等待中断,由于使用中断方式,CPU不用轮询按键 */
    	while(1)                            
    	{
    	}
    }
    /*********************************************END OF FILE**********************/
    
    

    烧进去就OK啦!

  • 相关阅读:
    三相异步电机动态数学模型及矢量控制仿真
    B. Difference Array--Codeforces Round #808 (Div. 1)
    Leetcode 15
    什么是内存和进程的运行原理
    【机器学习】——【线性回归模型】——详细【学习路线】
    springboot 跨域配置(处理filter,spring security等过滤器跨域问题)
    ElasticSearch性能原理拆解
    hive acid及事务表踩坑学习实录
    C++基础系列(一) 对象指针
    高端无主灯设计灯光设计该如何布置射灯灯具?
  • 原文地址:https://blog.csdn.net/weixin_44264994/article/details/140445053