STM32F7xx —— 输入

                              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执行一次,按键处理直接丢在主函数中。(自己写队列)

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

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/465644.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Kernel中如何操作CPU及外设寄存器

01ARM Coretex-A9寄存器对于ARM Coretex-A9处理器而言其寄存器主要包括两大部分&#xff0c;分别是通用寄存器以及系统控制寄存器。上图所示的通用寄存器&#xff0c;主要是在代码运行过程中使用到&#xff0c;CPU通过该部分寄存器执行代码并完成相关的运算操作。对于调试过程中…

初识设计模式(装饰者模式)

前言&#xff1a;总结这两天学到的装饰者模式&#xff0c;并用java小小的实现一下。书中有写到&#xff1a;给爱用继承的人一个全新的设计眼界。&#xff08;ps&#xff0c;本文最后有个小问题待解决&#xff09; 什么是装饰者模式&#xff08;Decorator Pattern&#xff09;&a…

帮一个读者解锁手机

昨天晚上&#xff0c;深圳下了好大好大的雨&#xff0c;我还在加班的时候&#xff0c;小云就发消息说家里打雷很大&#xff0c;到了十点多&#xff0c;我打开手机准备打车&#xff0c;发现打车排队有800多人&#xff0c;然后我赶紧冲下楼&#xff0c;拿起两个雨衣&#xff0c;消…

STM32F7xx —— 96位唯一ID

STM32F7xx —— 96位唯一ID // 配置单片机型号 对外只有这个宏CONFIG_SYSTEM_HARDWARE_TYPE #define CONFIG_SYSTEM_HARDWARE_TYPE SOC_TYPE_STM32F7// SOC类型 typedef enum {SOC_TYPE_STM32F0,SOC_TYPE_STM32F1,SOC_TYPE_STM32F2,SOC_TYPE_STM32F3,SOC_TYPE_STM32F4,SOC_TY…

我喜欢这样的老大[10-24]

据说原图是奥巴马和一个小朋友打雪仗&#xff0c;下面的图片是众多恶搞作品中的一个。也是我最喜欢的一个&#xff0c;因为总统先生可爱&#xff0c;猫更可爱。。。。我喜欢这样的老大&#xff0c;一把年纪了还保有童真非常难得&#xff1b;作为一位总统&#xff0c;愿意把童真…

知识点:Mysql 数据库索引优化实战(4)

知识点&#xff1a;Mysql 索引原理完全手册(1) 知识点&#xff1a;Mysql 索引原理完全手册(2) 知识点&#xff1a;Mysql 索引优化实战(3) 知识点&#xff1a;Mysql 数据库索引优化实战(4) 一&#xff1a;插入订单 业务逻辑&#xff1a;插入订单数据&#xff0c;为了避免重复导单…

看漫画学电子,非常精彩!有些概念以前模糊现在真的懂了

来源&#xff1a;gadgetronicx.com&#xff0c;排版&#xff1a;晓宇微信公众号&#xff1a;芯片之家&#xff08;ID&#xff1a;chiphome-dy&#xff09;1、按键消抖&#xff0c;在机械按键断开与闭合时&#xff0c;按键的触电是有一点弹性的&#xff0c;按下去的时候不会马上…

STM32F7xx —— 串口通信

STM32F7xx —— 串口通信 目录 STM32F7xx —— 串口通信 一、串口初始化过程 二、几个重要的串口函数 三、几个重要的结构 四、基本接口设计 一、串口初始化过程 1、时钟使能&#xff1b; 2、GPIO初始化&#xff1b; 3、串口波特率设置&#xff1b; 4、串口控制&#…

一个跳楼博士生的遗书:这个世界是一沟绝望的死水

o(︶︿︶)o 唉北邮跳楼博士生给母亲堵塞遗书&#xff1a;这个世界是一沟绝望的死水 这个世界是一沟绝望的死水&#xff0c;我在这里再怎么折腾也激不起半点涟漪。所有的努力都会被既得利益集团踩在脚下&#xff0c;所有的奋斗都面临着举步维艰。冷漠的人&#xff0c;谢谢你…

jquery插件课程1 幻灯片、城市选择、日期时间选择、拖放、方向拖动插件

jquery插件课程1 幻灯片、城市选择、日期时间选择、拖放、方向拖动插件 一、总结 一句话总结&#xff1a;都是jquery插件&#xff0c;都还比较小&#xff0c;参数&#xff08;配置参数、数据&#xff09;一般都是通过json传递。 1、插件配置数据或者参数的时候用的是什么数据结…

由c语言转向c++,我们需要做什么?

点击上方蓝字添加关注在此送大家一份小礼物&#xff0c;公众号内回复linux0001即可获得一本Linux电子教程“c语言和c到底有什么不同和联系呢&#xff1f;”毫无疑问&#xff0c;c语言和c是两种不同的语言&#xff0c;但是又有着千丝万缕的联系。语法上c语言与c一脉相承&#xf…

黄聪:【强烈推荐】搜索引擎排名决定一切吗!

在点石看到一篇《搜索引擎排名决定一切么》&#xff0c;作者cqqc626。写的太赞的&#xff0c;Kyw看后都有点激动&#xff0c;希望天下所有要需要SEO服务的客户们&#xff0c;都能明白其中道理&#xff0c;明白排名不是一切。正文如下&#xff1a; 前段时间经常看到很多和自己差…

STM32F7xx —— CAN通信

STM32F7xx —— CAN通信 目录 STM32F7xx —— CAN通信 一、CAN基础 二、几个重要的CAN函数 三、几个重要的结构 四、接口设计 一、CAN基础 差分信号&#xff1a;显性电平对应逻辑0&#xff0c;CAN_H和CAN_L差为2.5V&#xff1b;隐形电平对应逻辑1&#xff0c;CAN_H和CAN_…

[leetcode] 14. 最长公共前缀

14. 最长公共前缀 超级简单。。。 class Solution { public:string longestCommonPrefix(vector<string> &strs) {if (strs.size() 0) {return "";}string common strs[0];for (int i 1; i < strs.size(); i) {common findCommon(strs[i], common);…

Cmake确实应该用到的时候再学

最近在做项目用到Cmake相关的知识&#xff0c;之前做的是BSP驱动开发&#xff0c;基本用不到Cmake&#xff0c;唯一和Cmake有交集的应该是我们移植网关项目&#xff0c;不过也只是修修改改&#xff0c;直到最近用到Cmake开发项目&#xff0c;才真正是接触了这个东西。前天加载一…

手机吞吃蛇游戏的设计与开发

为什么80%的码农都做不了架构师&#xff1f;>>> J2ME(Java 2 Micro Edition) 是近年来随着各种不同设备&#xff0c;尤其是移动通信设备的飞速发展而诞生的一项新的开发技术。它定位在消费性电子产品的应用上&#xff0c;对设备的智能化、www.21cnlunwen.com Write…

STM32F7xx —— 内部flash

STM32F7xx —— 内部flash 这个就没什么好说的了&#xff0c;直接上代码了&#xff0c;主要封装了三个函数&#xff0c;擦除&#xff0c;写flash&#xff0c;读flash。 // STM32F767IGT6: 1M flash // STM32F767ZIT6: 2M flash #define ADDR_FLASH_SECTOR_0 ((uint32_t)0x…

深入理解 Vue Computed 计算属性

Computed 计算属性是 Vue 中常用的一个功能&#xff0c;我们今天来说一下他的执行过长 拿官网简单的例子来看一下&#xff1a; <div id"example"><p>Original message: "{{ message }}"</p><p>Computed reversed message: "{…

vscode 使用 ssh 登录

// 执行 // 使用你自己的服务器IP与登录账户 export USER_AT_HOST"服务器账户名服务器IP" // PUBKEYPATH是你公钥的路径 export PUBKEYPATH"$HOME/.ssh/id_rsa.pub"ssh-copy-id -i "$PUBKEYPATH" "$USER_AT_HOST"

SNMP4J的一点缺陷

最近在使用SNMP4J的过程中发现一个缺陷&#xff0c;不知道应不应该算是个bug&#xff0c;但我想终究算是一个不完善的地方。 问题描述如下&#xff1a; 在通过SNMP4J去获取某些交换机上的MAC地址转发表(dot1dTpFdbTable, OID为1.3.6.1.2.1.17.4.3&#xff09;时&#xff0c;发现…