【鸿蒙开发】Hi3861学习笔记- GPIO之按键
00. 目录
文章目录
- 00. 目录
- 01. GPIO概述
- 02. 按键概述
- 03. 硬件设计
- 04. 软件设计
- 05. 实验现象
- 06. 附录
01. GPIO概述
GPIO(General-purpose input/output)即通用型输入输出。通常,GPIO控制器通过分组的方式管理所有GPIO管脚,每组GPIO有一个或多个寄存器与之关联,通过读写寄存器完成对GPIO管脚的操作。
基本概念
GPIO又俗称为I/O口,I指的是输入(in),O指的是输出(out)。可以通过软件来控制其输入和输出,即I/O控制。
-
GPIO输入
输入是检测各个引脚上的电平状态,高电平或者低电平状态。常见的输入模式有:模拟输入、浮空输入、上拉输入、下拉输入。
-
GPIO输出
输出是当需要控制引脚电平的高低时需要用到输出功能。常见的输出模式有:开漏输出、推挽输出、复用开漏输出、复用推挽输出。
02. 按键概述
按键是一种电子开关,使用时轻轻按开关按钮就可使开关接通,当松开手时,开关断开。一般机械按键按下和松开时存在抖动情况,如下:
这种抖动可能会影响程序误判,造成严重后果,通常会使用软件延时 10ms来消斗。例如,当按键按下后,引脚为低电平;所以首先读取
引脚电平,若引脚为低电平,则延时 10ms 后再次读取引脚电平,若为低电平,则证明按键已按下。
消抖方案对比
方案 | 优点 | 缺点 |
---|---|---|
RC滤波 | 成本低、简单易实现 | 响应速度较慢 |
RS锁存器 | 无抖动、可靠性高 | 需要额外逻辑芯片 |
软件消抖 | 无需硬件、灵活可调 | 依赖MCU资源及代码质量 |
03. 硬件设计
由图可知,P1 端子的 KEY1-KEY2 脚为按键控制端,要检测按键是否被按下,只需读取端子的 KEY1-KEY2 脚是否为低电平,因此可使用
导线将芯片的 IO 口与P1 端子的 KEY1-KEY2 脚连接。
04. 软件设计
bsp_key.h
#ifndef BSP_KEY_H
#define BSP_KEY_H
#include "cmsis_os2.h"
#include "hi_io.h"
#include "hi_gpio.h"
//管脚定义
#define KEY1_PIN HI_IO_NAME_GPIO_11
#define KEY1_GPIO_FUN HI_IO_FUNC_GPIO_11_GPIO
#define KEY2_PIN HI_IO_NAME_GPIO_12
#define KEY2_GPIO_FUN HI_IO_FUNC_GPIO_12_GPIO
//使用宏定义独立按键按下的键值
#define KEY1_PRESS 1
#define KEY2_PRESS 2
#define KEY_UNPRESS 0
//函数声明
void key_init(void);
uint8_t key_scan(uint8_t mode);
#endif
bsp_key.c
#include "bsp_key.h"
#include <unistd.h>
//按键初始化
void key_init(void)
{
hi_gpio_init(); // GPIO初始化
hi_io_set_pull(KEY1_PIN, HI_IO_PULL_UP); // 设置GPIO上拉
hi_io_set_func(KEY1_PIN, KEY1_GPIO_FUN); // 设置IO为GPIO功能
hi_gpio_set_dir(KEY1_PIN, HI_GPIO_DIR_IN); // 设置GPIO为输入模式
hi_io_set_pull(KEY2_PIN, HI_IO_PULL_UP); // 设置GPIO上拉
hi_io_set_func(KEY2_PIN, KEY2_GPIO_FUN); // 设置IO为GPIO功能
hi_gpio_set_dir(KEY2_PIN, HI_GPIO_DIR_IN); // 设置GPIO为输入模式
}
/*******************************************************************************
* 函 数 名 : key_scan
* 函数功能 : 检测独立按键是否按下,按下则返回对应键值
* 输 入 : mode=0:单次扫描按键
mode=1:连续扫描按键
* 输 出 : KEY1_PRESS:K1按下
KEY2_PRESS:K2按下
KEY_UNPRESS:未有按键按下
*******************************************************************************/
uint8_t key_scan(uint8_t mode)
{
static uint8_t key1=0;
static uint8_t key2=0;
hi_gpio_get_input_val(KEY1_PIN,&key1);
hi_gpio_get_input_val(KEY2_PIN,&key2);
if(key1==0 || key2==0)
{
usleep(10*1000);//消抖
hi_gpio_get_input_val(KEY1_PIN,&key1);
hi_gpio_get_input_val(KEY2_PIN,&key2);
if(key1==0 || key2==0)
{
if(key1==0)return KEY1_PRESS;
else if(key2==0)return KEY2_PRESS;
}
}
return KEY_UNPRESS;
}
template.c
#include <stdio.h>
#include <unistd.h>
#include "ohos_init.h"
#include "cmsis_os2.h"
#include "bsp_key.h"
#include "bsp_led.h"
//按键控制任务
osThreadId_t KEY_Task_ID; //任务ID
void KEY_Task(void)
{
uint8_t key=0;
led_init();//LED初始化
key_init();//按键初始化
while (1)
{
key=key_scan(0);//按键扫描
if(key==KEY1_PRESS)LED(1);//点亮
else if(key==KEY2_PRESS)LED(0);//熄灭
usleep(10*1000);
}
}
//按键控制任务创建
void key_task_create(void)
{
osThreadAttr_t taskOptions;
taskOptions.name = "keyTask"; // 任务的名字
taskOptions.attr_bits = 0; // 属性位
taskOptions.cb_mem = NULL; // 堆空间地址
taskOptions.cb_size = 0; // 堆空间大小
taskOptions.stack_mem = NULL; // 栈空间地址
taskOptions.stack_size = 1024; // 栈空间大小 单位:字节
taskOptions.priority = osPriorityNormal; // 任务的优先级
KEY_Task_ID = osThreadNew((osThreadFunc_t)KEY_Task, NULL, &taskOptions); // 创建任务1
if (KEY_Task_ID != NULL)
{
printf("ID = %d, Task Create OK!\n", KEY_Task_ID);
}
}
/**
* @description: 初始化并创建任务
* @param {*}
* @return {*}
*/
static void template_demo(void)
{
printf("-Hi3861开发板--按键控制实验\r\n");
key_task_create();//按键任务
}
SYS_RUN(template_demo);
05. 实验现象
下载程序前,按照如下接线
实验现象:按键 K1-K2 控制 LED 指示灯亮灭。