STM32_按键控制LED之轮询

今天心情不错,写篇日记来记录一下我学习STM32按键控制LED的大抵情况 大笑

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

开发板   :奋斗STM32

CPU        :STM32F103

开发环境:keil uVsion4

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

本文主要是通过轮询的方法来实现按键控制LED的亮灭,我初始化led为灭的状态,也就是一开始上电LED就是灭着的,当实现按键按下时,LEd亮,再按下按键是LEd灭。
led对应的开发板GPIO管脚如图:



我写的按键轮询功能是所要实现的功能是:按下K1,LED1亮(按键K1对应PC5管脚,LED1对应PB5管脚)
代码如下:
main.c
#include "stm32f10x_gpio.h"
#include "stm32f10x_rcc.h"
#include "led.h"
#include "key.h"

int main(void)  
{  
    SystemInit();
    init_led_gpio();	
    Key_GPIO_Config();
	
    /* turn_led(LED1,ON);
    turn_led(LED2,ON);	
	  turn_led(LED3,ON); */
      
    while (1)  
    {  
        if (KeyScan(GPIOC,GPIO_Pin_5) == KEY_ON)  
        {  
            /* LED1反转 读取GPIOB 5端口位的值并用1减去之后再写入此位即LED1的控制位 */  
            GPIO_WriteBit(GPIOB,GPIO_Pin_5,(BitAction)(1-GPIO_ReadOutputDataBit(GPIOB,GPIO_Pin_5))); 
            					
        }  
				
          
        if (KeyScan(GPIOC,GPIO_Pin_2) == KEY_ON)  
        {  
            /* LED2反转 读取GPIOD 6端口位的值并用1减去之后再写入此位即LED2的控制位 */  
            GPIO_WriteBit(GPIOD,  GPIO_Pin_6,(BitAction)(1-GPIO_ReadOutputDataBit(GPIOD,GPIO_Pin_6)));
            					
        } 
				  
				
         if (KeyScan(GPIOC,GPIO_Pin_3) == KEY_ON)  
        {  
            /* LED3反转 读取GPIOD 3端口位的值并用1减去之后再写入此位即LED3的控制位 */  
            GPIO_WriteBit(GPIOD,  GPIO_Pin_3,(BitAction)(1-GPIO_ReadOutputDataBit(GPIOD,GPIO_Pin_3)));
            					
        }
  			
    }  
		
}

led.c
#include "stm32f10x.h"
#define ON 1 
#define OFF 0   

enum 
{
  LED1 = 0,
	LED2,
	LED3,
	MAX_LED,
};

typedef struct led_gpio_s
{
	int                 num;    /* LED编号 */
	GPIO_TypeDef        *group; /* LED使用的GPIO在哪一组: GPIOB or GPIOD */	
  uint16_t            pin;    /* LED使用的GPIO组中的那一个pin: GPIO_Pin_x */
} led_gpio_t;


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 */		
};

/*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);						
  }
}
  /*使LED在初始化后处于全灭状态*/
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);
}

key.c
#include "stm32f10x.h"
#define  KEY_ON 1 
#define  KEY_OFF 0 

		void delay_ms(u16 time)     
{    
  u16 i=0;    
  while(time--)     
  {    
    i=12000;    
    while(i--);    
  }    
}  


void Key_GPIO_Config(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
	
	RCC_APB2PeriphClockCmd (RCC_APB2Periph_GPIOC,ENABLE);
	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_2 |GPIO_Pin_3;
	//GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHZ;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
	
	GPIO_Init (GPIOC,&GPIO_InitStructure);
	
}
	
	/* 
  * @brief  : 按键按下检测 
  * @param  : 端口 : GPIOx  端口位 : GPIO_Pin_x 
  * @retval : 按键的状态 : 按下 弹起 
  */  
uint8_t KeyScan( GPIO_TypeDef * GPIOx, uint16_t GPIO_Pin_x )  
{  
    /* 检测是否有按键按下 */  
    if ( GPIO_ReadInputDataBit( GPIOx, GPIO_Pin_x ) == KEY_ON )  
    {  
        /* 延时消抖 延时大约5ms */  
        delay_ms(5);  
        if ( GPIO_ReadInputDataBit( GPIOx, GPIO_Pin_x ) == KEY_ON )  
        {  
            while ( GPIO_ReadInputDataBit( GPIOx, GPIO_Pin_x ) == KEY_ON ); /* 等待按键释放 */  
            return KEY_ON;  
        }  
        else  
        {  
            return KEY_OFF;  
        }  
    }  
    return KEY_OFF;
		
		
	}
写这个程序主要是为了完成相关的配置工作:
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);						
  }
}
由于奋斗STM32开发板有3个按键控制3个LED,为了代码的简洁和美观,本文用了一个for循环来实现LED的管脚的配置
2.配置按键以及初始化时钟
void Key_GPIO_Config(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
	
	RCC_APB2PeriphClockCmd (RCC_APB2Periph_GPIOC,ENABLE);
	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_2 |GPIO_Pin_3;
	//GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHZ;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
	
	GPIO_Init (GPIOC,&GPIO_InitStructure);
	
}

3.delay_ms函数用于消抖
void delay_ms(u16 time)     
{    
  u16 i=0;    
  while(time--)     
  {    
    i=12000;    
    while(i--);    
  }    
}  
关于按键消抖:
按键消抖:按键消抖通常的按键所用开关为机械弹性开关,当机械触点断开、闭合时,由于机械触点的弹性作用,一个按键开关在闭合时不会马上稳定地接通,在断开时也不会一下子断开。因而在闭合及断开的瞬间均伴随有一连串的抖动,为了不产生这种现象而作的措施就是按键消抖。

                                                                          


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


猜你喜欢

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