硬汉嵌入式论坛

 找回密码
 立即注册
查看: 6373|回复: 6
收起左侧

【STM32F429官方探索板】实验二:按键FIFO(MDK5.0和IAR6.7配套V5开发板教程,最新

[复制链接]

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106761
QQ
发表于 2013-12-5 20:55:19 | 显示全部楼层 |阅读模式
    说明:借推出armfly-v5开发板教程之际推出几期官方STM32F429探索套件的例子,
主要是做一下板载的外设,以及几期RTOS和emWin。实验教程可参考我们armfly-v5开
发板的教程:http://www.armbbs.cn/forum.php?mod=viewthread&tid=1285
软件平台:
MDK V4.73 OR V5.00
IAR6.7
硬件平台:
STM32F429官网探索套件
例程说明:
LED部分原理图
1.png

KEY部分原理图(电容按键滤波?
2.png

例程整体功能描述:
1. 创建一个1ms的滴答定时器中断以实现软件定时器
2. 主程序创建一个100ms的自动重装软件定时器,LED1每100ms翻转一次。
3. 创建一个按键的FIFO
4. K1按键按下点亮LED2,弹起熄灭LED2
5. 本身这个按键FIFO是支持,按下,弹起,长按和组合功能的,但是在测试

    长按的时候,有点问题,不知道是不是与按键外面的滤波电容有关,待查
例程下载
第二期:按键FIFO.zip (5 MB, 下载次数: 616)
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106761
QQ
 楼主| 发表于 2013-12-20 21:53:25 | 显示全部楼层
顶一下
回复

使用道具 举报

6

主题

390

回帖

408

积分

高级会员

积分
408
发表于 2015-6-2 15:46:32 | 显示全部楼层
[s:142]  [s:142]  [s:142]  [s:142]
回复

使用道具 举报

0

主题

7

回帖

0

积分

新手上路

积分
0
发表于 2016-5-10 17:12:59 | 显示全部楼层
程序里没有处理shift键(组合键的基础键),加入几句代码应该体验更好些:
无标题.png

组合键的基础键(shift键)应该具有几个特点:
1、作为单键使用时必须是释放有效,不支持长按有效和连发功能
2、按下(组合键):生效前需要清一下键值。也就是被确认为是组合键,那么单键功能就失效了。
3、释放(组合键):无论是先释放shift键还是另一个键,只要检测到shift释放就清一次键值。为了防止shift的单键功能干扰
4、暂时想到这些
回复

使用道具 举报

0

主题

7

回帖

0

积分

新手上路

积分
0
发表于 2016-5-13 09:15:31 | 显示全部楼层
按键FIFO带来一个问题:按键具有记录功能,这个要两方面来讨论。
1、优点:可以实现一个按键多种方式同时触发;可以做到连锁响应(不丢键值,例如当应用程序和按键部分异步时)。
2、缺点:如果两个个关联的界面使用了相反的按键触发方式,那“一个按键多种方式同时触发”将是一个麻烦,因为可能下一个界面会使用上一个界面的键值;对于这个不丢键有时也未必是个好事,有时不需要按键具有记录功能,所以我加了定时清键值控制,防止应用程序和按键程序(优先级高一些)异步造成的连发效应。
回复

使用道具 举报

0

主题

7

回帖

0

积分

新手上路

积分
0
发表于 2016-5-13 09:26:30 | 显示全部楼层
  1. #include "string.h"
  2. #include "stm32f2xx.h"
  3. #include "FreeRTOS.h"
  4. #include "task.h"
  5. #include "bsp_key.h"
  6. static KEY_T s_tBtn[KEY_COUNT];
  7. static KEY_FIFO_T s_tKey;        /* 按键FIFO变量,结构体 */
  8. static void bsp_InitKeyVar(void);
  9. static void bsp_InitKeyHard(void);
  10. static void bsp_DetectKey(uint8_t i);
  11. /*
  12. *********************************************************************************************************
  13. *    函 数 名: IsKeyDownX
  14. *    功能说明: 判断按键是否按下
  15. *    形    参: 无
  16. *    返 回 值: 返回值1 表示按下,0表示未按下
  17. *********************************************************************************************************
  18. */
  19. static uint8_t IsKeyDown1(void)
  20. {
  21.     if ((GPIO_PORT_K1->IDR & GPIO_PIN_K1) == 0 &&
  22.         (GPIO_PORT_K2->IDR & GPIO_PIN_K2) != 0 &&
  23.         (GPIO_PORT_K3->IDR & GPIO_PIN_K3) != 0 &&
  24.         (GPIO_PORT_K4->IDR & GPIO_PIN_K4) != 0 &&
  25.         (GPIO_PORT_K5->IDR & GPIO_PIN_K5) != 0 &&
  26.         (GPIO_PORT_K6->IDR & GPIO_PIN_K6) != 0)
  27.     {
  28.         return 1;
  29.     }
  30.     else
  31.     {
  32.         return 0;
  33.     }
  34. }
  35. static uint8_t IsKeyDown2(void)
  36. {
  37.     if ((GPIO_PORT_K1->IDR & GPIO_PIN_K1) != 0 &&
  38.         (GPIO_PORT_K2->IDR & GPIO_PIN_K2) == 0 &&
  39.         (GPIO_PORT_K3->IDR & GPIO_PIN_K3) != 0 &&
  40.         (GPIO_PORT_K4->IDR & GPIO_PIN_K4) != 0 &&
  41.         (GPIO_PORT_K5->IDR & GPIO_PIN_K5) != 0 &&
  42.         (GPIO_PORT_K6->IDR & GPIO_PIN_K6) != 0)
  43.     {
  44.         return 1;
  45.     }
  46.     else
  47.     {
  48.         return 0;
  49.     }
  50. }
  51. static uint8_t IsKeyDown3(void)
  52. {
  53.     if ((GPIO_PORT_K1->IDR & GPIO_PIN_K1) != 0 &&
  54.         (GPIO_PORT_K2->IDR & GPIO_PIN_K2) != 0 &&
  55.         (GPIO_PORT_K3->IDR & GPIO_PIN_K3) == 0 &&
  56.         (GPIO_PORT_K4->IDR & GPIO_PIN_K4) != 0 &&
  57.         (GPIO_PORT_K5->IDR & GPIO_PIN_K5) != 0 &&
  58.         (GPIO_PORT_K6->IDR & GPIO_PIN_K6) != 0)
  59.     {
  60.         return 1;
  61.     }
  62.     else
  63.     {
  64.         return 0;
  65.     }
  66. }
  67. static uint8_t IsKeyDown4(void)
  68. {
  69.     if ((GPIO_PORT_K1->IDR & GPIO_PIN_K1) != 0 &&
  70.         (GPIO_PORT_K2->IDR & GPIO_PIN_K2) != 0 &&
  71.         (GPIO_PORT_K3->IDR & GPIO_PIN_K3) != 0 &&
  72.         (GPIO_PORT_K4->IDR & GPIO_PIN_K4) == 0 &&
  73.         (GPIO_PORT_K5->IDR & GPIO_PIN_K5) != 0 &&
  74.         (GPIO_PORT_K6->IDR & GPIO_PIN_K6) != 0)
  75.     {
  76.         return 1;
  77.     }
  78.     else
  79.     {
  80.         return 0;
  81.     }
  82. }
  83. static uint8_t IsKeyDown5(void)
  84. {
  85.     if ((GPIO_PORT_K1->IDR & GPIO_PIN_K1) != 0 &&
  86.         (GPIO_PORT_K2->IDR & GPIO_PIN_K2) != 0 &&
  87.         (GPIO_PORT_K3->IDR & GPIO_PIN_K3) != 0 &&
  88.         (GPIO_PORT_K4->IDR & GPIO_PIN_K4) != 0 &&
  89.         (GPIO_PORT_K5->IDR & GPIO_PIN_K5) == 0 &&
  90.         (GPIO_PORT_K6->IDR & GPIO_PIN_K6) != 0)
  91.     {
  92.         return 1;
  93.     }
  94.     else
  95.     {
  96.         return 0;
  97.     }
  98. }
  99. static uint8_t IsKeyDown6(void)
  100. {
  101.     if ((GPIO_PORT_K1->IDR & GPIO_PIN_K1) != 0 &&
  102.         (GPIO_PORT_K2->IDR & GPIO_PIN_K2) != 0 &&
  103.         (GPIO_PORT_K3->IDR & GPIO_PIN_K3) != 0 &&
  104.         (GPIO_PORT_K4->IDR & GPIO_PIN_K4) != 0 &&
  105.         (GPIO_PORT_K5->IDR & GPIO_PIN_K5) != 0 &&
  106.         (GPIO_PORT_K6->IDR & GPIO_PIN_K6) == 0)
  107.     {
  108.         return 1;
  109.     }
  110.     else
  111.     {
  112.         return 0;
  113.     }
  114. }
  115. static uint8_t IsKeyDown7(void)    /* K1 K6组合键 */
  116. {
  117.     if ((GPIO_PORT_K1->IDR & GPIO_PIN_K1) == 0 &&
  118.         (GPIO_PORT_K2->IDR & GPIO_PIN_K2) != 0 &&
  119.         (GPIO_PORT_K3->IDR & GPIO_PIN_K3) != 0 &&
  120.         (GPIO_PORT_K4->IDR & GPIO_PIN_K4) != 0 &&
  121.         (GPIO_PORT_K5->IDR & GPIO_PIN_K5) != 0 &&
  122.         (GPIO_PORT_K6->IDR & GPIO_PIN_K6) == 0)
  123.     {
  124.         return 1;
  125.     }
  126.     else
  127.     {
  128.         return 0;
  129.     }
  130. }
  131. static uint8_t IsKeyDown8(void)    /* K2 K6组合键 */
  132. {
  133.     if ((GPIO_PORT_K1->IDR & GPIO_PIN_K1) != 0 &&
  134.         (GPIO_PORT_K2->IDR & GPIO_PIN_K2) == 0 &&
  135.         (GPIO_PORT_K3->IDR & GPIO_PIN_K3) != 0 &&
  136.         (GPIO_PORT_K4->IDR & GPIO_PIN_K4) != 0 &&
  137.         (GPIO_PORT_K5->IDR & GPIO_PIN_K5) != 0 &&
  138.         (GPIO_PORT_K6->IDR & GPIO_PIN_K6) == 0)
  139.     {
  140.         return 1;
  141.     }
  142.     else
  143.     {
  144.         return 0;
  145.     }
  146. }
  147. static uint8_t IsKeyDown9(void)    /* K3 K6组合键 */
  148. {
  149.     if ((GPIO_PORT_K1->IDR & GPIO_PIN_K1) != 0 &&
  150.         (GPIO_PORT_K2->IDR & GPIO_PIN_K2) != 0 &&
  151.         (GPIO_PORT_K3->IDR & GPIO_PIN_K3) == 0 &&
  152.         (GPIO_PORT_K4->IDR & GPIO_PIN_K4) != 0 &&
  153.         (GPIO_PORT_K5->IDR & GPIO_PIN_K5) != 0 &&
  154.         (GPIO_PORT_K6->IDR & GPIO_PIN_K6) == 0)
  155.     {
  156.         return 1;
  157.     }
  158.     else
  159.     {
  160.         return 0;
  161.     }
  162. }
  163. static uint8_t IsKeyDown10(void)    /* K4 K6组合键 */
  164. {
  165.     if ((GPIO_PORT_K1->IDR & GPIO_PIN_K1) != 0 &&
  166.         (GPIO_PORT_K2->IDR & GPIO_PIN_K2) != 0 &&
  167.         (GPIO_PORT_K3->IDR & GPIO_PIN_K3) != 0 &&
  168.         (GPIO_PORT_K4->IDR & GPIO_PIN_K4) == 0 &&
  169.         (GPIO_PORT_K5->IDR & GPIO_PIN_K5) != 0 &&
  170.         (GPIO_PORT_K6->IDR & GPIO_PIN_K6) == 0)
  171.     {
  172.         return 1;
  173.     }
  174.     else
  175.     {
  176.         return 0;
  177.     }
  178. }
  179. /*
  180. *********************************************************************************************************
  181. *    函 数 名: bsp_InitKey
  182. *    功能说明: 初始化按键. 该函数被 bsp_Init() 调用。
  183. *    形    参:  无
  184. *    返 回 值: 无
  185. *********************************************************************************************************
  186. */
  187. void bsp_InitKey(void)
  188. {
  189.     bsp_InitKeyVar();        /* 初始化按键变量 */
  190.     bsp_InitKeyHard();        /* 初始化按键硬件 */
  191. }
  192. /*
  193. *********************************************************************************************************
  194. *    函 数 名: bsp_PutKey
  195. *    功能说明: 将1个键值压入按键FIFO缓冲区。可用于模拟一个按键。
  196. *    形    参:  _KeyCode : 按键代码
  197. *    返 回 值: 无
  198. *********************************************************************************************************
  199. */
  200. void bsp_PutKey(uint8_t _KeyCode)
  201. {
  202.     s_tKey.Buf[s_tKey.Write] = _KeyCode;
  203.     if (++s_tKey.Write  >= KEY_FIFO_SIZE)
  204.     {
  205.         s_tKey.Write = 0;
  206.     }
  207. }
  208. /*
  209. *********************************************************************************************************
  210. *    函 数 名: bsp_GetKey
  211. *    功能说明: 从按键FIFO缓冲区读取一个键值。
  212. *    形    参:  无
  213. *    返 回 值: 按键代码
  214. *********************************************************************************************************
  215. */
  216. uint8_t bsp_GetKey(void)
  217. {
  218.     uint8_t ret;
  219.    
  220.     #if FREERTOS_ENABLED     //如FREERTOS_ENABLED定义了,说明使用FreeRTOS了.
  221.     vTaskDelay(5/portTICK_RATE_MS);//GUI靠按键阻塞的
  222.     #endif
  223.    
  224.     if (s_tKey.Read == s_tKey.Write)
  225.     {
  226.         return KEY_NONE;
  227.     }
  228.     else
  229.     {
  230.         ret = s_tKey.Buf[s_tKey.Read];
  231.         if (++s_tKey.Read >= KEY_FIFO_SIZE)
  232.         {
  233.             s_tKey.Read = 0;
  234.         }
  235.         return ret;
  236.     }
  237. }
  238. /*
  239. *********************************************************************************************************
  240. *    函 数 名: bsp_GetKeyState
  241. *    功能说明: 读取按键的状态
  242. *    形    参:  _ucKeyID : 按键ID,从0开始
  243. *    返 回 值: 1 表示按下, 0 表示未按下
  244. *********************************************************************************************************
  245. */
  246. uint8_t bsp_GetKeyState(KEY_ID_E _ucKeyID)
  247. {
  248.     return s_tBtn[_ucKeyID].State;
  249. }
  250. /*
  251. *********************************************************************************************************
  252. *    函 数 名: bsp_SetKeyParam
  253. *    功能说明: 设置按键参数
  254. *    形    参:_ucKeyID : 按键ID,从0开始
  255. *            _LongTime : 长按事件时间
  256. *             _RepeatSpeed : 连发速度
  257. *    返 回 值: 无
  258. *********************************************************************************************************
  259. */
  260. void bsp_SetKeyParam(uint8_t _ucKeyID, uint16_t _LongTime, uint8_t  _RepeatSpeed)
  261. {
  262.     s_tBtn[_ucKeyID].LongTime    = _LongTime;            /* 长按时间 0 表示不检测长按键事件 */
  263.     s_tBtn[_ucKeyID].RepeatSpeed = _RepeatSpeed;        /* 按键连发的速度,0表示不支持连发 */
  264.     s_tBtn[_ucKeyID].RepeatCount = 0;                    /* 连发计数器 */
  265. }
  266. /*
  267. *********************************************************************************************************
  268. *    函 数 名: bsp_ClearKey
  269. *    功能说明: 清空按键FIFO缓冲区
  270. *    形    参:无
  271. *    返 回 值: 按键代码
  272. *********************************************************************************************************
  273. */
  274. void bsp_ClearKey(void)
  275. {
  276.     s_tKey.Read = s_tKey.Write;
  277. }
  278. /*
  279. *********************************************************************************************************
  280. *    函 数 名: bsp_InitKeyHard
  281. *    功能说明: 配置按键对应的GPIO
  282. *    形    参:  无
  283. *    返 回 值: 无
  284. *********************************************************************************************************
  285. */
  286. static void bsp_InitKeyHard(void)
  287. {
  288.     GPIO_InitTypeDef GPIO_InitStructure;
  289.     RCC_APB2PeriphClockCmd(RCC_ALL_KEY, ENABLE);
  290.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;//输入输出设置,输入/输出/复用/模拟
  291.     GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//输入模式,上拉
  292.    
  293.     GPIO_InitStructure.GPIO_Pin = GPIO_PIN_K1;
  294.     GPIO_Init(GPIO_PORT_K1, &GPIO_InitStructure);
  295.     GPIO_InitStructure.GPIO_Pin = GPIO_PIN_K2;
  296.     GPIO_Init(GPIO_PORT_K2, &GPIO_InitStructure);
  297.     GPIO_InitStructure.GPIO_Pin = GPIO_PIN_K3;
  298.     GPIO_Init(GPIO_PORT_K3, &GPIO_InitStructure);
  299.    
  300.     GPIO_InitStructure.GPIO_Pin = GPIO_PIN_K4;
  301.     GPIO_Init(GPIO_PORT_K4, &GPIO_InitStructure);
  302.     GPIO_InitStructure.GPIO_Pin = GPIO_PIN_K5;
  303.     GPIO_Init(GPIO_PORT_K5, &GPIO_InitStructure);
  304.     GPIO_InitStructure.GPIO_Pin = GPIO_PIN_K6;
  305.     GPIO_Init(GPIO_PORT_K6, &GPIO_InitStructure);
  306. }
  307. /*
  308. *********************************************************************************************************
  309. *    函 数 名: bsp_InitKeyVar
  310. *    功能说明: 初始化按键变量
  311. *    形    参:  无
  312. *    返 回 值: 无
  313. *********************************************************************************************************
  314. */
  315. static void bsp_InitKeyVar(void)
  316. {
  317.     uint8_t i;
  318.     /* 对按键FIFO读写指针清零 */
  319.     s_tKey.Read  = 0;
  320.     s_tKey.Write = 0;
  321.     s_tKey.Read2 = 0;
  322.     /* 给每个按键结构体成员变量赋一组缺省值 */
  323.     for (i = 0; i < KEY_COUNT; i++)
  324.     {
  325.         s_tBtn[i].LongTime = 0;                        /* 长按时间 0 表示不检测长按键事件 */
  326.         s_tBtn[i].Count    = KEY_FILTER_TIME / 2;    /* 计数器设置为滤波时间的一半 */
  327.         s_tBtn[i].State    = 0;                        /* 按键缺省状态,0为未按下 */
  328.         s_tBtn[i].KeyCodeDown = 3 * i + 1;            /* 按键按下的键值代码 */
  329.         s_tBtn[i].KeyCodeUp   = 3 * i + 2;            /* 按键弹起的键值代码 */
  330.         s_tBtn[i].KeyCodeLong = 3 * i + 3;            /* 按键被持续按下的键值代码 */
  331.         s_tBtn[i].RepeatSpeed = 0;                    /* 按键连发的速度,0表示不支持连发 */
  332.         s_tBtn[i].RepeatCount = 0;                    /* 连发计数器 */
  333.         s_tBtn[5].attribute   = 0;                  //按键属性,通用按键
  334.     }
  335.     /* 如果需要单独更改某个按键的参数,可以在此单独重新赋值 */
  336.     //长按连发配置
  337.     s_tBtn[KID_K1].LongTime = KEY_LONG_TIME;
  338.     s_tBtn[KID_K1].RepeatSpeed = 5;    /* 每隔50ms自动发送键值 */
  339.     s_tBtn[KID_K2].LongTime = KEY_LONG_TIME;
  340.     s_tBtn[KID_K2].RepeatSpeed = 5;    /* 每隔50ms自动发送键值 */
  341.     s_tBtn[KID_K3].LongTime = KEY_LONG_TIME;
  342.     s_tBtn[KID_K3].RepeatSpeed = 5;    /* 每隔50ms自动发送键值 */
  343.     s_tBtn[KID_K4].LongTime = KEY_LONG_TIME;
  344.     s_tBtn[KID_K4].RepeatSpeed = 5;    /* 每隔50ms自动发送键值 */
  345.    
  346.     s_tBtn[KID_K9].LongTime = KEY_LONG_TIME;
  347.     s_tBtn[KID_K9].RepeatSpeed = 5;    /* 每隔50ms自动发送键值 */
  348.     s_tBtn[KID_K10].LongTime = KEY_LONG_TIME;
  349.     s_tBtn[KID_K10].RepeatSpeed = 5;/* 每隔50ms自动发送键值 */     
  350.     //按键属性
  351.     s_tBtn[KID_K6].attribute  = 2;//shift键
  352.     s_tBtn[KID_K7].attribute  = 1;//组合键
  353.     s_tBtn[KID_K8].attribute  = 1;//组合键
  354.     s_tBtn[KID_K9].attribute  = 1;//组合键
  355.     s_tBtn[KID_K10].attribute = 1;//组合键
  356.    
  357.     /* 判断按键按下的函数 */
  358.     s_tBtn[KID_K1].IsKeyDownFunc  = IsKeyDown1;
  359.     s_tBtn[KID_K2].IsKeyDownFunc  = IsKeyDown2;
  360.     s_tBtn[KID_K3].IsKeyDownFunc  = IsKeyDown3;
  361.     s_tBtn[KID_K4].IsKeyDownFunc  = IsKeyDown4;
  362.     s_tBtn[KID_K5].IsKeyDownFunc  = IsKeyDown5;
  363.     s_tBtn[KID_K6].IsKeyDownFunc  = IsKeyDown6;
  364.     s_tBtn[KID_K7].IsKeyDownFunc  = IsKeyDown7;
  365.     s_tBtn[KID_K8].IsKeyDownFunc  = IsKeyDown8;
  366.     s_tBtn[KID_K9].IsKeyDownFunc  = IsKeyDown9;
  367.     s_tBtn[KID_K10].IsKeyDownFunc = IsKeyDown10;
  368. }
  369. /*
  370. *********************************************************************************************************
  371. *    函 数 名: bsp_DetectKey
  372. *    功能说明: 检测一个按键。非阻塞状态,必须被周期性的调用。
  373. *    形    参:  按键结构变量指针
  374. *    返 回 值: 无
  375. *********************************************************************************************************
  376. */
  377. static void bsp_DetectKey(uint8_t i)
  378. {
  379.     static u8 flag = 0;//组合按键触发标识
  380.     KEY_T *pBtn = &s_tBtn[i];
  381.     if (pBtn->IsKeyDownFunc()) //读按键状态,按下
  382.     {
  383.         if (pBtn->Count < KEY_FILTER_TIME)
  384.         {
  385.             pBtn->Count = KEY_FILTER_TIME;
  386.         }
  387.         else if(pBtn->Count < 2 * KEY_FILTER_TIME) //滤波
  388.         {
  389.             pBtn->Count++;
  390.         }
  391.         else
  392.         {
  393.             if (pBtn->State == 0) //保证只触发一次
  394.             {
  395.                 pBtn->State = 1;
  396.                 if(pBtn->attribute == 1) //组合按键,需要消除独立按键的干扰
  397.                 {
  398.                     flag = 1;
  399.                     bsp_ClearKey();//发送组合按键前,要清一次键值
  400.                 }
  401.                 /* 发送按钮按下的消息 */
  402.                 bsp_PutKey(s_tBtn[i].KeyCodeDown);
  403.             }
  404.             if (pBtn->LongTime > 0) //长按处理代码
  405.             {
  406.                 if (pBtn->LongCount < pBtn->LongTime)
  407.                 {
  408.                     /* 发送按钮持续按下的消息 */
  409.                     if (++pBtn->LongCount == pBtn->LongTime)
  410.                     {
  411.                         /* 键值放入按键FIFO */
  412.                         bsp_PutKey(s_tBtn[i].KeyCodeLong);//第一个长按键发送
  413.                     }
  414.                 }
  415.                 else
  416.                 {
  417.                     if (pBtn->RepeatSpeed > 0) //连续按键周期
  418.                     {
  419.                         if (++pBtn->RepeatCount >= pBtn->RepeatSpeed)
  420.                         {
  421.                             pBtn->RepeatCount = 0;
  422.                             /* 常按键后,每隔10ms发送1个按键 */
  423.                             bsp_PutKey(s_tBtn[i].KeyCodeDown);//长安键值周期发送
  424.                         }
  425.                     }
  426.                 }
  427.             }
  428.         }
  429.     }
  430.     else //弹起
  431.     {
  432.         if(pBtn->Count > KEY_FILTER_TIME)
  433.         {
  434.             pBtn->Count = KEY_FILTER_TIME;
  435.         }
  436.         else if(pBtn->Count != 0)
  437.         {
  438.             pBtn->Count--;
  439.         }
  440.         else
  441.         {
  442.             if (pBtn->State == 1)
  443.             {
  444.                 pBtn->State = 0;
  445.                
  446.                 /* 发送按钮弹起的消息 */
  447.                 bsp_PutKey(s_tBtn[i].KeyCodeUp);
  448.                
  449.                 if((flag == 1) && //触发了组合键
  450.                    ((pBtn->attribute == 2) || ((bsp_GetKeyState(KID_K6) == 0) && (pBtn->attribute == 1)))) //shift键释放或者组合键同时释放清键值
  451.                 {
  452.                     flag = 0;
  453.                     bsp_ClearKey();//要清一次键值
  454.                 }               
  455.             }
  456.         }
  457.         pBtn->LongCount = 0;
  458.         pBtn->RepeatCount = 0;
  459.     }
  460. }
  461. /*
  462. *********************************************************************************************************
  463. *    函 数 名: bsp_KeyScan
  464. *    功能说明: 扫描所有按键。非阻塞,被systick中断周期性的调用
  465. *    形    参:  无
  466. *    返 回 值: 无
  467. *********************************************************************************************************
  468. */
  469. void bsp_KeyScan(void)
  470. {
  471.     #if KEY_CLEAR //定时请键
  472.     static uint32_t cont = 0;//计数
  473.     #endif
  474.     uint8_t i;
  475.    
  476.     #if KEY_CLEAR //定时请键
  477.     if(cont++ >= 50)
  478.     {
  479.         cont = 0;
  480.         bsp_ClearKey();//要清一次键值
  481.     }
  482.     #endif
  483.    
  484.     for (i = 0; i < KEY_COUNT; i++)
  485.     {
  486.         bsp_DetectKey(i);
  487.     }
  488. }
复制代码
  1. #ifndef __BSP_KEY_H
  2. #define __BSP_KEY_H
  3. #define KEY6  (GPIO_ReadInputDataBit(GPIOG,GPIO_Pin_15))//读取按键6【exit】
  4. #define KEY5  (GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_5)) //读取按键5【ok】
  5. #define KEY4  (GPIO_ReadInputDataBit(GPIOG,GPIO_Pin_14))//读取按键4【↓】
  6. #define KEY3  (GPIO_ReadInputDataBit(GPIOG,GPIO_Pin_12))//读取按键3【↑】
  7. #define KEY2  (GPIO_ReadInputDataBit(GPIOG,GPIO_Pin_11))//读取按键2【→】
  8. #define KEY1  (GPIO_ReadInputDataBit(GPIOG,GPIO_Pin_13))//读取按键1【←】
  9. /* 按键口对应的RCC时钟 */
  10. #define RCC_ALL_KEY     (RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOG)
  11. #define GPIO_PORT_K1    GPIOG
  12. #define GPIO_PIN_K1        GPIO_Pin_13
  13. #define GPIO_PORT_K2    GPIOG
  14. #define GPIO_PIN_K2        GPIO_Pin_11
  15. #define GPIO_PORT_K3    GPIOG
  16. #define GPIO_PIN_K3        GPIO_Pin_12
  17. #define GPIO_PORT_K4    GPIOG
  18. #define GPIO_PIN_K4        GPIO_Pin_14
  19. #define GPIO_PORT_K5    GPIOB
  20. #define GPIO_PIN_K5        GPIO_Pin_5
  21. #define GPIO_PORT_K6    GPIOG
  22. #define GPIO_PIN_K6        GPIO_Pin_15
  23. /*
  24.     按键滤波时间50ms, 单位10ms。
  25.     只有连续检测到50ms状态不变才认为有效,包括弹起和按下两种事件
  26.     即使按键电路不做硬件滤波,该滤波机制也可以保证可靠地检测到按键事件
  27. */
  28. #define KEY_COUNT           10  /* 按键个数, 6个独立建 + 4个组合键 */
  29. #define KEY_FIFO_SIZE        10  /* 按键FIFO用到变量 */
  30. #define KEY_FILTER_TIME     2   /* 滤波时间 */
  31. #define KEY_LONG_TIME       100 /* 单位10ms, 持续1秒,认为长按事件 */
  32. #define KEY_CLEAR           50  /* 定时清除按键,以10ms为单位,不定义则不使用;
  33.                                    按键fifo带来一个问题:按键具有记忆功能,如果应用程序和按键(优先级高一些)产生了异步,会产生连锁响应*/
  34. /* 根据应用程序的功能重命名按键宏 */
  35. #define KEY_LEFT_PRESS    KEY_1_DOWN //【←】
  36. //#define KEY_LEFT_UNDO    KEY_1_UP
  37. //#define KEY_LEFT_LONG    KEY_1_LONG
  38. #define KEY_RIGHT_PRESS    KEY_2_DOWN //【→】
  39. //#define KEY_RIGHT_UNDO    KEY_2_UP
  40. //#define KEY_RIGHT_LONG    KEY_2_LONG
  41. #define KEY_UP_PRESS    KEY_3_DOWN //【↑】
  42. //#define KEY_UP_UNDO        KEY_3_UP
  43. //#define KEY_UP_LONG        KEY_3_LONG
  44. #define KEY_DOWN_PRESS    KEY_4_DOWN //【↓】
  45. //#define KEY_DOWN_UNDO    KEY_4_UP
  46. //#define KEY_DOWN_LONG    KEY_4_LONG
  47. #define KEY_ENTER_PRESS    KEY_5_DOWN //【OK】
  48. //#define KEY_ENTER_UNDO    KEY_5_UP
  49. //#define KEY_ENTER_LONG    KEY_5_LONG
  50. //#define KEY_ESC_PRESS    KEY_6_DOWN //【Esc】
  51. #define KEY_ESC_UNDO    KEY_6_UP
  52. //#define KEY_ESC_LONG    KEY_6_LONG
  53. //组合键
  54. #define KEY_SET_PRESS            KEY_7_DOWN
  55. //#define KEY_SET_UNDO            KEY_7_UP
  56. //#define KEY_SET_LONG            KEY_7_LONG
  57. #define KEY_SHIFT1_PRESS        KEY_8_DOWN
  58. //#define KEY_SHIFT1_UNDO            KEY_8_UP
  59. //#define KEY_SHIFT1_LONG            KEY_8_LONG
  60. #define KEY_SHIFT_UP_PRESS        KEY_9_DOWN
  61. //#define KEY_SHIFT_UP_UNDO        KEY_9_UP
  62. //#define KEY_SHIFT_UP_LONG        KEY_9_LONG
  63. #define KEY_SHIFT_DOWN_PRESS    KEY_10_DOWN
  64. //#define KEY_SHIFT_DOWN_UNDO        KEY_10_UP
  65. //#define KEY_SHIFT_DOWN_LONG        KEY_10_LONG
  66. /* 按键ID, 主要用于bsp_KeyState()函数的入口参数 */
  67. typedef enum
  68. {
  69.     KID_K1 = 0,
  70.     KID_K2,
  71.     KID_K3,
  72.     KID_K4,
  73.     KID_K5,
  74.     KID_K6,
  75.     KID_K7,
  76.     KID_K8,
  77.     KID_K9,
  78.     KID_K10
  79. }KEY_ID_E;
  80. /*
  81.     每个按键对应1个全局的结构体变量。
  82. */
  83. typedef struct
  84. {
  85.     /* 下面是一个函数指针,指向判断按键手否按下的函数 */
  86.     uint8_t (*IsKeyDownFunc)(void); /* 按键按下的判断函数,1表示按下 */
  87.     uint8_t  Count;            /* 滤波器计数器 */
  88.     uint16_t LongCount;        /* 长按计数器 */
  89.     uint16_t LongTime;        /* 按键按下持续时间, 0表示不检测长按 */
  90.     uint8_t  State;            /* 按键当前状态(按下还是弹起) */
  91.     uint8_t  KeyCodeDown;    /* 按键按下的键值代码 */
  92.     uint8_t  KeyCodeUp;        /* 按键弹起的键值代码 */
  93.     uint8_t  KeyCodeLong;    /* 按键被持续按下的键值代码 */   
  94.     uint8_t  RepeatSpeed;    /* 连续按键周期 */
  95.     uint8_t  RepeatCount;    /* 连续按键计数器 */
  96.     uint8_t  attribute;     //属性,0,通用按键(独立按键);1,组合按键;2,shift键
  97. }KEY_T;
  98. /*
  99.     定义键值代码, 必须按如下次序定时每个键的按下、弹起和长按事件
  100. */
  101. typedef enum
  102. {
  103.     KEY_NONE = 0,            /* 0 表示按键事件 */
  104.     KEY_1_DOWN,                /* 1键按下 */
  105.     KEY_1_UP,                /* 1键弹起 */
  106.     KEY_1_LONG,                /* 1键长按 */
  107.     KEY_2_DOWN,                /* 2键按下 */
  108.     KEY_2_UP,                /* 2键弹起 */
  109.     KEY_2_LONG,                /* 2键长按 */
  110.     KEY_3_DOWN,                /* 3键按下 */
  111.     KEY_3_UP,                /* 3键弹起 */
  112.     KEY_3_LONG,                /* 3键长按 */
  113.     KEY_4_DOWN,                /* 4键按下 */
  114.     KEY_4_UP,                /* 4键弹起 */
  115.     KEY_4_LONG,                /* 4键长按 */
  116.     KEY_5_DOWN,                /* 5键按下 */
  117.     KEY_5_UP,                /* 5键弹起 */
  118.     KEY_5_LONG,                /* 5键长按 */
  119.     KEY_6_DOWN,                /* 6键按下 */
  120.     KEY_6_UP,                /* 6键弹起 */
  121.     KEY_6_LONG,                /* 6键长按 */
  122.    
  123.     /* 组合键 */
  124.     KEY_7_DOWN,                /* 7键按下 */
  125.     KEY_7_UP,                /* 7键弹起 */
  126.     KEY_7_LONG,                /* 7键长按 */
  127.     KEY_8_DOWN,                /* 8键按下 */
  128.     KEY_8_UP,                /* 8键弹起 */
  129.     KEY_8_LONG,                /* 8键长按 */
  130.     KEY_9_DOWN,                /* 9键按下 */
  131.     KEY_9_UP,                /* 9键弹起 */
  132.     KEY_9_LONG,                /* 9键长按 */
  133.     KEY_10_DOWN,            /* 10键按下 */
  134.     KEY_10_UP,                /* 10键弹起 */
  135.     KEY_10_LONG,            /* 10键长按 */
  136. }KEY_ENUM;
  137. typedef struct
  138. {
  139.     uint8_t Buf[KEY_FIFO_SIZE];        /* 键值缓冲区 */
  140.     uint8_t Read;                    /* 缓冲区读指针1 */
  141.     uint8_t Write;                    /* 缓冲区写指针 */
  142.     uint8_t Read2;                    /* 缓冲区读指针2 */
  143. }KEY_FIFO_T;
  144. /* 供外部调用的函数声明 */
  145. void bsp_InitKey(void);
  146. void bsp_KeyScan(void);
  147. void bsp_PutKey(uint8_t _KeyCode);
  148. uint8_t bsp_GetKey(void);
  149. uint8_t Key_GetState(KEY_ID_E _ucKeyID);
  150. void bsp_SetKeyParam(uint8_t _ucKeyID, uint16_t _LongTime, uint8_t  _RepeatSpeed);
  151. void bsp_ClearKey(void);
  152. #endif //__BSP_KEY_H
复制代码
回复

使用道具 举报

2

主题

6

回帖

12

积分

新手上路

积分
12
发表于 2017-5-17 22:36:21 | 显示全部楼层

回 makosolo 的帖子

makosolo:程序里没有处理shift键(组合键的基础键),加入几句代码应该体验更好些:


组合键的基础键(shift键)应该具有几个特点:
1、作为单键使用时必须是释放有效,不支持长按有效和连发功能
....... (2016-05-10 17:12) 
受教了
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2024-5-5 08:07 , Processed in 0.185290 second(s), 28 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表