正点原子STM32F103(精英版)------按键输入
配合正点原子视频(工程新建与路径加入省略)
按键输入硬件连接:
【KEY0 和 KEY1 是低电平有效的,而 KEY_UP 是高电平有效的】
1)读取IO口输入电平调用库函数为:
uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
2)读取IO口输入电平操作寄存器为: GPIOx_IDR:端口输入寄存器
3)使用位带操作读取IO口输入电平:
PEin(4) -读取GPIOE.4口电平
PEin(n) -读取GPIOE.n口电平
外部都没有上下拉电阻,所以,需要在 STM32F1 内部设置上下拉。
C语言关键字 :static
int getValue(void)
{int flag=0;
for(int i=0;i<=3;i++){flag++;}return flag;
}//函数执行两次后 值为3
int getValue(void)
{static int flag=0;
for(int i=0;i<=3;i++){flag++;}return flag;
}//函数执行两次后 值为6 (第二次执行函数时,flag值为3继续执行++)
实验思想
按键扫描(支持连续按)的一般思路
【如果我要实现:按键按下,没有松开,只能算按下一次,这个函数无法实现。】
u8 KEY_Scan(void){if(KEY按下){delay_ms(10);//延时10-20ms,防抖。if(KEY确实按下){return KEY_Value;}return 无效值;}}
按键扫描(不支持连续按)的一般思路
【不支持连续按:就是说,按键按下了,没有松开,只能算一次。】
u8 KEY_Scan(void){static u8 key_up=1;if(key_up && KEY按下){delay_ms(10);//延时,防抖key_up=0;//标记这次key已经按下if(KEY确实按下){return KEY_VALUE;}}else if(KEY没有按下) key_up=1;return 没有按下}
按键扫描(两种模式合二为一)的一般思路
u8 KEY_Scan(u8 mode){static u8 key_up=1;if(mode==1) key_up=1;//支持连续按if(key_up && KEY按下){delay_ms(10);//延时,防抖key_up=0;//标记这次key已经按下if(KEY确实按下){return KEY_VALUE;}}else if(KEY没有按下) key_up=1;return 没有按下}
一.库函数版本
1.按键输入实验步骤
在实验一跑马灯的基础上实现按键输入(直观看出是否有按下操作,按下灯亮)
1)使能IO口时钟。调用函数 RCC_APB2PeriphClockCmd();
2)初始化IO模式:上拉/下拉输入。 调用函数GPIO_Init();
3)扫描IO口电平。
key.h
#if ndef __KEY_H
#define __KEY_H
#include "sys.h"
#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_PRES 1 //KEY0 按下
#define KEY1_PRES 2 //KEY1 按下
#define WKUP_PRES 3 //WK_UP 按下void KEY_Init(void); //IO 初始化
u8 KEY_Scan(u8); 按键扫描函数
#endif
KEY0------PE4 (GPIO_Pin_4)
因此 #define KEY0 GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_4) //读取按键 0
key.c
#include "key.
#include "sys.h"
#include "delay.h"
//按键初始化函数
void KEY_Init(void) //IO 初始化
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOE,ENABLE);
//使能PORTA,PORTE 时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3|GPIO_Pin_4;// GPIO.E 3 ~4
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //设置成上拉输入
GPIO_Init(GPIOE, &GPIO_InitStructure); //初始化 GPIOE3,4
GPIO_InitStr ucture.GPIO_Pin = GPIO_Pin_0; //初始化 WK_UP ---->GPIOA.0
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //PA0 设置成输入,下拉
GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化 GPIOA.0
}//按键处理函数
//返回按键值
//mode: 0不支持连续按 ; 1支持连续按
//0 ,没有任何按键按下
//1 KEY0 按下
//2 KEY1 按下
//3 WK_UP 按下
//注意此函数有响应优先级 ,KEY0>KEY1>WK_UPu8 KEY_Scan(u8 mode)
{
static u8 key_up=1;// 按键按松开标志
if(mode)key_up=1; // 支持连按
if(key_up&&(KEY0==0||KEY1==0||WK_UP==1))
{ delay_ms(10);// 去抖动key_up=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_up=1;return 0;// 无按键按下
}
KEY_Init() :是用来初始化按键输入的 IO 口的。
KEY_Scan() : 是用来扫描这 3 个 IO 口是否有按键按下。
当mode 为 0 的时候, KEY_Scan 函数将不支持连续按, 扫描某个按键,该按键按下之后
必须要松开,才能第二次触发,否则不会再响应这个按键,这样的好处就是可以防止按一次多
次触发,而坏处就是在需要长按的时候比较不合适。
当mode 为 1 的时候, KEY_Scan 函数将支持连续按,如 果某个按键一直按下,则会一直
返回这个按键的键值,这样可以方便的实现长按检测。
main.c
#include "led.h"
#include "delay.h"
#include "key.h"
#include "sys.h"
#include "beep.h"//按键输入实验
int main(void)
{u8 key;delay_init(); 延时函数初始化LED_Init(); //LED 端口初始化KEY_Init(); 初始化与按键连接的硬件接口BEEP_Init(); 初始化蜂鸣器端口LED0=0; 先点亮红灯while(1){key =KEY_Scan(0) // 得到键值if(key){ switch(key){ 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);}
}
二.寄存器版本
key.h
#ifndef __KEY_H
#define __KEY_H
#include "sys.h"
#define KEY0 PEin(4) //PE4
#define KEY1 PEin(3) //PE3
#define WK_UP PAin(0) //PA0#define KEY0_PRES 1 //KEY0按下
#define KEY1_PRES 2 //KEY1按下
#define WKUP_PRES 3 //WKUP按下void KEY_Init(void); //IO初始化
u8 KEY_Scan(u8); //按键扫描函数
#endif
宏定义段也有另一种写法,上述写法简单明了,但是下面的写法更易移植
#define KEY0 (1<<4) //KEY0 PE4
#define KEY1 (1<<3) //KEY1 PE3
#define WK_UP (1<<0) //KEY_UP PA0
#define KEY0_GET() ((GPIOE-->IDR&(KEY0))?1 0) //读取按键 KEY0
KEY0 #define KEY1_GET() ((GPIOE-->IDR&(KEY1))?1 0) //读取按键 KEY1
KEY1 #define WK_UP _GET() ((GPIOA-->IDR&( WK_UP))?1 0) //读取按键 WK_UP
key.c
#include "key.h"
#include "delay.h"//按键初始化函数
void KEY_Init(void)
{RCC->APB2ENR|=1<<2; //使能PORTA时钟RCC->APB2ENR|=1<<6; //使能PORTE时钟GPIOA->CRL&=0xFFFFFFF0; //PA0设置成输入,默认下拉GPIOA->CRL|=0x00000008; GPIOE->CRL&=0xFFF00FFF; //PE3/4设置成输入GPIOE->CRL|=0x00088000; GPIOE->ODR|=3<<3; //PE3/4 上拉
}//按键处理函数
//返回按键值
//mode:0,不支持连续按 ;1,支持连续按 ;
//0,没有任何按键按下
//1 KEY0按下
//2 KEY1按下
//3 KEY_UP按下 即 WK_UP //注意此函数有响应优先级 ,KEY0>KEY1>KEY_UP!!u8 KEY_Scan(u8 mode)
{static u8 key_up=1; //按键按松开标志if(mode)key_up=1; //支持连按if (key_up&&(KEY0==0||KEY1==0||WK_UP==1)){delay_ms(10); //去抖动key_up=0;if(KEY0==0)return 1;else if(KEY1==0)return 2;else if(WK_UP==1)return 3;}else if(KEY0==1&&KEY1==1&&WK_UP==0)key_up=1;return 0; //无按键按下
}
main.c
#include "sys.h"
#include "led.h"
#include "beep.h"
#include "delay.h"
#include "key.h"int main (void)
{u8 key;Stm32_Clock_Init(9); //系统时钟设置delay_init(72); //延时初始化LED_Init();BEEP_Init();KEY_Init();LED0=0; //先点亮红灯while(1){key=KEY_Scan(0); //得到键值if(key){switch(key){case WKUP_PRES://BEEP=!BEEP;break;case KEY1_PRES:LED1=!LED1;break;case KEY0_PRES:LED1=!LED1;LED0=!LED0;break;}}elsedelay_ms(10);}
}
正点原子STM32F103(精英版)------按键输入相关推荐
- 正点原子STM32F103精英版开发环境搭建并编写第一个程序(使用串口下载,基于HAL库)
一:软件下载: 使用图形化配置软件:STM32cubeMX,支持HAL库. 1,下载stm32cubeMX; 2,下载STM32f103器件包: 3,下载IED:keil5 arm版本: 4,下载 s ...
- 正点原子STM32F103精英版学习笔记(二)
#使用ST-LINK下载调试程序 **应用场景:**如果工程的代码比较大,难免存在bug,就需要硬件调试解决 ST-LINK 和STM32F103都支持JTAG 和SWD,用JTAG调试时占用的IO线 ...
- 基于正点原子STM32F1精英版秒表(库函数版)
基于正点原子STM32F1精英版秒表(库函数版) 一.前期准备 二.代码实现: 1.独立按键与触摸按键 2.TFTLCD 3.定时器 4.蜂鸣器与LED灯 5.主函数设计 三. 结束语: 一.前期准备 ...
- 基于正点原子STM32F103精英板IIC实验的MS5611气压计的使用
MS5611是一款气压计,能够提供高精度的气压值与温度值,这次做项目正好需要用到这款传感器,包括之前也没好好学习用过IIC,所以写下博客记录一下. 如果有需要使用的朋友可以去https://downl ...
- 正点原子STM32精英版LCD实验白屏
最近在咸鱼上买了一块正点原子的STM32精英版,带一个2.8寸的lcd屏幕,然后下载官方的历程测试,但是到lcd实验的时候发现下载样例后屏幕仍然是白色的,这让我很疑惑,于是我直接下载最后一个综合实验, ...
- 用正点原子的精英版与onenet云平台连接
关于这个想法我也是做了接近3个月,由于一直没有找到现成的例子,加上修改端口但是看不懂原理,也是不愿意去做的,现在就展示下我这3个月的成品把 ![这是onenet的效果展示](https://img-b ...
- 正点原子STM32f103ZE精英开发板实现基于ESP8266 WIFI模块温湿度数据上传至乐联网平台
文章目录 一.准备工作 二.实现流程 1.AT指令 2.接入乐联网平台 3.代码实现 三.数据可视化分析 一.准备工作 1.准备一块正点原子STM32f103ZE精英开发板 2.在某宝上购买好正点原子 ...
- STM32F103RB 实作笔记(六)- HC-05 蓝牙模组与手机 APP(正点原子 STM32F103 nano开发板)程式解析
这一篇文章是为后面的实验做的一个准备工作 我们在做开发板扩展时,最不喜欢遇到的就是"不知道发生了什么事"!所以, 会用一些输出显示装备来告诉我们,现在已经在哪里了. 譬如,前一个实 ...
- STM32F103RB 实作笔记(九)- PWM + SPI +MAX6675 整合试验 (正点原子 STM32F103 nano开发板)程式解析
个人工作上的关系,需要做一款温度控制风扇速度的控制器,还需要能够看到温度和PWM的值.于是我用这个不熟悉的 STM32F103 试试,顺便把 PWM 和 SPI 也了解一番. 一开始当然也是跌跌撞撞, ...
- 对于威纶通MT8071ip与正点原子stm32f103的modbus通信,如何接线和配置
1.威纶通与正点原子stm32f103的接线关系:威纶通的针脚1接stm32f103开发板的RS485的B端口,针脚2接RS485的A端口. 2.如果是威纶通接usb转串口485的接口,那就是针脚1接 ...
最新文章
- 【ShareCode】不错的技术文章 -- 如何使用异或(XOR)运算找到数组中缺失的数?...
- 关于JAVA中URL传递中文参数,取值是乱码的解决办法
- java 实现队列读写锁_史上最全的Java并发系列之Java中的锁的使用和实现介绍(二)...
- 七个非常好用的黑科技APP,免费/小众/超实用,一次性全给你
- 18个小实例入门SQLServer XML查询
- DuiLib快速入门。你的第一个DuiLib程序
- Java、JSP公文流转系统
- pointnet源码阅读:训练
- 高通平台紧急呼叫问题总结
- python opencv实现三角测量(triangulation)
- 2.4. Prompting
- 人们从诗人的字句里选取自己心爱的意义但诗句的最终意义是指向你
- 树莓派3B+ 人脸识别(OpenCV)
- 前端实现轮播图的三种方法。
- docker学习(四) 配置阿里云镜像加速器
- ZYNQ 图像处理之千兆网传(一)【寄存器级操作】
- win10系统服务器在哪里设置,服务器win10在哪里设置方法
- cdkey和激活码的生成
- python 复杂网络中的 SIR 模型
- 抖小火山视频服务器维护中,抖音、火山小视频、悟空问答昨天都崩了
热门文章
- Codeforces Round #290 (Div. 2)C
- java中Int范围越界检测
- inline函数不报重定义错误浅析
- 报道|香港科大EMBA苏州招生说明会暨体验课堂成功举办
- 腾讯WEB加速器 原理分析手记
- 使用YOLOV5进行手势识别(详细教程)
- 麦塔金,告诉大家图形用户界面是个人用户电脑操作系统不可分割的一部分,重新定义了操作系统...
- 如何利用Smartbi电子表格进行财务常用账簿数据的联动查询
- Anaconda安装pytorch——清华镜像源不稳定
- Vue3.0 setup的使用及作用