使用STM32实现按键控制功能

目录

一、实现原理:

1.1 按键控制电路分析

二、程序部分:


一、实现原理:

1.1 按键控制电路分析

    可以看见电路上key_up按键连接3.3v,K1、K2、K3下拉接地。按键检测的时候需要配置输入模式。key_up配置下拉输入:在默认状态下,读取的GPIO引脚为低电平,按键按下时,输入变为高电平。K1、K2、K3配置上拉输入:在默认状态下,读取的GPIO引脚为高电平,当按键按下的时候,相应管脚变为低电平。

 1.2 按键检测分析

    按键在按下的时候并不是立马会得到稳定的低电平,如下图所示存在一个前沿抖动,同理在按键松开的时候也会存在一个后沿抖动。在实际检测的时候,为了克服这种抖动,一般可以采用两种方法消除:软件消除通过添加一个延时检测,(一般来讲在5-10ms),确定是否按键稳定按下。硬件上采用rc滤波电路来消除这种抖动。

二、程序部分:

button.h包含GPIO的封装

#ifndef _button_H
#define _button_H
//对一些IO口通过位带封装函数
#include "system.h"

//key_up以及key封装
#define BUTTON_PORT_RCC		RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOE
#define BUTTON_UP_PIN       GPIO_Pin_0
#define BUTTON_UP_PORT  	GPIOA

#define BUTTON_LEFT_PIN     GPIO_Pin_2
#define BUTTON_DOWN_PIN     GPIO_Pin_3
#define BUTTON_RIGHT_PIN    GPIO_Pin_4
#define BUTTON_PORT  	    GPIOE


//管脚输入电平
#define BUTTON_UP           PAin(0)
#define BUTTON_LEFT         PEin(2)
#define BUTTON_DOWN         PEin(3)
#define BUTTON_RIGHT        PEin(4)
//扫描函数返回检测值
#define key_detection_up    1
#define key_detection_left  2
#define key_detection_down  3
#define key_detection_right 4

void button_Init(void);
u8 button_scan(u8 mode);

#endif

button.c包含端口初始化函数以及扫描函数

#include "button.h"
#include "SysTick.h"

void button_Init()
{
    GPIO_InitTypeDef GPIO_InitStructure;
    //开启时钟
    RCC_APB2PeriphClockCmd(BUTTON_PORT_RCC,ENABLE);
    //key_up初始化,模式选择下拉
    GPIO_InitStructure.GPIO_Pin = BUTTON_UP_PIN ;
    GPIO_InitStructure.GPIO_Mode= GPIO_Mode_IPD;
    GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
    GPIO_Init(BUTTON_UP_PORT,&GPIO_InitStructure); 
    //key初始化,模式选择输入上拉
    GPIO_InitStructure.GPIO_Pin = BUTTON_LEFT_PIN|BUTTON_DOWN_PIN|BUTTON_RIGHT_PIN;
    GPIO_InitStructure.GPIO_Mode= GPIO_Mode_IPU;
    GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
    GPIO_Init(BUTTON_PORT,&GPIO_InitStructure); 


}

//mode = 0 单次扫描检测
//一次按下进入检测条件语句,key置0,而后不满足条件key==1无法进入检测语句,实现只检测一次的效果
//mode = 1 连续扫描检测
//mode始终处于1,在不满足按键按下的条件下才会不进入检测语句

u8 button_scan(u8 mode)
{
    static u8 key=1;
    if (key==1&&(BUTTON_UP==1||BUTTON_LEFT==0||BUTTON_DOWN==0||BUTTON_RIGHT==0))
    {
       //克服抖动延时10ms
        delay_ms(10);
        key = 0;
        if (BUTTON_UP==1)
        {
            return key_detection_up;
        }
        else if (BUTTON_LEFT==0)
        {
            return key_detection_left;
        }
        else if (BUTTON_DOWN==0)
        {
            return key_detection_down;
        }
        else
        {
            return key_detection_right;
        } 
    }
    else if (BUTTON_UP==0&&BUTTON_LEFT==1&&BUTTON_DOWN==1&&BUTTON_RIGHT==1)
    {
        key = 1;

    }
    if (mode==1)
    {
        key = 1;
    }
    return 0;
}

位带封装函数

#ifndef _system_H
#define _system_H


#include "stm32f10x.h"



#define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2)) 
#define MEM_ADDR(addr)  *((volatile unsigned long  *)(addr)) 
#define BIT_ADDR(addr, bitnum)   MEM_ADDR(BITBAND(addr, bitnum)) 

#define GPIOA_ODR_Addr    (GPIOA_BASE+12) //0x4001080C 
#define GPIOB_ODR_Addr    (GPIOB_BASE+12) //0x40010C0C 
#define GPIOC_ODR_Addr    (GPIOC_BASE+12) //0x4001100C 
#define GPIOD_ODR_Addr    (GPIOD_BASE+12) //0x4001140C 
#define GPIOE_ODR_Addr    (GPIOE_BASE+12) //0x4001180C 
#define GPIOF_ODR_Addr    (GPIOF_BASE+12) //0x40011A0C    
#define GPIOG_ODR_Addr    (GPIOG_BASE+12) //0x40011E0C    

#define GPIOA_IDR_Addr    (GPIOA_BASE+8) //0x40010808 
#define GPIOB_IDR_Addr    (GPIOB_BASE+8) //0x40010C08 
#define GPIOC_IDR_Addr    (GPIOC_BASE+8) //0x40011008 
#define GPIOD_IDR_Addr    (GPIOD_BASE+8) //0x40011408 
#define GPIOE_IDR_Addr    (GPIOE_BASE+8) //0x40011808 
#define GPIOF_IDR_Addr    (GPIOF_BASE+8) //0x40011A08 
#define GPIOG_IDR_Addr    (GPIOG_BASE+8) //0x40011E08 
 

#define PAout(n)   BIT_ADDR(GPIOA_ODR_Addr,n)  //��� 
#define PAin(n)    BIT_ADDR(GPIOA_IDR_Addr,n)  //���� 

#define PBout(n)   BIT_ADDR(GPIOB_ODR_Addr,n)  //��� 
#define PBin(n)    BIT_ADDR(GPIOB_IDR_Addr,n)  //���� 

#define PCout(n)   BIT_ADDR(GPIOC_ODR_Addr,n)  //��� 
#define PCin(n)    BIT_ADDR(GPIOC_IDR_Addr,n)  //���� 

#define PDout(n)   BIT_ADDR(GPIOD_ODR_Addr,n)  //��� 
#define PDin(n)    BIT_ADDR(GPIOD_IDR_Addr,n)  //���� 

#define PEout(n)   BIT_ADDR(GPIOE_ODR_Addr,n)  //��� 
#define PEin(n)    BIT_ADDR(GPIOE_IDR_Addr,n)  //����

#define PFout(n)   BIT_ADDR(GPIOF_ODR_Addr,n)  //��� 
#define PFin(n)    BIT_ADDR(GPIOF_IDR_Addr,n)  //����

#define PGout(n)   BIT_ADDR(GPIOG_ODR_Addr,n)  //��� 
#define PGin(n)    BIT_ADDR(GPIOG_IDR_Addr,n)  //����


#endif

本次实验还使用led灯模块用于指示按键是否运行:

led.h

#ifndef _led_H
#define _led_H

#include "system.h"


#define LED_PORT 			GPIOC   
#define LED_PIN 			(GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7)
#define LED_PORT_RCC		RCC_APB2Periph_GPIOC


#define led1 PCout(0)
#define led2 PCout(1)
#define led3 PCout(2)
#define led4 PCout(3)
#define led5 PCout(7)



void LED_Init(void);


#endif

led.c

#include "led.h"


void LED_Init()
{
	GPIO_InitTypeDef GPIO_InitStructure;
	
	RCC_APB2PeriphClockCmd(LED_PORT_RCC,ENABLE);
	
	GPIO_InitStructure.GPIO_Pin=LED_PIN;  
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;	 
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;	
	GPIO_Init(LED_PORT,&GPIO_InitStructure); 	 
	
	GPIO_SetBits(LED_PORT,LED_PIN);   
}

主函数控制main.c

#include "system.h"
#include "SysTick.h"
#include "led.h"
#include "button.h"


int main()
{
	u8 key,i=0;
	SysTick_Init(72);
	LED_Init();
	button_Init();
	
	while (1)
	{
		key = button_scan(0);
		switch (key)
		{
		case key_detection_up:
			led1 = 0;
			break;
		case key_detection_left:
			led1 = 1;
			break;
		case key_detection_down:
			led2 = 0;
			break;
		case key_detection_right:
			led2 = 1;
			break;
		default:
			break;
		}
		i++;
		//if更少延时不影响按键检测
		if (i%20==0)
		{
			led5 = !led5;
		}
		delay_ms(10);
		
	}
		
}

物联沃分享整理
物联沃-IOTWORD物联网 » 使用STM32实现按键控制功能

发表评论