目录
一、实现原理:
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文章来源:https://www.toymoban.com/news/detail-613968.html
#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文章来源地址https://www.toymoban.com/news/detail-613968.html
#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);
}
}
到了这里,关于stm32实现按键控制的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!