一、硬件连接部分
stm32战舰版的硬件连接如上图所示
KEY_UP一端连接到的VCC,另外一端连接到PA0,那么我们在读取电平的时候只要读取到PA0的电平为高,就说明KEY_UP被按下了。其他三个按键的一端接地,那么对应的GPIO口读取到低电平就说明这三个按键被按下了。
二、GPIO相关设置
1.初始化
void KeyInit()
{
GPIO_InitTypeDef GPIO_InitTypeStruct;
GPIO_InitTypeStruct.GPIO_Mode=GPIO_Mode_IPU;//输入上拉
GPIO_InitTypeStruct.GPIO_Pin=GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4;
GPIO_InitTypeStruct.GPIO_Speed=GPIO_Speed_50MHz;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE|RCC_APB2Periph_GPIOA,ENABLE);//使能GPIOA和GPIOE的时钟
GPIO_Init(GPIOE,&GPIO_InitTypeStruct);
GPIO_InitTypeStruct.GPIO_Mode=GPIO_Mode_IPD;//输入下拉
GPIO_InitTypeStruct.GPIO_Pin=GPIO_Pin_0;
GPIO_Init(GPIOA,&GPIO_InitTypeStruct);
}
GPIOE配置为输入上拉是因为在没有检测到低电平的时候始终保持高电平,低电平就意味着按键被按下了,防止出现误判的情况所以在没有输入的时候拉高,GPIOA配置为输入下拉同理。
2.读取GPIO电平
#define KEY_UP GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)
#define KEY_0 GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_4)
#define KEY_1 GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_3)
#define KEY_2 GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_2)
//#define KEY_UP PAin(0)
//#define KEY_0 PEin(4)
//#define KEY_1 PEin(3)
//#define KEY_2 PEin(2)
使用GPIO_ReadInputDataBit()函数读取电平或者使用位操作读取电平
三、扫描方式
u8 Key_Scan(u8 mode)//mode为0即支持短按,为1即支持长按
{
u8 key_up = 1;//记录上一次按键的状态,1为松开,0为按下
if(mode)key_up =1;
if(key_up == 1&&(KEY_UP == 1||KEY_0 == 0||KEY_1 == 0||KEY_2 == 0))
{
delay_ms(10);//延时消抖
key_up = 0;
if(KEY_UP == 1)return KEY_UP_PREE;
if(KEY_0 == 0)return KEY_0_PREE;
if(KEY_1 == 0)return KEY_1_PREE;
if(KEY_2 == 0)return KEY_2_PREE;
}
else if(KEY_UP == 0||KEY_0 == 1||KEY_1 == 1||KEY_2 == 1)key_up=0;
return 0;
}
KEY_UP 等标识符均使用了宏定义,具体内容请移步文章末尾查看key.h头文件
当mode等于0的时候,key_up 的值是记录了按键的上一个状态,再次调用
Key_Scan()函数的时候即是和按键的上一个状态做比较,只有当按键的状态与上一次不同的时候才会进行到第二步的按键有效性判断,实现了短按键的功能。
当mode等于1的时候 if(mode)key_up =1;
生效,在每一次调用Key_Scan()函数的时候,key_up 的值都会被赋值1,就相当于是每一次在判断的按键状态的时候,按键的上一个状态都是松开的,这样就可以实现长按键的功能。
delay_ms(10)为延时消抖,不懂这里的小伙伴请移步延时消抖写独立按键有比较详细的讲解,这里不再赘述。
四、按键功能
u8 key_val = Key_Scan(0);
if(key_val)
switch(key_val)
{
case 1:LED1=0;LED2=0;break;
case 2:LED1=0;LED2=1;break;
case 3:LED1=1;LED2=0;break;
case 4:LED1=1;LED2=1;break;
}
LED这边使用了宏定义,具体移步底部查看led.h头文件
这一段是放在主函数的while里面的,也可以单独写一个函数keyfun()用来放按键功能的代码我这里作为演示就简单些了。
key_val 用来获取是哪一个按键按下,通过switch语句来执行对应按键按下后的程序语段。
五、部分代码
key.h
#ifndef _KEY_H
#define _KEY_H
#define u8 unsigned char
#define KEY_UP GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)
#define KEY_0 GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_4)
#define KEY_1 GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_3)
#define KEY_2 GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_2)
//#define KEY_UP PAin(0)
//#define KEY_0 PEin(4)
//#define KEY_1 PEin(3)
//#define KEY_2 PEin(2)
#define KEY_UP_PREE 1
#define KEY_0_PREE 2
#define KEY_1_PREE 3
#define KEY_2_PREE 4
void KeyInit();
u8 KeyScan();
#endif
key.c
#include "stm32f10x.h"
#include "key.h"
#include "delay.h"
void KeyInit()
{
GPIO_InitTypeDef GPIO_InitTypeStruct;
GPIO_InitTypeStruct.GPIO_Mode=GPIO_Mode_IPU;
GPIO_InitTypeStruct.GPIO_Pin=GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4;
GPIO_InitTypeStruct.GPIO_Speed=GPIO_Speed_50MHz;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE|RCC_APB2Periph_GPIOA,ENABLE);
GPIO_Init(GPIOE,&GPIO_InitTypeStruct);
GPIO_InitTypeStruct.GPIO_Mode=GPIO_Mode_IPD;
GPIO_InitTypeStruct.GPIO_Pin=GPIO_Pin_0;
GPIO_Init(GPIOA,&GPIO_InitTypeStruct);
}
u8 Key_Scan(u8 mode)
{
u8 key_up = 1;
if(mode)key_up =1;
if(key_up == 1&&(KEY_UP == 1||KEY_0 == 0||KEY_1 == 0||KEY_2 == 0))
{
delay_ms(10);
key_up = 0;
if(KEY_UP == 1)return KEY_UP_PREE;
if(KEY_0 == 0)return KEY_0_PREE;
if(KEY_1 == 0)return KEY_1_PREE;
if(KEY_2 == 0)return KEY_2_PREE;
}
else if(KEY_UP == 0||KEY_0 == 1||KEY_1 == 1||KEY_2 == 1)key_up=0;
return 0;
}
led.h
#ifndef __LED_H
#define __LED_H
#define LED1 PBout(5)
#define LED2 PEout(5)
void LED_Init();
#endif
led.c
#include "led.h"
#include "stm32f10x.h"
void LED_Init()
{
GPIO_InitTypeDef GPIO_InitTypeStruct;
GPIO_InitTypeStruct.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_InitTypeStruct.GPIO_Pin=GPIO_Pin_5;
GPIO_InitTypeStruct.GPIO_Speed=GPIO_Speed_50MHz;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOE,ENABLE);
GPIO_Init(GPIOB,&GPIO_InitTypeStruct);
GPIO_Init(GPIOE,&GPIO_InitTypeStruct);
GPIO_SetBits(GPIOB,GPIO_Pin_5);
GPIO_SetBits(GPIOE,GPIO_Pin_5);
}
main.c
#include "stm32f10x.h"
#include "led.h"
#include "delay.h"
#include "key.h"
int main()
{
LED_Init();
delay_init();
KeyInit();
while(1)
{
u8 key_val = Key_Scan(0);
if(key_val)
switch(key_val)
{
case 1:LED1=0;LED2=0;break;
case 2:LED1=0;LED2=1;break;
case 3:LED1=1;LED2=0;break;
case 4:LED1=1;LED2=1;break;
}
else delay_ms(10);
}
}