key.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405
  1. /*
  2. *********************************************************************************************************
  3. *
  4. * 模块名称 : 独立按键驱动模块
  5. * 文件名称 : bsp_key.c
  6. * 版 本 : V1.0
  7. * 说 明 : 扫描独立按键,具有软件滤波机制,具有按键FIFO。可以检测如下事件:
  8. * (1) 按键按下
  9. * (2) 按键弹起
  10. * (3) 长按键
  11. * (4) 长按时自动连发
  12. *
  13. * 修改记录 :
  14. * 版本号 日期 作者 说明
  15. * V1.0 2013-02-01 armfly 正式发布
  16. * V1.1 2013-06-29 armfly 增加1个读指针,用于bsp_Idle() 函数读取系统控制组合键(截屏)
  17. * 增加 K1 K2 组合键 和 K2 K3 组合键,用于系统控制
  18. *
  19. * Copyright (C), 2013-2014, 安富莱电子 www.armfly.com
  20. *
  21. *********************************************************************************************************
  22. */
  23. /*
  24. 该程序适用于安富莱STM32-X3、STM32-V5开发板
  25. 如果用于其它硬件,请修改GPIO定义和 IsKeyDown1 - IsKeyDown8 函数
  26. 如果用户的按键个数小于8个,你可以将多余的按键全部定义为和第1个按键一样,并不影响程序功能
  27. #define KEY_COUNT 8 这个在 bsp_key.h 文件中定义
  28. */
  29. #include "key.h"
  30. static KEY_T s_tBtn[KEY_COUNT];
  31. static KEY_FIFO_T s_tKey; /* 按键FIFO变量,结构体 */
  32. static void bsp_DetectKey(uint8_t i);
  33. /*
  34. *********************************************************************************************************
  35. * 函 数 名: IsKeyDownX
  36. * 功能说明: 判断按键是否按下
  37. * 形 参: 无
  38. * 返 回 值: 返回值1 表示按下,0表示未按下
  39. *********************************************************************************************************
  40. */
  41. static uint8_t IsKeyDown1(void)
  42. {
  43. if ((GPIO_PORT_K1->IDR & GPIO_PIN_K1) == 0)
  44. return 1;
  45. else
  46. return 0;
  47. }
  48. static uint8_t IsKeyDown2(void)
  49. {
  50. if ((GPIO_PORT_K2->IDR & GPIO_PIN_K2) == 0)
  51. return 1;
  52. else
  53. return 0;
  54. }
  55. static uint8_t IsKeyDown3(void)
  56. {
  57. if ((GPIO_PORT_K3->IDR & GPIO_PIN_K3) == 0)
  58. return 1;
  59. else
  60. return 0;
  61. }
  62. static uint8_t IsKeyDown4(void)
  63. {
  64. if ((GPIO_PORT_K4->IDR & GPIO_PIN_K4) == 0)
  65. return 1;
  66. else
  67. return 0;
  68. }
  69. static uint8_t IsKeyDown5(void)
  70. {
  71. if ((GPIO_PORT_K5->IDR & GPIO_PIN_K5) == 0)
  72. return 1;
  73. else
  74. return 0;
  75. }
  76. static uint8_t IsKeyDown6(void)
  77. {
  78. if ((GPIO_PORT_K6->IDR & GPIO_PIN_K6) == 0)
  79. return 1;
  80. else
  81. return 0;
  82. }
  83. static uint8_t IsKeyDown7(void)
  84. {
  85. if ((GPIO_PORT_K7->IDR & GPIO_PIN_K7) == 0)
  86. return 1;
  87. else
  88. return 0;
  89. }
  90. static uint8_t IsKeyDown8(void)
  91. {
  92. if ((GPIO_PORT_K8->IDR & GPIO_PIN_K8) == 0)
  93. return 1;
  94. else
  95. return 0;
  96. }
  97. static uint8_t IsKeyDown9(void)
  98. {
  99. if (IsKeyDown1() && IsKeyDown2())
  100. return 1;
  101. else
  102. return 0;
  103. }
  104. static uint8_t IsKeyDown10(void)
  105. {
  106. if (IsKeyDown1() && IsKeyDown2())
  107. return 1;
  108. else
  109. return 0;
  110. }
  111. /*
  112. *********************************************************************************************************
  113. * 函 数 名: key_put
  114. * 功能说明: 将1个键值压入按键FIFO缓冲区。可用于模拟一个按键。
  115. * 形 参: _KeyCode : 按键代码
  116. * 返 回 值: 无
  117. *********************************************************************************************************
  118. */
  119. void key_put(uint8_t _KeyCode)
  120. {
  121. s_tKey.Buf[s_tKey.Write] = _KeyCode;
  122. if (++s_tKey.Write >= KEY_FIFO_SIZE)
  123. {
  124. s_tKey.Write = 0;
  125. }
  126. }
  127. /*
  128. *********************************************************************************************************
  129. * 函 数 名: key_get
  130. * 功能说明: 从按键FIFO缓冲区读取一个键值。
  131. * 形 参: 无
  132. * 返 回 值: 按键代码
  133. *********************************************************************************************************
  134. */
  135. uint8_t key_get(void)
  136. {
  137. uint8_t ret;
  138. if (s_tKey.Read == s_tKey.Write)
  139. {
  140. return KEY_NONE;
  141. }
  142. else
  143. {
  144. ret = s_tKey.Buf[s_tKey.Read];
  145. if (++s_tKey.Read >= KEY_FIFO_SIZE)
  146. {
  147. s_tKey.Read = 0;
  148. }
  149. return ret;
  150. }
  151. }
  152. /*
  153. *********************************************************************************************************
  154. * 函 数 名: key_get_fifo
  155. * 功能说明: 从按键FIFO缓冲区读取一个键值。独立的读指针。
  156. * 形 参: 无
  157. * 返 回 值: 按键代码
  158. *********************************************************************************************************
  159. */
  160. uint8_t key_get_fifo(void)
  161. {
  162. uint8_t ret;
  163. if (s_tKey.Read2 == s_tKey.Write)
  164. {
  165. return KEY_NONE;
  166. }
  167. else
  168. {
  169. ret = s_tKey.Buf[s_tKey.Read2];
  170. if (++s_tKey.Read2 >= KEY_FIFO_SIZE)
  171. {
  172. s_tKey.Read2 = 0;
  173. }
  174. return ret;
  175. }
  176. }
  177. /*
  178. *********************************************************************************************************
  179. * 函 数 名: key_state
  180. * 功能说明: 读取按键的状态
  181. * 形 参: _ucKeyID : 按键ID,从0开始
  182. * 返 回 值: 1 表示按下, 0 表示未按下
  183. *********************************************************************************************************
  184. */
  185. uint8_t key_state(KEY_ID_E _ucKeyID)
  186. {
  187. return s_tBtn[_ucKeyID].State;
  188. }
  189. /*
  190. *********************************************************************************************************
  191. * 函 数 名: key_state
  192. * 功能说明: 设置按键参数
  193. * 形 参:_ucKeyID : 按键ID,从0开始
  194. * _LongTime : 长按事件时间
  195. * _RepeatSpeed : 连发速度
  196. * 返 回 值: 无
  197. *********************************************************************************************************
  198. */
  199. void key_set(uint8_t _ucKeyID, uint16_t _LongTime, uint8_t _RepeatSpeed)
  200. {
  201. s_tBtn[_ucKeyID].LongTime = _LongTime; /* 长按时间 0 表示不检测长按键事件 */
  202. s_tBtn[_ucKeyID].RepeatSpeed = _RepeatSpeed; /* 按键连发的速度,0表示不支持连发 */
  203. s_tBtn[_ucKeyID].RepeatCount = 0; /* 连发计数器 */
  204. }
  205. /*
  206. *********************************************************************************************************
  207. * 函 数 名: key_clear_fifo
  208. * 功能说明: 清空按键FIFO缓冲区
  209. * 形 参:无
  210. * 返 回 值: 按键代码
  211. *********************************************************************************************************
  212. */
  213. void key_clear_fifo(void)
  214. {
  215. s_tKey.Read = s_tKey.Write;
  216. }
  217. /*
  218. *********************************************************************************************************
  219. * 函 数 名: key_init
  220. * 功能说明: 初始化按键变量
  221. * 形 参: 无
  222. * 返 回 值: 无
  223. *********************************************************************************************************
  224. */
  225. void key_init(void)
  226. {
  227. uint8_t i;
  228. /* 对按键FIFO读写指针清零 */
  229. s_tKey.Read = 0;
  230. s_tKey.Write = 0;
  231. s_tKey.Read2 = 0;
  232. /* 给每个按键结构体成员变量赋一组缺省值 */
  233. for (i = 0; i < KEY_COUNT; i++)
  234. {
  235. s_tBtn[i].LongTime = KEY_LONG_TIME; /* 长按时间 0 表示不检测长按键事件 */
  236. s_tBtn[i].Count = KEY_FILTER_TIME / 2; /* 计数器设置为滤波时间的一半 */
  237. s_tBtn[i].State = 0; /* 按键缺省状态,0为未按下 */
  238. // s_tBtn[i].KeyCodeDown = 3 * i + 1; /* 按键按下的键值代码 */
  239. // s_tBtn[i].KeyCodeUp = 3 * i + 2; /* 按键弹起的键值代码 */
  240. // s_tBtn[i].KeyCodeLong = 3 * i + 3; /* 按键被持续按下的键值代码 */
  241. s_tBtn[i].RepeatSpeed = 0; /* 按键连发的速度,0表示不支持连发 */
  242. s_tBtn[i].RepeatCount = 0; /* 连发计数器 */
  243. }
  244. /* 如果需要单独更改某个按键的参数,可以在此单独重新赋值 */
  245. /* 比如,我们希望按键1按下超过1秒后,自动重发相同键值 */
  246. s_tBtn[KID_JOY_U].LongTime = 100;
  247. s_tBtn[KID_JOY_U].RepeatSpeed = 5; /* 每隔50ms自动发送键值 */
  248. s_tBtn[KID_JOY_D].LongTime = 100;
  249. s_tBtn[KID_JOY_D].RepeatSpeed = 5; /* 每隔50ms自动发送键值 */
  250. s_tBtn[KID_JOY_L].LongTime = 100;
  251. s_tBtn[KID_JOY_L].RepeatSpeed = 5; /* 每隔50ms自动发送键值 */
  252. s_tBtn[KID_JOY_R].LongTime = 100;
  253. s_tBtn[KID_JOY_R].RepeatSpeed = 5; /* 每隔50ms自动发送键值 */
  254. /* 判断按键按下的函数 */
  255. s_tBtn[0].IsKeyDownFunc = IsKeyDown1;
  256. s_tBtn[1].IsKeyDownFunc = IsKeyDown2;
  257. s_tBtn[2].IsKeyDownFunc = IsKeyDown3;
  258. s_tBtn[3].IsKeyDownFunc = IsKeyDown4;
  259. s_tBtn[4].IsKeyDownFunc = IsKeyDown5;
  260. s_tBtn[5].IsKeyDownFunc = IsKeyDown6;
  261. s_tBtn[6].IsKeyDownFunc = IsKeyDown7;
  262. s_tBtn[7].IsKeyDownFunc = IsKeyDown8;
  263. /* 组合键 */
  264. s_tBtn[8].IsKeyDownFunc = IsKeyDown9;
  265. s_tBtn[9].IsKeyDownFunc = IsKeyDown10;
  266. }
  267. /*
  268. *********************************************************************************************************
  269. * 函 数 名: bsp_DetectKey
  270. * 功能说明: 检测一个按键。非阻塞状态,必须被周期性的调用。
  271. * 形 参: 按键结构变量指针
  272. * 返 回 值: 无
  273. *********************************************************************************************************
  274. */
  275. static void bsp_DetectKey(uint8_t i)
  276. {
  277. KEY_T *pBtn;
  278. /*
  279. 如果没有初始化按键函数,则报错
  280. if (s_tBtn[i].IsKeyDownFunc == 0)
  281. {
  282. printf("Fault : DetectButton(), s_tBtn[i].IsKeyDownFunc undefine");
  283. }
  284. */
  285. pBtn = &s_tBtn[i];
  286. if (pBtn->IsKeyDownFunc())
  287. {
  288. if (pBtn->Count < KEY_FILTER_TIME)
  289. {
  290. pBtn->Count = KEY_FILTER_TIME;
  291. }
  292. else if (pBtn->Count < 2 * KEY_FILTER_TIME)
  293. {
  294. pBtn->Count++;
  295. }
  296. else
  297. {
  298. if (pBtn->State == 0)
  299. {
  300. pBtn->State = 1;
  301. /* 发送按钮按下的消息 */
  302. key_put((uint8_t)(3 * i + 1));
  303. }
  304. if (pBtn->LongTime > 0)
  305. {
  306. if (pBtn->LongCount < pBtn->LongTime)
  307. {
  308. /* 发送按钮持续按下的消息 */
  309. if (++pBtn->LongCount == pBtn->LongTime)
  310. {
  311. /* 键值放入按键FIFO */
  312. key_put((uint8_t)(3 * i + 3));
  313. }
  314. }
  315. else
  316. {
  317. if (pBtn->RepeatSpeed > 0)
  318. {
  319. if (++pBtn->RepeatCount >= pBtn->RepeatSpeed)
  320. {
  321. pBtn->RepeatCount = 0;
  322. /* 常按键后,每隔10ms发送1个按键 */
  323. key_put((uint8_t)(3 * i + 1));
  324. }
  325. }
  326. }
  327. }
  328. }
  329. }
  330. else
  331. {
  332. if (pBtn->Count > KEY_FILTER_TIME)
  333. {
  334. pBtn->Count = KEY_FILTER_TIME;
  335. }
  336. else if (pBtn->Count != 0)
  337. {
  338. pBtn->Count--;
  339. }
  340. else
  341. {
  342. if (pBtn->State == 1)
  343. {
  344. pBtn->State = 0;
  345. /* 发送按钮弹起的消息 */
  346. key_put((uint8_t)(3 * i + 2));
  347. }
  348. }
  349. pBtn->LongCount = 0;
  350. pBtn->RepeatCount = 0;
  351. }
  352. }
  353. /*
  354. *********************************************************************************************************
  355. * 函 数 名: key_scan
  356. * 功能说明: 扫描所有按键。非阻塞,被systick中断周期性的调用
  357. * 形 参: 无
  358. * 返 回 值: 无
  359. *********************************************************************************************************
  360. */
  361. void key_scan(void)
  362. {
  363. uint8_t i;
  364. for (i = 0; i < KEY_COUNT; i++)
  365. {
  366. bsp_DetectKey(i);
  367. }
  368. }