key.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464
  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. #ifdef STM32_X3 /* 安富莱 STM32-X3 开发板 */
  42. static uint8_t IsKeyDown1(void)
  43. {
  44. if ((GPIO_PORT_K1->IDR & GPIO_PIN_K1) == 0)
  45. return 1;
  46. else
  47. return 0;
  48. }
  49. static uint8_t IsKeyDown2(void)
  50. {
  51. if ((GPIO_PORT_K2->IDR & GPIO_PIN_K2) == 0)
  52. return 1;
  53. else
  54. return 0;
  55. }
  56. static uint8_t IsKeyDown3(void)
  57. {
  58. if ((GPIO_PORT_K3->IDR & GPIO_PIN_K3) == 0)
  59. return 1;
  60. else
  61. return 0;
  62. }
  63. static uint8_t IsKeyDown4(void)
  64. {
  65. if ((GPIO_PORT_K4->IDR & GPIO_PIN_K4) == 0)
  66. return 1;
  67. else
  68. return 0;
  69. }
  70. static uint8_t IsKeyDown5(void)
  71. {
  72. if ((GPIO_PORT_K5->IDR & GPIO_PIN_K5) == 0)
  73. return 1;
  74. else
  75. return 0;
  76. }
  77. static uint8_t IsKeyDown6(void)
  78. {
  79. if ((GPIO_PORT_K6->IDR & GPIO_PIN_K6) == 0)
  80. return 1;
  81. else
  82. return 0;
  83. }
  84. static uint8_t IsKeyDown7(void)
  85. {
  86. if ((GPIO_PORT_K7->IDR & GPIO_PIN_K7) == 0)
  87. return 1;
  88. else
  89. return 0;
  90. }
  91. static uint8_t IsKeyDown8(void)
  92. {
  93. if ((GPIO_PORT_K8->IDR & GPIO_PIN_K8) == 0)
  94. return 1;
  95. else
  96. return 0;
  97. }
  98. #else /* 安富莱 STM32-V5 开发板 */
  99. static uint8_t IsKeyDown1(void)
  100. {
  101. if ((GPIO_PORT_K1->IDR & GPIO_PIN_K1) == 0)
  102. return 1;
  103. else
  104. return 0;
  105. }
  106. static uint8_t IsKeyDown2(void)
  107. {
  108. if ((GPIO_PORT_K2->IDR & GPIO_PIN_K2) == 0)
  109. return 1;
  110. else
  111. return 0;
  112. }
  113. static uint8_t IsKeyDown3(void)
  114. {
  115. if ((GPIO_PORT_K3->IDR & GPIO_PIN_K3) == 0)
  116. return 1;
  117. else
  118. return 0;
  119. }
  120. static uint8_t IsKeyDown4(void)
  121. {
  122. if ((GPIO_PORT_K4->IDR & GPIO_PIN_K4) == 0)
  123. return 1;
  124. else
  125. return 0;
  126. }
  127. static uint8_t IsKeyDown5(void)
  128. {
  129. if ((GPIO_PORT_K5->IDR & GPIO_PIN_K5) == 0)
  130. return 1;
  131. else
  132. return 0;
  133. }
  134. static uint8_t IsKeyDown6(void)
  135. {
  136. if ((GPIO_PORT_K6->IDR & GPIO_PIN_K6) == 0)
  137. return 1;
  138. else
  139. return 0;
  140. }
  141. static uint8_t IsKeyDown7(void)
  142. {
  143. if ((GPIO_PORT_K7->IDR & GPIO_PIN_K7) == 0)
  144. return 1;
  145. else
  146. return 0;
  147. }
  148. static uint8_t IsKeyDown8(void)
  149. {
  150. if ((GPIO_PORT_K8->IDR & GPIO_PIN_K8) == 0)
  151. return 1;
  152. else
  153. return 0;
  154. }
  155. #endif
  156. static uint8_t IsKeyDown9(void)
  157. {
  158. if (IsKeyDown1() && IsKeyDown2())
  159. return 1;
  160. else
  161. return 0;
  162. }
  163. static uint8_t IsKeyDown10(void)
  164. {
  165. if (IsKeyDown1() && IsKeyDown2())
  166. return 1;
  167. else
  168. return 0;
  169. }
  170. /*
  171. *********************************************************************************************************
  172. * 函 数 名: bsp_PutKey
  173. * 功能说明: 将1个键值压入按键FIFO缓冲区。可用于模拟一个按键。
  174. * 形 参: _KeyCode : 按键代码
  175. * 返 回 值: 无
  176. *********************************************************************************************************
  177. */
  178. void bsp_PutKey(uint8_t _KeyCode)
  179. {
  180. s_tKey.Buf[s_tKey.Write] = _KeyCode;
  181. if (++s_tKey.Write >= KEY_FIFO_SIZE)
  182. {
  183. s_tKey.Write = 0;
  184. }
  185. }
  186. /*
  187. *********************************************************************************************************
  188. * 函 数 名: bsp_GetKey
  189. * 功能说明: 从按键FIFO缓冲区读取一个键值。
  190. * 形 参: 无
  191. * 返 回 值: 按键代码
  192. *********************************************************************************************************
  193. */
  194. uint8_t bsp_GetKey(void)
  195. {
  196. uint8_t ret;
  197. if (s_tKey.Read == s_tKey.Write)
  198. {
  199. return KEY_NONE;
  200. }
  201. else
  202. {
  203. ret = s_tKey.Buf[s_tKey.Read];
  204. if (++s_tKey.Read >= KEY_FIFO_SIZE)
  205. {
  206. s_tKey.Read = 0;
  207. }
  208. return ret;
  209. }
  210. }
  211. /*
  212. *********************************************************************************************************
  213. * 函 数 名: bsp_GetKey2
  214. * 功能说明: 从按键FIFO缓冲区读取一个键值。独立的读指针。
  215. * 形 参: 无
  216. * 返 回 值: 按键代码
  217. *********************************************************************************************************
  218. */
  219. uint8_t bsp_GetKey2(void)
  220. {
  221. uint8_t ret;
  222. if (s_tKey.Read2 == s_tKey.Write)
  223. {
  224. return KEY_NONE;
  225. }
  226. else
  227. {
  228. ret = s_tKey.Buf[s_tKey.Read2];
  229. if (++s_tKey.Read2 >= KEY_FIFO_SIZE)
  230. {
  231. s_tKey.Read2 = 0;
  232. }
  233. return ret;
  234. }
  235. }
  236. /*
  237. *********************************************************************************************************
  238. * 函 数 名: bsp_GetKeyState
  239. * 功能说明: 读取按键的状态
  240. * 形 参: _ucKeyID : 按键ID,从0开始
  241. * 返 回 值: 1 表示按下, 0 表示未按下
  242. *********************************************************************************************************
  243. */
  244. uint8_t bsp_GetKeyState(KEY_ID_E _ucKeyID)
  245. {
  246. return s_tBtn[_ucKeyID].State;
  247. }
  248. /*
  249. *********************************************************************************************************
  250. * 函 数 名: bsp_SetKeyParam
  251. * 功能说明: 设置按键参数
  252. * 形 参:_ucKeyID : 按键ID,从0开始
  253. * _LongTime : 长按事件时间
  254. * _RepeatSpeed : 连发速度
  255. * 返 回 值: 无
  256. *********************************************************************************************************
  257. */
  258. void bsp_SetKeyParam(uint8_t _ucKeyID, uint16_t _LongTime, uint8_t _RepeatSpeed)
  259. {
  260. s_tBtn[_ucKeyID].LongTime = _LongTime; /* 长按时间 0 表示不检测长按键事件 */
  261. s_tBtn[_ucKeyID].RepeatSpeed = _RepeatSpeed; /* 按键连发的速度,0表示不支持连发 */
  262. s_tBtn[_ucKeyID].RepeatCount = 0; /* 连发计数器 */
  263. }
  264. /*
  265. *********************************************************************************************************
  266. * 函 数 名: bsp_ClearKey
  267. * 功能说明: 清空按键FIFO缓冲区
  268. * 形 参:无
  269. * 返 回 值: 按键代码
  270. *********************************************************************************************************
  271. */
  272. void bsp_ClearKey(void)
  273. {
  274. s_tKey.Read = s_tKey.Write;
  275. }
  276. /*
  277. *********************************************************************************************************
  278. * 函 数 名: key_init
  279. * 功能说明: 初始化按键变量
  280. * 形 参: 无
  281. * 返 回 值: 无
  282. *********************************************************************************************************
  283. */
  284. void key_init(void)
  285. {
  286. uint8_t i;
  287. /* 对按键FIFO读写指针清零 */
  288. s_tKey.Read = 0;
  289. s_tKey.Write = 0;
  290. s_tKey.Read2 = 0;
  291. /* 给每个按键结构体成员变量赋一组缺省值 */
  292. for (i = 0; i < KEY_COUNT; i++)
  293. {
  294. s_tBtn[i].LongTime = KEY_LONG_TIME; /* 长按时间 0 表示不检测长按键事件 */
  295. s_tBtn[i].Count = KEY_FILTER_TIME / 2; /* 计数器设置为滤波时间的一半 */
  296. s_tBtn[i].State = 0; /* 按键缺省状态,0为未按下 */
  297. // s_tBtn[i].KeyCodeDown = 3 * i + 1; /* 按键按下的键值代码 */
  298. // s_tBtn[i].KeyCodeUp = 3 * i + 2; /* 按键弹起的键值代码 */
  299. // s_tBtn[i].KeyCodeLong = 3 * i + 3; /* 按键被持续按下的键值代码 */
  300. s_tBtn[i].RepeatSpeed = 0; /* 按键连发的速度,0表示不支持连发 */
  301. s_tBtn[i].RepeatCount = 0; /* 连发计数器 */
  302. }
  303. /* 如果需要单独更改某个按键的参数,可以在此单独重新赋值 */
  304. /* 比如,我们希望按键1按下超过1秒后,自动重发相同键值 */
  305. s_tBtn[KID_JOY_U].LongTime = 100;
  306. s_tBtn[KID_JOY_U].RepeatSpeed = 5; /* 每隔50ms自动发送键值 */
  307. s_tBtn[KID_JOY_D].LongTime = 100;
  308. s_tBtn[KID_JOY_D].RepeatSpeed = 5; /* 每隔50ms自动发送键值 */
  309. s_tBtn[KID_JOY_L].LongTime = 100;
  310. s_tBtn[KID_JOY_L].RepeatSpeed = 5; /* 每隔50ms自动发送键值 */
  311. s_tBtn[KID_JOY_R].LongTime = 100;
  312. s_tBtn[KID_JOY_R].RepeatSpeed = 5; /* 每隔50ms自动发送键值 */
  313. /* 判断按键按下的函数 */
  314. s_tBtn[0].IsKeyDownFunc = IsKeyDown1;
  315. s_tBtn[1].IsKeyDownFunc = IsKeyDown2;
  316. s_tBtn[2].IsKeyDownFunc = IsKeyDown3;
  317. s_tBtn[3].IsKeyDownFunc = IsKeyDown4;
  318. s_tBtn[4].IsKeyDownFunc = IsKeyDown5;
  319. s_tBtn[5].IsKeyDownFunc = IsKeyDown6;
  320. s_tBtn[6].IsKeyDownFunc = IsKeyDown7;
  321. s_tBtn[7].IsKeyDownFunc = IsKeyDown8;
  322. /* 组合键 */
  323. s_tBtn[8].IsKeyDownFunc = IsKeyDown9;
  324. s_tBtn[9].IsKeyDownFunc = IsKeyDown10;
  325. }
  326. /*
  327. *********************************************************************************************************
  328. * 函 数 名: bsp_DetectKey
  329. * 功能说明: 检测一个按键。非阻塞状态,必须被周期性的调用。
  330. * 形 参: 按键结构变量指针
  331. * 返 回 值: 无
  332. *********************************************************************************************************
  333. */
  334. static void bsp_DetectKey(uint8_t i)
  335. {
  336. KEY_T *pBtn;
  337. /*
  338. 如果没有初始化按键函数,则报错
  339. if (s_tBtn[i].IsKeyDownFunc == 0)
  340. {
  341. printf("Fault : DetectButton(), s_tBtn[i].IsKeyDownFunc undefine");
  342. }
  343. */
  344. pBtn = &s_tBtn[i];
  345. if (pBtn->IsKeyDownFunc())
  346. {
  347. if (pBtn->Count < KEY_FILTER_TIME)
  348. {
  349. pBtn->Count = KEY_FILTER_TIME;
  350. }
  351. else if (pBtn->Count < 2 * KEY_FILTER_TIME)
  352. {
  353. pBtn->Count++;
  354. }
  355. else
  356. {
  357. if (pBtn->State == 0)
  358. {
  359. pBtn->State = 1;
  360. /* 发送按钮按下的消息 */
  361. bsp_PutKey((uint8_t)(3 * i + 1));
  362. }
  363. if (pBtn->LongTime > 0)
  364. {
  365. if (pBtn->LongCount < pBtn->LongTime)
  366. {
  367. /* 发送按钮持续按下的消息 */
  368. if (++pBtn->LongCount == pBtn->LongTime)
  369. {
  370. /* 键值放入按键FIFO */
  371. bsp_PutKey((uint8_t)(3 * i + 3));
  372. }
  373. }
  374. else
  375. {
  376. if (pBtn->RepeatSpeed > 0)
  377. {
  378. if (++pBtn->RepeatCount >= pBtn->RepeatSpeed)
  379. {
  380. pBtn->RepeatCount = 0;
  381. /* 常按键后,每隔10ms发送1个按键 */
  382. bsp_PutKey((uint8_t)(3 * i + 1));
  383. }
  384. }
  385. }
  386. }
  387. }
  388. }
  389. else
  390. {
  391. if (pBtn->Count > KEY_FILTER_TIME)
  392. {
  393. pBtn->Count = KEY_FILTER_TIME;
  394. }
  395. else if (pBtn->Count != 0)
  396. {
  397. pBtn->Count--;
  398. }
  399. else
  400. {
  401. if (pBtn->State == 1)
  402. {
  403. pBtn->State = 0;
  404. /* 发送按钮弹起的消息 */
  405. bsp_PutKey((uint8_t)(3 * i + 2));
  406. }
  407. }
  408. pBtn->LongCount = 0;
  409. pBtn->RepeatCount = 0;
  410. }
  411. }
  412. /*
  413. *********************************************************************************************************
  414. * 函 数 名: bsp_KeyScan
  415. * 功能说明: 扫描所有按键。非阻塞,被systick中断周期性的调用
  416. * 形 参: 无
  417. * 返 回 值: 无
  418. *********************************************************************************************************
  419. */
  420. void bsp_KeyScan(void)
  421. {
  422. uint8_t i;
  423. for (i = 0; i < KEY_COUNT; i++)
  424. {
  425. bsp_DetectKey(i);
  426. }
  427. }
  428. /***************************** 安富莱电子 www.armfly.com (END OF FILE) *********************************/