STM32F7xx —— 输入

目录

STM32F7xx —— 输入

一、输入配置

二、输入扫描

三、输入处理


一、输入配置

为了灵活使用,我们将输入的有效电平设置成可配置。同样是列表表示所有IO口。

// 配置有效电平
typedef enum
{KEY_INIT_IS_ACTIVE = 0,KEY_LOW_IS_ACTIVE  = 1,KEY_HIGH_IS_ACTIVE = 2,
} key_active_t;#define KEY_CONFIG(gpio, pin)     GPIOConfig(gpio, pin, GPIO_MODE_INPUT, GPIO_PULLUP)
#define KEY_READ(gpio, pin)       HAL_GPIO_ReadPin(gpio, pin)#define KEY1_PORT                 GPIOH
#define KEY1_PIN                  GPIO_PIN_3#define KEY2_PORT                 GPIOH
#define KEY2_PIN                  GPIO_PIN_2#define KEY3_PORT                 GPIOC
#define KEY3_PIN                  GPIO_PIN_13
// demo代码 只传递思想static void key_gpio_config(GPIO_TypeDef *gpio, uint16_t pin)
{KEY_CONFIG(gpio, pin);
}typedef struct
{GPIO_TypeDef *gpio;uint16_t pin;
} key_port_t;static key_port_t key_entries[] =
{{KEY1_PORT, KEY1_PIN},{KEY2_PORT, KEY2_PIN},{KEY3_PORT, KEY3_PIN},
};void KeyInit(void)
{uint32_t i, mask = 1;for(i = 0; i < ARRAY_SIZE(key_entries); ++i){if(0xFFFFFFFF & mask){key_gpio_config(key_entries[i].gpio, key_entries[i].pin);#if(CONFIG_KEY_TEST == 1) // 测试时使用      //config.key.total_switch  = KEY_MODE_OPEN;//config.key.sub_switch[i] = KEY_MODE_OPEN;config.key.active_tag[i] = KEY_LOW_IS_ACTIVE;
#endif}mask <<= 1;}
}// 输入是否可用
static uint8_t key_is_enable(uint8_t index)
{// 这里可以写成可配置 配置IO口可用或者不可用(类似一个总开关)return 1;
}// 有输入到来
static uint8_t key_is_pressed(uint8_t index)
{if(key_is_enable(index)){if(KEY_LOW_IS_ACTIVE == config.key.active_tag[index]){if(KEY_READ(key_entries[index].gpio, key_entries[index].pin) == 0){return 1;}}else if(KEY_HIGH_IS_ACTIVE == config.key.active_tag[index]){if(KEY_READ(key_entries[index].gpio, key_entries[index].pin) == 1){return 1;}}}return 0;
}// 按键被按下
uint8_t Key1IsDown(void)
{return key_is_pressed(0);
}uint8_t Key2IsDown(void)
{return key_is_pressed(1);
}uint8_t Key3IsDown(void)
{return key_is_pressed(2);
}

二、输入扫描

// 按键的状态机结构定义
// 按键状态
typedef enum
{KEY_STATE_INIT, // 缺省按键状态KEY_STATE_UP,   // 按键弹起状态KEY_STATE_DOWN, // 按键按下状态KEY_STATE_LONG, // 按键长按状态KEY_STATE_AUTO, // 按键自动连发状态
} key_state_t;// 按键滤波时间20ms, 单位10ms。
// 只有连续检测到20ms状态不变才认为有效,包括弹起和按下两种事件
// 即使按键电路不做硬件滤波,该滤波机制也可以保证可靠地检测到按键事件
#define KEY_FILTER_TIME 2   // 滤波消抖
#define KEY_LONG_TIME   100 // 单位10ms    持续1秒,认为长按事件
#define KEY_REPEAT_TIME 100 // 单位10ms    持续1秒,自动连发typedef uint8_t (*key_cb)(void);
typedef struct
{uint8_t state;        // 按键当前状态(按下还是弹起)uint8_t last;         // 上一次按键的状态uint8_t count;        // 滤波消抖计数器uint16_t long_time;   // 按键按下持续时间, 0表示不检测长按uint16_t long_count;  // 长按计数器uint8_t repeat_speed; // 连续按键周期uint8_t repeat_count; // 连续按键计数器key_cb is_down_func;  // 按键按下的判断函数,1表示按下
} key_t;static key_t key_items[] =
{{KEY_STATE_INIT, KEY_STATE_INIT, KEY_FILTER_TIME, KEY_LONG_TIME, 0, KEY_REPEAT_TIME, 0, Key1IsDown},{KEY_STATE_INIT, KEY_STATE_INIT, KEY_FILTER_TIME, KEY_LONG_TIME, 0, KEY_REPEAT_TIME, 0, Key2IsDown},{KEY_STATE_INIT, KEY_STATE_INIT, KEY_FILTER_TIME, KEY_LONG_TIME, 0, KEY_REPEAT_TIME, 0, Key3IsDown},
};
// 按键状态机key_scan
// 配置限制条件在这个函数里面加
static void key_scan_ext(key_t *entry, uint8_t i)
{switch(entry->state){case KEY_STATE_INIT:case KEY_STATE_UP:{entry->state = KEY_STATE_DOWN; // 按键被按下break;}case KEY_STATE_DOWN:{if(entry->long_time > 0){if(entry->long_count < entry->long_time){if(++entry->long_count >= entry->long_time){entry->state = KEY_STATE_LONG;}}}break;}case KEY_STATE_LONG:{if(entry->repeat_speed > 0) // 自动连发时间到  自动连发事件{if(++entry->repeat_count >= entry->repeat_speed){entry->repeat_count = 0;// 长按触发}}break;}}entry->last = entry->state; // 最新的按键状态
}static void key_scan(uint8_t i)
{key_t *entry = &key_items[i];uint8_t key;if(entry->is_down_func()){if(entry->count < KEY_FILTER_TIME) // 消抖{++entry->count;}else{key_scan_ext(entry, i); // 按键扫描状态机}}else{if(entry->count > KEY_FILTER_TIME){entry->count = KEY_FILTER_TIME;}else if(entry->count > 0){--entry->count;}else{if(KEY_STATE_DOWN == entry->last) // 一次完整的按键到这里就弹起了{// 按键按下之后可以加入到队列中,这里的队列可以自己写;如果带系统可以使用系统的消息队列等方式。// key = i + 1;// xQueueSend(os_key_queue, &key, 10); }entry->last  = KEY_STATE_UP;entry->state = KEY_STATE_UP; // 按键弹起状态}entry->long_count = 0;entry->repeat_count = 0; // 清空计数器}
}

三、输入处理

// 按键按下之后,会将值加入到队列中,我们读取队列数据,然后扫描列表匹配功能
static void key1_cb(void);
static void key2_cb(void);
static void key3_cb(void);#define KEY1_CMD         1
#define KEY2_CMD         2
#define KEY3_CMD         3typedef struct
{uint8_t cmd;void (* key_handle_cb)(void);
} key_handle_t;static const key_handle_t key_entries[] =
{{KEY1_CMD, key1_cb},{KEY2_CMD, key2_cb},{KEY3_CMD, key3_cb},{0xFF, NULL  },
};// 按键的通用功能
static void key_func(uint8_t func)
{}static void key1_cb(void)
{}static void key2_cb(void)
{}static void key3_cb(void)
{}static void key_process(uint8_t event)
{const key_handle_t *entry;for(entry = key_entries; entry->key_handle_cb; ++entry){if(event == entry->cmd){entry->key_handle_cb();break;}}
}

裸机:按键扫描20ms执行一次,按键处理直接丢在主函数中。(自己写队列)

系统:在任务中执行按键扫描和按键处理。(系统自带队列或者邮箱)

STM32F7xx —— 输入相关推荐

  1. [转]深度学习在目标跟踪中的应用

    原文链接:https://zhuanlan.zhihu.com/p/22334661 开始本文之前,我们首先看上方给出的3张图片,它们分别是同一个视频的第1,40,80帧.在第1帧给出一个跑步者的边框 ...

  2. 卷积神经网络超详细介绍(转载)

    卷积神经网络超详细介绍 文章目录 1.卷积神经网络的概念 2. 发展过程 3.如何利用CNN实现图像识别的任务 4.CNN的特征 5.CNN的求解 6.卷积神经网络注意事项 7.CNN发展综合介绍 8 ...

  3. STM32F7xx —— LAN8720(FreeRTOS+LWIP)

    STM32F7xx -- LAN8720 STM32F767自带以太网模块,需要外接PHY芯片,完成以太网通信(MII/RMII接口).LAN8720详细资料看手册.LWIP:1.4.1 FreeRT ...

  4. STM32F7xx —— 输出

    STM32F7xx -- 输出 目录 STM32F7xx -- 输出 一.几个重要的IO口操作函数 二.几个重要的结构 三.封装两个GPIO初始化函数(普通GPIO,复用GPIO) 四.输出接口设计 ...

  5. java命令行读入密码_java-在命令行上隐藏输入

    是的,可以做. 这称为命令行输入屏蔽. 您可以轻松实现此目的. 您可以使用单独的线程擦除输入的回显字符,并用星号替换. 使用下面显示的EraserThread类完成此操作 import java.io ...

  6. C++ 笔记(36)— 接收输入字符串的几种方法

    C++中常见的几种输入字符串的方法如下: std::cin.std::cin.get().std::cin.getline().std::getline().std::gets().std::getc ...

  7. C++ OJ 中多行数据输入(大小写转换、通过移位运算实现2的n次方、多组输入,每行输入数量不一样)

    1. 多组输入,输出每行最大值 while(cin>>a>>b) 主要解决的是两个为一组的多组数据输入,当一次只输入一个数据时就用 while(cin>>a) 输入 ...

  8. Anaconda3-5.0.1 输入ipython 出现 ImportError: cannot import name ‘create_prompt_application‘

    在 Windows 系统上安装 Anaconda3-5.0.1 版本后,输入 ipython 结果出现如下错误: (G:\Anaconda3-5.0.1\install) C:\Users\wohu& ...

  9. Linux shell 学习笔记(11)— 理解输入和输出(标准输入、输出、错误以及临时重定向和永久重定向)

    1. 理解输入和输出 1.1 标准文件描述符 Linux 系统将每个对象当作文件处理.这包括输入和输出进程.Linux 用文件描述符(file descriptor)来标识每个文件对象.文件描述符是一 ...

最新文章

  1. core identity mysql_Asp.Net Core Identity 4 改成 MySql/MariaDB
  2. 2021第一季度云智能生态技术服务能力盘点
  3. 2013年人人校园招聘笔试题
  4. 硬核!C语言八大排序算法,附动图和详细代码解释!
  5. 使用linux内核编译独立系统,编译linux内核以及depmod的使用
  6. windows中运行qt5构建的程序提示 无法启动此程序,因为计算机中丢失qt5Cored.dll 解决方法
  7. POJ 1151 扫描线 线段树
  8. [UWP开发]NavigationView基础使用方法
  9. 深度学习斯坦福cs231n 课程笔记
  10. 蓝牙鼠标windows linux,在Deepin和Windows 10双系统中蓝牙4.0鼠标共享使用的方法
  11. 如何虚拟打印PDF文件(Win7)
  12. html将option设为默认,select设置option默认
  13. 《组合数学引论》第二章部分习题解答
  14. 远程桌面不能复制粘贴
  15. IDEA 设置自动启动的浏览器
  16. OSPF50个经典问题
  17. 不要过分相信基础函数, 因为那也是人写的------警惕负负得正的现有逻辑之坑
  18. 掌上智维技术支持 App Tech Support
  19. 零基础入门学习Python 011列表:一个打了激素的数组2
  20. 【Apollo配置中心】Apollo环境配置

热门文章

  1. mapreduce shuffle过程问答
  2. 谈“80后”程序员为什么找不到工作? [转]
  3. 组播相对于单播和广播的优势
  4. 26-- 转换成小写字母
  5. 网络爬虫--11.XPath和lxml
  6. 嵌入式面试中常见的编程题目
  7. 5类6类7类网线对比_孩子们长高的黄金时期是从3月到5月,这阶段多吃6类食物长得快...
  8. jeecms附件标签用法
  9. 【面试】c++单例模式
  10. SpringCloud学习--微服务架构