一、适用功能
检测按键,光电开关,水位传感器等检测 GPIO 输入电平信号。
二、 硬件设计(参考)
三、 软件设计
① 使用到的固件库文件
#include stm32f10x_gpio.c/stm32f10x_gpio.h
#include stm32f10x_rcc.c/stm32f10x_rcc.h
② 代码整理
- delay.h
#ifndef __DELAY_H
#define __DELAY_H
#include "stm32f10x.h"
void Delay(__IO uint32_t nCount);
#endif
- delay.c
#include "delay.h"
void Delay(__IO uint32_t nCount) // 简单的延时函数
{
for(; nCount != 0; nCount--);
}
- led.h
#ifndef _LED_H
#define _LED_H
#include "stm32f10x.h"
void LED_Init(void);
void LED0_Level(unsigned char Level);
void LED1_Level(unsigned char Level);
#endif
- led.c
#include "led.h"
/*******************************************************************************
* 函 数 名 : LED_Init
* 函数功能 : LED初始化函数
* 输 入 : 无
* 输 出 : 无
* 说 明 :无
*******************************************************************************/
void LED_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); // 使能PB端口时钟
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_5; // LED0-->PB.5 端口配置
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP; // 推挽输出
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; // IO口速度为50MHz
GPIO_Init(GPIOB,&GPIO_InitStructure); // 根据设定参数初始化GPIOB.5
GPIO_SetBits(GPIOB,GPIO_Pin_5); // PB.5 输出高
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE); // 使能PE端口时钟
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_5; // LED1-->PE.5 端口配置
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP; // 推挽输出
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; // IO口速度为50MHz
GPIO_Init(GPIOE,&GPIO_InitStructure); // 根据设定参数初始化GPIOB.5
GPIO_SetBits(GPIOE,GPIO_Pin_5); // PE.5 输出高
}
/*******************************************************************************
* 函 数 名 : LED0_Level
* 函数功能 : LED0——IO电平输出
* 输 入 : Level: 1 —— 输出高; 0 —— 输出低
* 输 出 : 无
* 说 明 :无
*******************************************************************************/
void LED0_Level(unsigned char Level)
{
if (Level == 1)
{
// PB.5 输出高
GPIO_SetBits(GPIOB,GPIO_Pin_5);
}
else if (Level == 0)
{
// PB.5 输出低
GPIO_ResetBits(GPIOB,GPIO_Pin_5);
}
}
/*******************************************************************************
* 函 数 名 : LED1_Level
* 函数功能 : LED1——IO电平输出
* 输 入 : Level: 1 —— 输出高; 0 —— 输出低
* 输 出 : 无
* 说 明 :无
*******************************************************************************/
void LED1_Level(unsigned char Level)
{
if (Level == 1)
{
// PB.5 输出高
GPIO_SetBits(GPIOE,GPIO_Pin_5);
}
else if (Level == 0)
{
// PB.5 输出低
GPIO_ResetBits(GPIOE,GPIO_Pin_5);
}
}
- key.h
#ifndef __KEY_H
#define __KEY_H
#include "sys.h"
#include "delay.h"
enum E_KEY_PRES
{
// 没按键按下
E_KEY_PRES_NULL = 0,
// KEY0 按下
E_KEY_PRES_0,
// KEY1 按下
E_KEY_PRES_1,
//KEY2 按下
E_KEY_PRES_2,
//KEY_UP 按下 (即WK_UP/KEY_UP)
E_KEY_PRES_WK_UP
};
#define KEY0 GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_4) // 读取按键0
#define KEY1 GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_3) // 读取按键1
#define KEY2 GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_2) // 读取按键2
#define WK_UP GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0) // 读取按键3(WK_UP)
void KEY_Init(void);
unsigned char KEY_Scan(void);
#endif
- key.c
#include "key.h"
/*******************************************************************************
* 函 数 名 : KEY_Init
* 函数功能 : KEY初始化函数
* 输 入 : 无
* 输 出 : 无
* 说 明 :无
*******************************************************************************/
void KEY_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
// KEY0
// 使能 KEY0 时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE);
// KEY0 按键的引脚
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
// 设置按键的引脚为上拉输入
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
// 初始化 KEY0
GPIO_Init(GPIOE, &GPIO_InitStructure);
// KEY1
// 使能 KEY1 时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE);
// KEY1 按键的引脚
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
// 设置按键的引脚为上拉输入
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
// 初始化 KEY1
GPIO_Init(GPIOE, &GPIO_InitStructure);
// KEY2
// 使能 KEY2 时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE);
// KEY2 按键的引脚
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
// 设置按键的引脚为上拉输入
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
// 初始化 KEY2
GPIO_Init(GPIOE, &GPIO_InitStructure);
// WK_UP
// 使能 WK_UP 时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
// WK_UP 按键的引脚
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
// 设置按键的引脚为下拉输入
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
// 初始化 WK_UP
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
/*******************************************************************************
* 函 数 名 : KEY_Scan
* 函数功能 : KEY检测函数
* 输 入 : 无
* 输 出 :
E_KEY_PRES_NULL:没有按键被按下
E_KEY_PRES_0:KEY0被按下
E_KEY_PRES_1:KEY1被按下
E_KEY_PRES_2:KEY2被按下
E_KEY_PRES_WK_UP:WK_UP被按下
* 说 明 :
注意此函数有响应优先级,KEY0>KEY1>KEY2>WK_UP!!
*******************************************************************************/
unsigned char KEY_Scan(void)
{
if ((0 == KEY0) || (0 == KEY1) || (0 == KEY2) || (1 == WK_UP))
{
// 去抖动
Delay(0xff);
if (0 == KEY0)
{
// 等待按键松手
while(0 == KEY0);
return E_KEY_PRES_0;
}
else if (0 == KEY1)
{
// 等待按键松手
while(0 == KEY1);
return E_KEY_PRES_1;
}
else if (0 == KEY2)
{
// 等待按键松手
while(0 == KEY2);
return E_KEY_PRES_2;
}
else if (1 == WK_UP)
{
// 等待按键松手
while(1 == WK_UP);
return E_KEY_PRES_WK_UP;
}
}
return E_KEY_PRES_NULL;
}
- main
#include "led.h"
#include "delay.h"
#include "key.h"
unsigned char Key_Status;
int main(void)
{
// LED GPIO 初始化
LED_Init();
// KEY GPIO 初始化
KEY_Init();
while(1)
{
Key_Status = KEY_Scan();
switch (Key_Status)
{
case E_KEY_PRES_0:
{
LED0_Level(0);
LED1_Level(0);
}
break;
case E_KEY_PRES_1:
{
LED0_Level(1);
LED1_Level(0);
}
break;
case E_KEY_PRES_2:
{
LED0_Level(0);
LED1_Level(1);
}
break;
case E_KEY_PRES_WK_UP:
{
LED0_Level(1);
LED1_Level(1);
}
break;
}
}
}
KEY GPIO 设置上拉模式、下拉模式或者浮空模式,这个取决于硬件。
当硬件有默认电平信号(非高阻态)时,只要按键按下时,会发生电平翻转,这种情况可以设置为浮空模式。
当硬件没有默认电平信号时,按下按键电平置 0 ,这种情况可以设置为上拉模式。
当硬件没有默认电平信号时,按下按键电平置 1 ,这种情况可以设置为下拉模式。