温馨提示:本文不会重复之前提到的内容,如需查看,请参考附录。
目录
内容提炼:
如果比赛时只考察一个按键,那就可以考虑不使用专门的驱动程序,只使用驱动程序的其中一段即可。
比赛时为了节省时间,也可以直接在main.c中实现驱动,KEY驱动程序在三、代码编写中。
一、需求分析
1、需要的外设资源分析:
4个KEY信号引脚,8个LED控制引脚(LED配置与前文相同,这里不再赘述)
2、外设具体分析:
查看原理图,和手册。
根据原理图,选择PB0~PB2和PA0引脚作为KEY信号输入引脚,低电平有效。
KEY控制引脚配置为:输入,上拉。
3、软件分析:
要求分析:一个独立的驱动程序,需要在比赛时快速写出、简单、便于记忆。
功能分析:
a、轮询扫描四个按键,返回按下的按键值
b、编写常用代码switch框架
二、软件配置
新建建名为“dev_KEY_Demo”的项目。
可以按照【蓝桥杯嵌入式】三、省赛套路一条龙(一)工具配置新建项目,或者从test1中复制 .ioc 文件(建议新建练习一下)
复制 .ioc 文件以及基本操作与【蓝桥杯嵌入式】三、省赛套路一条龙(二)基本项目相同,结果如图:
生成项目文件后,打开MDK。
在 "D:\IoT-Engineer\IoT-Project\BBC-Demo\object\dev_KEY_Demo\Core"文件夹中新建两个.txt文件,分别命名为key.c和key.h(即后缀也要修改)
然后把.c文件放到Src,.h文件放到Inc。
然后将这两个文件Add进来,具体看上一篇文章【蓝桥杯嵌入式】三、省赛套路一条龙(二)基本项目。
三、代码编写
直接在main.c中实现,代码框架如下:
//按键1响应函数
void B1Fun()
{
}
//按键2响应函数
void B2Fun()
{
}
//按键3响应函数
void B3Fun()
{
}
//按键4响应函数
void B4Fun()
{
}
//按键扫描
void KeyScan()
{
uint32_t keyDelay=50;
if(HAL_GPIO_ReadPin(B1_GPIO_Port,B1_Pin)==GPIO_PIN_RESET)
{
HAL_Delay(keyDelay);
if(HAL_GPIO_ReadPin(B1_GPIO_Port,B1_Pin)==GPIO_PIN_RESET)
{
B1Fun();
}
}
if(HAL_GPIO_ReadPin(B2_GPIO_Port,B2_Pin)==GPIO_PIN_RESET)
{
HAL_Delay(keyDelay);
if(HAL_GPIO_ReadPin(B2_GPIO_Port,B2_Pin)==GPIO_PIN_RESET)
{
B2Fun();
}
}
if(HAL_GPIO_ReadPin(B3_GPIO_Port,B3_Pin)==GPIO_PIN_RESET)
{
HAL_Delay(keyDelay);
if(HAL_GPIO_ReadPin(B3_GPIO_Port,B3_Pin)==GPIO_PIN_RESET)
{
B3Fun();
}
}
if(HAL_GPIO_ReadPin(B4_GPIO_Port,B4_Pin)==GPIO_PIN_RESET)
{
HAL_Delay(keyDelay);
if(HAL_GPIO_ReadPin(B4_GPIO_Port,B4_Pin)==GPIO_PIN_RESET)
{
B4Fun();
}
}
}
驱动文件形式:较复杂但是规范
需要宏:
KEY_WAIT_ALWAYS:表示一直等待
需要值:
枚举类型:KEYS,表示各个按键
函数:
a、扫描按键
KEYS KEY_scan(超时时间);
搭配使用模块:
a、根据KEY_scan() 函数,确定按下的按键,利用swicth语句执行对应操作。
在MDK中编写代码,代码如下:
key.h:
#ifndef KEY_H_
#define KEY_H_
#include "main.h"
typedef enum {
KEY_NONE=0,
KEY1,
KEY2,
KEY3,
KEY4
}KEYS;
KEYS KEY_scan(void);
#endif /* KEY_H_ */
key.c:四段类似,记住一段,比赛时直接复制粘贴调整即可
#include "key.h"
KEYS KEY_scan(void)
{
const uint32_t btnDelay=20; //延时时间ms
GPIO_PinState keyState; //按键状态
while(1)
{
//扫描按键
keyState=HAL_GPIO_ReadPin(KEY1_GPIO_Port, KEY1_Pin);
if (keyState==GPIO_PIN_RESET)
{
HAL_Delay(btnDelay);
keyState=HAL_GPIO_ReadPin(KEY1_GPIO_Port, KEY1_Pin);
if (keyState ==GPIO_PIN_RESET)
return KEY1;
}
keyState=HAL_GPIO_ReadPin(KEY2_GPIO_Port, KEY2_Pin);
if (keyState==GPIO_PIN_RESET)
{
HAL_Delay(btnDelay);
keyState=HAL_GPIO_ReadPin(KEY2_GPIO_Port, KEY2_Pin);
if (keyState ==GPIO_PIN_RESET)
return KEY2;
}
keyState=HAL_GPIO_ReadPin(KEY3_GPIO_Port, KEY3_Pin);
if (keyState==GPIO_PIN_RESET)
{
HAL_Delay(btnDelay);
keyState=HAL_GPIO_ReadPin(KEY3_GPIO_Port, KEY3_Pin);
if (keyState ==GPIO_PIN_RESET)
return KEY3;
}
keyState=HAL_GPIO_ReadPin(KEY4_GPIO_Port, KEY4_Pin);
if (keyState==GPIO_PIN_RESET)
{
HAL_Delay(btnDelay);
keyState=HAL_GPIO_ReadPin(KEY4_GPIO_Port, KEY4_Pin);
if (keyState ==GPIO_PIN_RESET)
return KEY4;
}
}
}
常用代码框架:
/* USER CODE BEGIN WHILE */
while (1)
{
KEYS curKey=KEY_scan();
switch(curKey)
{
case KEY1:
break;
case KEY2:
break;
case KEY3:
break;
case KEY4:
break;
}
HAL_Delay(400); //弹起去抖动
/* USER CODE END WHILE */
四、运行测试
将【蓝桥杯嵌入式】四、各种外设驱动(一)LED中的LED驱动程序复制到本项目的Src和Inc
在main.h中引用"led.h"、“key.h”
在 main(void) 的 while(1) 代码段,编写以下代码
/* USER CODE BEGIN WHILE */
while (1)
{
KEYS curKey=KEY_scan();
switch(curKey)
{
case KEY1:
LED_change(LED1_Pin);
break;
case KEY2:
LED_change(LED2_Pin);
break;
case KEY3:
LED_change(LED3_Pin);
break;
case KEY4:
LED_change(LED4_Pin);
break;
}
HAL_Delay(400);
/* USER CODE END WHILE */
编译、下载。
运行结果如下:
KEY驱动测试