《STM32单片机开发应用教程(HAL库版)—基于国信长天嵌入式竞赛实训平台(CT117E-M4)》第四章4.3 按键控制实验
写在前面——
《STM32单片机开发应用教程(HAL库版)—基于国信长天嵌入式竞赛实训平台(CT117E-M4)》第四章4.3 按键控制实验,讲述按键控制的编程方法
官方例程下载:https://pan.baidu.com/s/1QC5BnDgY1m1me6-ihQ_OUQ?pwd=nqb1
提取码:nqb1
目录
- 4.3 按键控制实验
- 4.3.1. 实验任务
- 4.3.2. 硬件连接
- 4.3.3. GPIO初始化配置(STM32CubeMX)
- 4.3.4. 应用程序设计(KEIL5)
- 1. 按键控制LED显示
- 2. 通用函数---按键扫描函数(含消抖)
- 3. 按键控制程序设计(长/短按之分)
- (1)无长/短按之分
- (2)有长/短按之分
- 4 .小练习
- 4.3.5. 小结
4.3 按键控制实验
4.3.1. 实验任务
- 简单按键控制:官方例程HAL_02_KEY_TEST,实现4个按键控制对应的LED亮/灭。
- 拓展功能:编写按键扫描函数Key_scan、按键服务函数Key_proc,实现按键长/短按之分。
4.3.2. 硬件连接
开发板上共配备了4个按键,分别连接在PB0,PB1,PB2,PA0引脚上,引脚通过10K的电阻连接在电源正极VDD,按键的另一端连接在电源负极GND。
可知,在没有按键按下时,对应的GPIO输入高电平,有按键按下时,输入低电平。
4.3.3. GPIO初始化配置(STM32CubeMX)
参看2.3.1节所述步骤,配置STM32CubeMX相关选项(GPIO、RCC、SYS)。其中, LED涉及的GPIO(PD2、PC8 ~ PC15)全部设置为输出模式。按键对应的GPIO(PB0,PB1,PB2,PA0)全部设置为输入模式。
4.3.4. 应用程序设计(KEIL5)
1. 按键控制LED显示
参考官方例程2(HAL_02_KEY_TEST),编程思路:
- 先LED全灭
- 按键值判别
根据按键电路原理,按下时则能检测到输入值为0,否则为1,进行各个按键判别。
因此,先HAL_GPIO_ReadPin()读取某个按键值,再用if语句将读取值与0比较 - 对应的LED显示控制:某按键值为0,则置对应的LED控制引脚为0(亮)
关键程序设计如下:
/* USER CODE END 2 */HAL_GPIO_WritePin(GPIOC, GPIO_PIN_All, GPIO_PIN_SET);// GPIO_PIN_All,灯全灭HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);/* Infinite loop *//* USER CODE BEGIN WHILE */while (1){//B1,PB0if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_0) == GPIO_PIN_RESET){HAL_GPIO_WritePin(GPIOC, GPIO_PIN_8 | GPIO_PIN_9, GPIO_PIN_RESET);HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);}//B2,PB1if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1) == GPIO_PIN_RESET){HAL_GPIO_WritePin(GPIOC, GPIO_PIN_10 | GPIO_PIN_11, GPIO_PIN_RESET);HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);}//B3,PB2if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_2) == GPIO_PIN_RESET){HAL_GPIO_WritePin(GPIOC, GPIO_PIN_12 | GPIO_PIN_13, GPIO_PIN_RESET);HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);}//B4,PA0if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_RESET){HAL_GPIO_WritePin(GPIOC, GPIO_PIN_14 | GPIO_PIN_15, GPIO_PIN_RESET);HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);}}
}
2. 通用函数—按键扫描函数(含消抖)
上述HAL_02_KEY_TEST例程编程方法,适合简单的按键控制操作。稍复杂的按键控制,一般采用按键扫描方式实现采样按键值。
按键扫描函数为通用函数,只要涉及有KEY的题目,都需要编写此函数。
以下按键扫描函数,包含消抖功能(短暂延时前后两次读取按键引脚状态,通过两次按键值是否一致,判断按键是否被正确按下),实现4个按键按下后,输出值分别为0/1/2/3/4。
在main.c中用户添加代码区添加以下代码:
uint8_t Key_Scan(void) //按键扫描函数
{ if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_0) == 0) //PB0 (按键B1)被按下{HAL_Delay(10);//延时消抖if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_0) == 0){//while(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_0) == 1); //等待按键抬起return 1;//返回1}}if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1) == 0) //PB1 (按键B2)被按下{HAL_Delay(10);//延时消抖if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1) == 0){//while(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1) == 1); //等待按键抬起return 2;//返回2}}if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_2) == 0) //PB2 (按键B3)被按下{HAL_Delay(10);//延时消抖if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_2) == 0){//while(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_2) == 1); //等待按键抬起return 3; //返回3}}if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == 0) //PA0 (按键B4)被按下{HAL_Delay(10);//延时消抖if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == 0){//while(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == 1); //等待按键抬起return 4; //返回4}}return 0; //没有按键按下返回0
}
该程序代码较长,但是简单易懂。建议新手使用。
其中while(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_0) == 1)判断按键是否抬起(未按时按键值为1),看实际情况是否添加它。通常无需判断按键是否抬起。
为简化代码,可以采用以下程序设计,请自行理解:
uint8_t Key_Scan()
{uint8_t ucVal;if(~HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_All)&0x07){HAL_Delay(10);// 判断B1 B2和B3是否按下if(!HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_0))ucVal = 1;if(!HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1))ucVal = 2;if(!HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_2))ucVal =3;}// 判断B4是否按下if(!HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0)){HAL_Delay(10);if(!HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0))ucVal = 4;}return ucVal;
}
3. 按键控制程序设计(长/短按之分)
在按键扫描函数的基础上,根据所得的按键值,再实现相应的控制要求,按键1按下时点亮LED1,按键2按下时点亮LED2,等等。
这里,看题目要求,是否有长按、短按之分的要求。
(1)无长/短按之分
在main.c中用户添加代码区编辑按键服务函数KEY_Proc():
uint8_t ucKey,ucKeyLong; //全局变量定义
void KEY_Proc()
{ucKey = Key_Scan();//将按键扫描函数的返回值传递给全局变量ucKeyif(ucKey != ucKeyLong)//键值改变ucKeyLong = ucKey;//保存键值elseucKey = 0;//清除键值switch(ucKey){case 1:
//在短按时不加松手检测,长按就会不断触发短按的程序while(!HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_0));//等待B1按键抬起
/*这里添加 B1短按操作程序*/
break;/*case 2 ,其他按键控制程序,同上 */}
}
最后在while(1)中调用KEY_Proc();
(2)有长/短按之分
蓝桥杯赛题中,通常需要长按、短按实现不同按键功能。
在4.2节阐述sysTICK原理中,我们知道有个全局变量uwTick。当单片机上电后,uwTick自动累加计算(每1ms 自动累加1),数据类型为uint32_t。它是实现延时函数HAL_Delay()的关键变量。
这里使用全局变量uwTick,进行按键动作的计时,实现长短按键之分。
在main.c中用户添加代码区编辑按键服务函数KEY_Proc():
uint8_t ucKey,ucKeyLong; //全局变量定义
uint32_t ulTick_ms;
void KEY_Proc(void)
{ucKey = Key_Scan();ucKey = Key_Scan(); //按键扫描if(ucKey != ucKeyLong) //该if语句的作用是避免多次重复运行下面的switch语句,可省略{ucKeyLong = ucKey;//ucKeyLong的作用,保存键值ulTick_ms = uwTick;//记录下按键刚被按下时的时间,不能省略} elseucKey = 0; /*短按*/switch(ucKEY) { case 1: //添加松手检测,避免长按时不断触发短按的控制程序while(!HAL_GPIO_ReadPin(B1_GPIO_Port,B1_Pin)); /*这里添加 B1短按的控制程序*/break;/*case 2 ,其他按键短按控制程序 */}
/*长按*/if(uwTick - ulTick_ms > 800)//按下时间超过 0.8s { switch(ucKeyLong) { case 1: while(!HAL_GPIO_ReadPin(B1_GPIO_Port, B1_Pin)); //松手检测/*这里添加 B1长按操作程序*/break; /*case 2 ,其他按键长按控制程序 */}}
}
该程序中添加松手检测while(!HAL_GPIO_ReadPin(B1_GPIO_Port,B1_Pin)),可有效避免长按时不断触发短按的操作任务。
在此程序框架下,自行添加其他按键控制程序,实现题目的任务要求。
4 .小练习
设置两个电压参数的变量:Max_Volt 和Min_Volt ,取值范围为 0-3.3V,且Max_Volt > Min_Volt 。
B3:定义为“加”按键,当前选择的电压参数加 0.3V。
B4:定义为“减”按键,当前选择的电压参数减 0.3V。
程序设计:按键扫描函数Key_Scan同上,按键控制函数设计如下:
uint8_t ucKey,ucKeyLong,ucPara; //全局变量定义
void KEY_Proc()
{ucKey = Key_Scan();if(ucKey != ucKeyLong)ucKeyLong = ucKey;elseucKey = 0;switch(ucKey) { case 3:if(ucPara == 1)//选中Max_Volt这个参数{if(Max_Volt < 3.3f) //最大值加时考虑上限值3.3Max_Volt += 0.3f;}if(ucPara == 2) //选中Min_Volt这个参数{Min_Volt += 0.3f;if(Max_Volt - Min_Volt < 0.3f) //最小值加时考虑上限值<Max_voltMin_Volt -= 0.3f;} break; case 4:if(ucPara == 1)//选中Max_Volt这个参数{Max_Volt -= 0.3f;if(Max_Volt - Min_Volt < 0.3f) //最大值减时考虑下限值>Min_VoltMax_Volt += 0.3f;}if(ucPara == 2) //选中Min_Volt这个参数{if(Min_Volt > 0) //最小值减时考虑下限值为0Min_Volt -= 0.3f; }break;}
}
最后在while(1)中调用KEY_Proc()。
注意先给ucPara赋值1或者2,就可对两个电压参数的变量:Max_Volt 和Min_Volt进行按键控制。
4.3.5. 小结
- 引脚
PB0 ------> B0
PB1 ------> B1
PB2 ------> B2
PA0 ------> B3 - 编写按键扫描(含消抖)通用函数Key_scan();
- 编写按键服务函数Key_proc(),实现各个按键按下对应的功能实现程序。
注意长按/短按之分、松手判定
1)按键读取函数:HAL_GPIO_ReadPin();
2)按键消抖5~10ms即可
3)检测按键松开
while(!HAL_GPIO_ReadPin(B1_GPIO_Port,B1_Pin));
《STM32单片机开发应用教程(HAL库版)—基于国信长天嵌入式竞赛实训平台(CT117E-M4)》第四章4.3 按键控制实验相关推荐
- 《STM32单片机开发应用教程(HAL库版)—基于国信长天嵌入式竞赛实训平台(CT117E-M4)》第四章4.9 TIM---输入捕获(脉冲频率测量)实验
写在前面-- <STM32单片机开发应用教程(HAL库版)-基于国信长天嵌入式竞赛实训平台(CT117E-M4)>第四章4.9 TIM-输入捕获(脉冲频率测量)实验,讲解TIM输入捕获的原 ...
- 《STM32单片机开发应用教程(HAL库版)---基于国信长天嵌入式竞赛实训平台(CT117E-M4)》第二章 软件安装与使用
写在前面-- 作为<STM32单片机开发应用教程(HAL库版)-基于国信长天嵌入式竞赛实训平台(CT117E-M4)>系列之第二章,本章节将介绍开发软件STM32CubeMX和KEIL5的 ...
- 《STM32单片机开发应用教程(HAL库版)—基于国信长天嵌入式竞赛实训平台(CT117E-M4)》第四章4.1 LED显示控制实验
写在前面-- <STM32单片机开发应用教程(HAL库版)-基于国信长天嵌入式竞赛实训平台(CT117E-M4)>第四章4.1,本节将通过LED显示控制实验,学习STM32G431的开发技 ...
- STM32单片机开发应用教程 (HAL库版) ---基于国信长天嵌入式竞赛实训平台(CT117E-M4)教程汇总 与第一章 硬件平台简介
写在前面-- 作为<STM32单片机开发应用教程(HAL库版)-基于国信长天嵌入式竞赛实训平台(CT117E-M4)>教程汇总,第一章将介绍国信长天嵌入式竞赛实训平台(CT117E-M4) ...
- HAL库版STM32双轮自平衡车(四) ———— 原理图以及PCB绘制
系列文章目录 HAL库版STM32双轮自平衡车(一) ---代码思路和PID基础精讲 HAL库版STM32双轮自平衡车(二) --- CubeMX的配置.原理图接线.物料准备 HAL库版STM32双轮 ...
- HAL库版STM32双轮自平衡车(三) ———代码精讲
系列文章目录 编码电机测速 HAL库OLED的使用 HAL库版STM32双轮自平衡车(一) ---代码思路和PID基础精讲 HAL库版STM32双轮自平衡车(二) --- CubeMX的配置.原理图接 ...
- HAL库版STM32双轮自平衡车(一) ———代码思路和PID基础精讲
系列文章目录 HAL库版STM32双轮自平衡车(一) ---代码思路和PID的简单介绍(本篇) HAL库版STM32双轮自平衡车(二) --- CubeMX的配置.原理图接线.物料准备 HAL库版ST ...
- HAL库版STM32双轮自平衡车(五) ———— 调参
系列文章目录 HAL库版STM32双轮自平衡车(一) ---代码思路和PID基础精讲 HAL库版STM32双轮自平衡车(二) --- CubeMX的配置.原理图接线.物料准备 HAL库版STM32双轮 ...
- HAL库版STM32双轮自平衡车(二) ——— CubeMX的配置、原理图接线、物料准备
系列文章目录 编码电机测速 HAL库版 0.96'OLED的使用 HAL库版STM32双轮自平衡车(一) ---代码思路和PID的简单介绍 HAL库版STM32双轮自平衡车(二) --- CubeMX ...
最新文章
- 什么是 Design System
- Dictionary Serializer(Dictionary 序列化)
- mysql按周统计_MySQL按周统计 WEEK 实例
- 在一个.net sln中包含多个project,project引用同一个dll导致的错误
- 磁盘分区原理:从MBR到GPT
- python 整除的数组_计算和可被整除的所有子数组
- telnet收发邮件
- SQLServer如何在批量插入后,获取批量插入的自增列的值
- 打开计算机任务栏有桌面没,打开的窗口在任务栏上显示不出来?解决办法
- High-Sierra,MacOS10.13,增加IntelHD3000显存的方法
- 智能车学习(2)—— 舵机、电机
- 怎么在html中加校验,如何通过W3C验证?
- 倪光南华为鸿蒙,院士倪光南谈华为鸿蒙:国产操作系统需要生态支持
- 物联网智能家居系统解决方案
- 6612345免费网页打印浏览器
- 零钱通项目 - 韩老师
- 分享应用于桌面闹钟的超低成本MG127蓝牙射频前端芯片
- 在贷款行业中,运营商大数据精准获客,是否真实有效呢
- 秋招干货|给面试官满分的自我介绍
- Windows 下安装 Xdebug 受难记之(1)