123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405 |
- /*
- *********************************************************************************************************
- *
- * 模块名称 : 独立按键驱动模块
- * 文件名称 : bsp_key.c
- * 版 本 : V1.0
- * 说 明 : 扫描独立按键,具有软件滤波机制,具有按键FIFO。可以检测如下事件:
- * (1) 按键按下
- * (2) 按键弹起
- * (3) 长按键
- * (4) 长按时自动连发
- *
- * 修改记录 :
- * 版本号 日期 作者 说明
- * V1.0 2013-02-01 armfly 正式发布
- * V1.1 2013-06-29 armfly 增加1个读指针,用于bsp_Idle() 函数读取系统控制组合键(截屏)
- * 增加 K1 K2 组合键 和 K2 K3 组合键,用于系统控制
- *
- * Copyright (C), 2013-2014, 安富莱电子 www.armfly.com
- *
- *********************************************************************************************************
- */
- /*
- 该程序适用于安富莱STM32-X3、STM32-V5开发板
- 如果用于其它硬件,请修改GPIO定义和 IsKeyDown1 - IsKeyDown8 函数
- 如果用户的按键个数小于8个,你可以将多余的按键全部定义为和第1个按键一样,并不影响程序功能
- #define KEY_COUNT 8 这个在 bsp_key.h 文件中定义
- */
- #include "key.h"
- static KEY_T s_tBtn[KEY_COUNT];
- static KEY_FIFO_T s_tKey; /* 按键FIFO变量,结构体 */
- static void bsp_DetectKey(uint8_t i);
- /*
- *********************************************************************************************************
- * 函 数 名: IsKeyDownX
- * 功能说明: 判断按键是否按下
- * 形 参: 无
- * 返 回 值: 返回值1 表示按下,0表示未按下
- *********************************************************************************************************
- */
- static uint8_t IsKeyDown1(void)
- {
- if ((GPIO_PORT_K1->IDR & GPIO_PIN_K1) == 0)
- return 1;
- else
- return 0;
- }
- static uint8_t IsKeyDown2(void)
- {
- if ((GPIO_PORT_K2->IDR & GPIO_PIN_K2) == 0)
- return 1;
- else
- return 0;
- }
- static uint8_t IsKeyDown3(void)
- {
- if ((GPIO_PORT_K3->IDR & GPIO_PIN_K3) == 0)
- return 1;
- else
- return 0;
- }
- static uint8_t IsKeyDown4(void)
- {
- if ((GPIO_PORT_K4->IDR & GPIO_PIN_K4) == 0)
- return 1;
- else
- return 0;
- }
- static uint8_t IsKeyDown5(void)
- {
- if ((GPIO_PORT_K5->IDR & GPIO_PIN_K5) == 0)
- return 1;
- else
- return 0;
- }
- static uint8_t IsKeyDown6(void)
- {
- if ((GPIO_PORT_K6->IDR & GPIO_PIN_K6) == 0)
- return 1;
- else
- return 0;
- }
- static uint8_t IsKeyDown7(void)
- {
- if ((GPIO_PORT_K7->IDR & GPIO_PIN_K7) == 0)
- return 1;
- else
- return 0;
- }
- static uint8_t IsKeyDown8(void)
- {
- if ((GPIO_PORT_K8->IDR & GPIO_PIN_K8) == 0)
- return 1;
- else
- return 0;
- }
- static uint8_t IsKeyDown9(void)
- {
- if (IsKeyDown1() && IsKeyDown2())
- return 1;
- else
- return 0;
- }
- static uint8_t IsKeyDown10(void)
- {
- if (IsKeyDown1() && IsKeyDown2())
- return 1;
- else
- return 0;
- }
- /*
- *********************************************************************************************************
- * 函 数 名: key_put
- * 功能说明: 将1个键值压入按键FIFO缓冲区。可用于模拟一个按键。
- * 形 参: _KeyCode : 按键代码
- * 返 回 值: 无
- *********************************************************************************************************
- */
- void key_put(uint8_t _KeyCode)
- {
- s_tKey.Buf[s_tKey.Write] = _KeyCode;
- if (++s_tKey.Write >= KEY_FIFO_SIZE)
- {
- s_tKey.Write = 0;
- }
- }
- /*
- *********************************************************************************************************
- * 函 数 名: key_get
- * 功能说明: 从按键FIFO缓冲区读取一个键值。
- * 形 参: 无
- * 返 回 值: 按键代码
- *********************************************************************************************************
- */
- uint8_t key_get(void)
- {
- uint8_t ret;
- if (s_tKey.Read == s_tKey.Write)
- {
- return KEY_NONE;
- }
- else
- {
- ret = s_tKey.Buf[s_tKey.Read];
- if (++s_tKey.Read >= KEY_FIFO_SIZE)
- {
- s_tKey.Read = 0;
- }
- return ret;
- }
- }
- /*
- *********************************************************************************************************
- * 函 数 名: key_get_fifo
- * 功能说明: 从按键FIFO缓冲区读取一个键值。独立的读指针。
- * 形 参: 无
- * 返 回 值: 按键代码
- *********************************************************************************************************
- */
- uint8_t key_get_fifo(void)
- {
- uint8_t ret;
- if (s_tKey.Read2 == s_tKey.Write)
- {
- return KEY_NONE;
- }
- else
- {
- ret = s_tKey.Buf[s_tKey.Read2];
- if (++s_tKey.Read2 >= KEY_FIFO_SIZE)
- {
- s_tKey.Read2 = 0;
- }
- return ret;
- }
- }
- /*
- *********************************************************************************************************
- * 函 数 名: key_state
- * 功能说明: 读取按键的状态
- * 形 参: _ucKeyID : 按键ID,从0开始
- * 返 回 值: 1 表示按下, 0 表示未按下
- *********************************************************************************************************
- */
- uint8_t key_state(KEY_ID_E _ucKeyID)
- {
- return s_tBtn[_ucKeyID].State;
- }
- /*
- *********************************************************************************************************
- * 函 数 名: key_state
- * 功能说明: 设置按键参数
- * 形 参:_ucKeyID : 按键ID,从0开始
- * _LongTime : 长按事件时间
- * _RepeatSpeed : 连发速度
- * 返 回 值: 无
- *********************************************************************************************************
- */
- void key_set(uint8_t _ucKeyID, uint16_t _LongTime, uint8_t _RepeatSpeed)
- {
- s_tBtn[_ucKeyID].LongTime = _LongTime; /* 长按时间 0 表示不检测长按键事件 */
- s_tBtn[_ucKeyID].RepeatSpeed = _RepeatSpeed; /* 按键连发的速度,0表示不支持连发 */
- s_tBtn[_ucKeyID].RepeatCount = 0; /* 连发计数器 */
- }
- /*
- *********************************************************************************************************
- * 函 数 名: key_clear_fifo
- * 功能说明: 清空按键FIFO缓冲区
- * 形 参:无
- * 返 回 值: 按键代码
- *********************************************************************************************************
- */
- void key_clear_fifo(void)
- {
- s_tKey.Read = s_tKey.Write;
- }
- /*
- *********************************************************************************************************
- * 函 数 名: key_init
- * 功能说明: 初始化按键变量
- * 形 参: 无
- * 返 回 值: 无
- *********************************************************************************************************
- */
- void key_init(void)
- {
- uint8_t i;
- /* 对按键FIFO读写指针清零 */
- s_tKey.Read = 0;
- s_tKey.Write = 0;
- s_tKey.Read2 = 0;
- /* 给每个按键结构体成员变量赋一组缺省值 */
- for (i = 0; i < KEY_COUNT; i++)
- {
- s_tBtn[i].LongTime = KEY_LONG_TIME; /* 长按时间 0 表示不检测长按键事件 */
- s_tBtn[i].Count = KEY_FILTER_TIME / 2; /* 计数器设置为滤波时间的一半 */
- s_tBtn[i].State = 0; /* 按键缺省状态,0为未按下 */
- // s_tBtn[i].KeyCodeDown = 3 * i + 1; /* 按键按下的键值代码 */
- // s_tBtn[i].KeyCodeUp = 3 * i + 2; /* 按键弹起的键值代码 */
- // s_tBtn[i].KeyCodeLong = 3 * i + 3; /* 按键被持续按下的键值代码 */
- s_tBtn[i].RepeatSpeed = 0; /* 按键连发的速度,0表示不支持连发 */
- s_tBtn[i].RepeatCount = 0; /* 连发计数器 */
- }
- /* 如果需要单独更改某个按键的参数,可以在此单独重新赋值 */
- /* 比如,我们希望按键1按下超过1秒后,自动重发相同键值 */
- s_tBtn[KID_JOY_U].LongTime = 100;
- s_tBtn[KID_JOY_U].RepeatSpeed = 5; /* 每隔50ms自动发送键值 */
- s_tBtn[KID_JOY_D].LongTime = 100;
- s_tBtn[KID_JOY_D].RepeatSpeed = 5; /* 每隔50ms自动发送键值 */
- s_tBtn[KID_JOY_L].LongTime = 100;
- s_tBtn[KID_JOY_L].RepeatSpeed = 5; /* 每隔50ms自动发送键值 */
- s_tBtn[KID_JOY_R].LongTime = 100;
- s_tBtn[KID_JOY_R].RepeatSpeed = 5; /* 每隔50ms自动发送键值 */
- /* 判断按键按下的函数 */
- s_tBtn[0].IsKeyDownFunc = IsKeyDown1;
- s_tBtn[1].IsKeyDownFunc = IsKeyDown2;
- s_tBtn[2].IsKeyDownFunc = IsKeyDown3;
- s_tBtn[3].IsKeyDownFunc = IsKeyDown4;
- s_tBtn[4].IsKeyDownFunc = IsKeyDown5;
- s_tBtn[5].IsKeyDownFunc = IsKeyDown6;
- s_tBtn[6].IsKeyDownFunc = IsKeyDown7;
- s_tBtn[7].IsKeyDownFunc = IsKeyDown8;
- /* 组合键 */
- s_tBtn[8].IsKeyDownFunc = IsKeyDown9;
- s_tBtn[9].IsKeyDownFunc = IsKeyDown10;
- }
- /*
- *********************************************************************************************************
- * 函 数 名: bsp_DetectKey
- * 功能说明: 检测一个按键。非阻塞状态,必须被周期性的调用。
- * 形 参: 按键结构变量指针
- * 返 回 值: 无
- *********************************************************************************************************
- */
- static void bsp_DetectKey(uint8_t i)
- {
- KEY_T *pBtn;
- /*
- 如果没有初始化按键函数,则报错
- if (s_tBtn[i].IsKeyDownFunc == 0)
- {
- printf("Fault : DetectButton(), s_tBtn[i].IsKeyDownFunc undefine");
- }
- */
- pBtn = &s_tBtn[i];
- if (pBtn->IsKeyDownFunc())
- {
- if (pBtn->Count < KEY_FILTER_TIME)
- {
- pBtn->Count = KEY_FILTER_TIME;
- }
- else if (pBtn->Count < 2 * KEY_FILTER_TIME)
- {
- pBtn->Count++;
- }
- else
- {
- if (pBtn->State == 0)
- {
- pBtn->State = 1;
- /* 发送按钮按下的消息 */
- key_put((uint8_t)(3 * i + 1));
- }
- if (pBtn->LongTime > 0)
- {
- if (pBtn->LongCount < pBtn->LongTime)
- {
- /* 发送按钮持续按下的消息 */
- if (++pBtn->LongCount == pBtn->LongTime)
- {
- /* 键值放入按键FIFO */
- key_put((uint8_t)(3 * i + 3));
- }
- }
- else
- {
- if (pBtn->RepeatSpeed > 0)
- {
- if (++pBtn->RepeatCount >= pBtn->RepeatSpeed)
- {
- pBtn->RepeatCount = 0;
- /* 常按键后,每隔10ms发送1个按键 */
- key_put((uint8_t)(3 * i + 1));
- }
- }
- }
- }
- }
- }
- else
- {
- if (pBtn->Count > KEY_FILTER_TIME)
- {
- pBtn->Count = KEY_FILTER_TIME;
- }
- else if (pBtn->Count != 0)
- {
- pBtn->Count--;
- }
- else
- {
- if (pBtn->State == 1)
- {
- pBtn->State = 0;
- /* 发送按钮弹起的消息 */
- key_put((uint8_t)(3 * i + 2));
- }
- }
- pBtn->LongCount = 0;
- pBtn->RepeatCount = 0;
- }
- }
- /*
- *********************************************************************************************************
- * 函 数 名: key_scan
- * 功能说明: 扫描所有按键。非阻塞,被systick中断周期性的调用
- * 形 参: 无
- * 返 回 值: 无
- *********************************************************************************************************
- */
- void key_scan(void)
- {
- uint8_t i;
- for (i = 0; i < KEY_COUNT; i++)
- {
- bsp_DetectKey(i);
- }
- }
|