h网站模板,中国建设银行青岛网站,类似享设计的网站,虹口上海网站建设STM32学习7 按键扫描 一、实验电路介绍二、按键GPIO初始化三、扫描原理1. GPIO引脚配置2. 状态轮询3. 按键状态检测4. 循环扫描的优缺点优点#xff1a;缺点#xff1a; 四、一次扫描与持续扫描五、代码实现1. 头文件定义2. 函数实现3. 主体函数 一、实验电路介绍
本实验使用… STM32学习7 按键扫描 一、实验电路介绍二、按键GPIO初始化三、扫描原理1. GPIO引脚配置2. 状态轮询3. 按键状态检测4. 循环扫描的优缺点优点缺点 四、一次扫描与持续扫描五、代码实现1. 头文件定义2. 函数实现3. 主体函数 一、实验电路介绍
本实验使用普中STM32-F1开发板芯片型号是STM32F103ZET6。 其按键电路如下 对应的芯片引脚 从电路可以看出键盘的 KEY_UP 键如果接通会连接高电平 。 其它几个按键在按下的时候连接低电平对应的GPIO口
KEY_UPGPIOA GPIO_Pin0 引脚KEY_LEFTGPIOE GPIO_Pin2 引脚KEY_RIGHTGPIOE_GPIO_Pin4 引脚KEY_DOWNGPIOE_GPIO_Pin3 引脚
二、按键GPIO初始化
按键 KEY_UP 和其它三个按键的接法不同需要不同的配置方式。 其中 KEY_UP 按下后接高电平在默认情况下需要置低初始化时设置为输入下拉代码如下 // 开启GPIOA的时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);// 设置上引脚GPIO_InitStructure.GPIO_Pin KEY_UP_PIN;// 设置输入下拉模式GPIO_InitStructure.GPIO_Mode GPIO_Mode_IPD;GPIO_Init(KEY_UP_PORT, GPIO_InitStructure); // 初始化GPIOA其它三个按键按下时接低电平默认置高初始化设置为输入上拉代码如下 // 开 E 时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE);// 设置下、左、右引脚GPIO_InitStructure.GPIO_Pin KEY_DOWN_PIN | KEY_LEFT_PIN | KEY_RIGHT_PIN;// 设置输入上拉模式GPIO_InitStructure.GPIO_Mode GPIO_Mode_IPU;GPIO_Init(KEY_DOWN_PORT, GPIO_InitStructure); // 初始化GPIOE三、扫描原理
1. GPIO引脚配置
首先需要将用于连接按键的GPIO引脚配置为输入模式。
2. 状态轮询
然后轮询每个按键的状态以确定按键是否被按下或释放。轮询扫描可以通过在主循环中定期检查每个按键的状态来实现。例如在每次主循环迭代中都检查一次按键的状态。
3. 按键状态检测
一般来说按键有两种状态按下和释放。在检测按键状态时需要注意去除按键的抖动干扰。抖动是指在按键被按下或释放时由于机械接触或物理特性导致的瞬间状态变化。为了应对抖动可以采用软件方法或硬件滤波器。
本示例采用延时10ms读取值的方法来去抖示例
if(key_up_value 1 || key_down_value 0 || key_left_value 0 || key_right_value 0){delay_ms(10);
}硬件方法去抖可以参考实现SR触发器去抖
4. 循环扫描的优缺点
优点 简单直观 在循环中进行按键扫描的方法简单易懂逻辑清晰易于理解和实现。 灵活性 可以根据具体需求灵活调整扫描的频率和方式满足不同场景下的要求。 适用性广 适用于小型嵌入式系统或者对按键响应速度要求不高的场景适用性广泛。 资源消耗低 相比于中断方式循环扫描不需要额外的中断处理函数减少了系统资源的占用。
缺点 效率低下 在循环中进行按键扫描会占用 CPU 的时间片降低了系统的处理效率特别是当系统有其他紧急任务需要处理时会影响响应速度和实时性。 实时性差 循环扫描需要不断地遍历所有按键状态导致按键的检测周期相对较长实时性差无法满足对按键响应速度要求较高的场景。 占用 CPU 资源 循环扫描需要持续占用 CPU 资源特别是在大型系统中可能会影响其他任务的执行降低系统的整体性能。 功耗高 循环扫描需要 CPU 不断地处于工作状态会增加系统的功耗对于对功耗要求较高的场景不太适用。
后面学习中会采用中断的方式来读取键盘。
四、一次扫描与持续扫描
这里的一次扫描是指按下按键后如果不松开键盘的扫描函数不会继续输出所按键值。 而持续扫描在按下按键后如果手不松开键盘的扫描函数仍会持续输出按键值。
五、代码实现
为方便看到演示效果示例的代码在获取到扫描的按键后会在数码管显示不同的数值。
上显示0下显示1左显示2右显示3
1. 头文件定义
key_utils.h
#ifndef __KEY_UTILS_H__
#define __KEY_UTILS_H__
#include stm32f10x.h// 引脚和端口
#define KEY_UP_PIN GPIO_Pin_0
#define KEY_UP_PORT GPIOA
#define KEY_LEFT_PIN GPIO_Pin_2
#define KEY_LEFT_PORT GPIOE
#define KEY_DOWN_PIN GPIO_Pin_3
#define KEY_DOWN_PORT GPIOE
#define KEY_RIGHT_PIN GPIO_Pin_4
#define KEY_RIGHT_PORT GPIOE// 读取引脚状态
#define key_up_value GPIO_ReadInputDataBit(KEY_UP_PORT, KEY_UP_PIN)
#define key_down_value GPIO_ReadInputDataBit(KEY_DOWN_PORT, KEY_DOWN_PIN)
#define key_left_value GPIO_ReadInputDataBit(KEY_LEFT_PORT, KEY_LEFT_PIN)
#define key_right_value GPIO_ReadInputDataBit(KEY_RIGHT_PORT, KEY_RIGHT_PIN)// 按键
#define KEY_UP 0
#define KEY_DOWN 1
#define KEY_LEFT 2
#define KEY_RIGHT 3
#define KEY_NONE 4void key_init(void);
u8 key_scan(u8 mode);
#endif
2. 函数实现
#include key_utils.h
#include sys_tick_utils.hvoid key_init(void)
{GPIO_InitTypeDef GPIO_InitStructure; // 定义GPIO初始化结构体// 开启GPIOA的时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);// 设置上引脚GPIO_InitStructure.GPIO_Pin KEY_UP_PIN;// 设置输入下拉模式GPIO_InitStructure.GPIO_Mode GPIO_Mode_IPD;GPIO_Init(KEY_UP_PORT, GPIO_InitStructure); // 初始化GPIOA// 开 E 时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE);// 设置下、左、右引脚GPIO_InitStructure.GPIO_Pin KEY_DOWN_PIN | KEY_LEFT_PIN | KEY_RIGHT_PIN;// 设置输入上拉模式GPIO_InitStructure.GPIO_Mode GPIO_Mode_IPU;GPIO_Init(KEY_DOWN_PORT, GPIO_InitStructure); // 初始化GPIOE}
static u8 key_read(void){if(key_up_value 1 || key_down_value 0 || key_left_value 0 || key_right_value 0){delay_ms(10);if(key_up_value 1){return KEY_UP;}else if(key_down_value 0){return KEY_DOWN;}else if(key_left_value 0){return KEY_LEFT;}else if(key_right_value 0){return KEY_RIGHT;}}return KEY_NONE;
}
u8 last_key;
/*** brief 按键扫描函数* param mode: 0 单次扫描 1: 连续扫描*/
u8 key_scan(u8 mode)
{if(mode0){u8 key key_read();if(key ! KEY_NONE){if(key last_key){return KEY_NONE;}else{last_key key;return key;}}else{last_key KEY_NONE;}}else{return key_read();}return KEY_NONE;
}
3. 主体函数
#include gpio_utils.h
#include rcc_utils.h
#include stm32f10x.h
#include sys_tick_utils.h
#include led_utils.h
#include key_utils.h// 主函数
int main(void)
{GPIO_Configuration(); //调用GPIO配置函数sys_tick_init(72);led_all_off();key_init();while (1) //无限循环{delay_ms(10);u8 key key_scan(0);if(keyKEY_UP){led_lightn(0);}else if(keyKEY_DOWN){led_lightn(1);}else if(keyKEY_LEFT){led_lightn(2);}else if(keyKEY_RIGHT){led_lightn(3);}else{led_all_off();}}
}
本文源码地址 https://gitee.com/xundh/stm32_arm_learn/tree/master/lesson7_key