目录
硬件原理
注意:KEY0 和 KEY1 是低电平有效的,而 KEY_UP 是高电平有效的,并且外部都没有上下拉电阻,所以,需要在 STM32F1 内部设置上下拉
对于KEY0和KEY1,其连接为共阴接法,故IO口默认读取为高电平,故程序需设计为上拉输入模式;而对于KEY_UP,其连接为共阳接法,故IO口默认读取为低电平,故程序需设计为下拉输入模式
软件原理
读取GPIO输入电平的方法
1.调用库函数
GPIO_ReadInputDataBit();
2.直接操作寄存器
GPIOx_IDR:端口输入寄存器
3.位带操作
PEin(n) 读取GPIOE.n口的电平
程序设计原理
1.使能对应IO口时钟
RCC_APB2PeriphClockCmd();
2.初始化IO口模式
GPIO_Init(); 需初始化为上拉/下拉输入模式
3.扫描IO口电平
详见读取GPIO输入电平的方法和代码部分
代码
1.Key.h
#ifndef _Key_H_
#define _Key_H_
#include "sys.h" //为了引用PEin(n),PAin(n)
/* 库函数 */
#define KEY0 GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_4)//读取按键 0
#define KEY1 GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_3)//读取按键 1
#define WK_UP GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)//读取按键 WK_UP
/* 位操作 */
//#define KEY0 PEin(4) //PE4
//#define KEY1 PEin(3) //PE3
//#define WK_UP PAin(0) //PA0 WK_UP
#define KEY0_PRES 1 //KEY0 按下
#define KEY1_PRES 2 //KEY1 按下
#define WKUP_PRES 3 //WK_UP 按下
void Key_Init(void);
u8 Key_Scan(u8 Mode);
#endif
2.Key.c
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "Key.h"
/**
* @brief 按键初始化函数
* @param 无
* @retval 无
*/
void Key_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|
RCC_APB2Periph_GPIOE,ENABLE); //使能 GPIOA,GPIOE 时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3|GPIO_Pin_4;//选择GPIOE端口
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //设置成上拉输入
GPIO_Init(GPIOE, &GPIO_InitStructure); //初始化 GPIOE3,GPIOE4
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; //选择GPIOA端口
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //PA0 设置成输入,下拉
GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化 GPIOA.0
}
/**
* @brief 按键扫描函数
* @param Mode 按键支持的模式,0为不支持连按,1为支持连按
* @retval 0 没有按键按下
* @retval 1 KEY0_PRES Key0按下
* @retval 2 KEY1_PRES Key1按下
* @retval 3 WKUP_PRES WakeUp按下
*/
u8 Key_Scan(u8 Mode)
{
static u8 Key_ForeState = 1; //记录按键上一次按下的状况,0为按下,1为松手
if(Mode == 1){Key_ForeState = 1;} //支持连按
if(Key_ForeState && (KEY0==0||KEY1==0||WK_UP==1))
{
delay_ms(10); //消抖
Key_ForeState = 0; //记录状态为按下
/* 判断确切的按键 */
if(KEY0 == 0){return KEY0_PRES;}
else if(KEY1 == 0){return KEY1_PRES;}
else if(WK_UP == 1){return WKUP_PRES;}
}
else if(KEY0==1 && KEY1==1 && WK_UP==0) //没有按键按下时
{
Key_ForeState = 1;
}
return 0;
}
3.main.c
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "LED.h"
#include "Beep.h"
#include "Key.h"
u8 KeyNum; //存放返回键值
int main(void)
{
delay_init();
LED_Init();
Beep_Init();
Key_Init();
LED0 = 0; //先点亮红灯
while(1)
{
KeyNum = Key_Scan(0); //得到返回键值(不支持连按)
if(KeyNum)
{
switch(KeyNum)
{
case WKUP_PRES: //控制蜂鸣器
BEEP=!BEEP;
break;
case KEY1_PRES: //控制 LED1 翻转
LED1=!LED1;
break;
case KEY0_PRES: //同时控制 LED0,LED1 翻转
LED0=!LED0;
LED1=!LED1;
break;
}
}
else delay_ms(10); //不让其立即重新读键值
}
}