button.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511
  1. /************************************************************
  2. * @brief 按键驱动
  3. * @param NULL
  4. * @return NULL
  5. * @author jiejie
  6. * @github https://github.com/jiejieTop
  7. * @date 2018-xx-xx
  8. * @version v1.0
  9. * @note button.c
  10. ***********************************************************/
  11. #include "button.h"
  12. #include "string.h"
  13. /*******************************************************************
  14. * 变量声明
  15. *******************************************************************/
  16. static struct button* Head_Button = NULL;
  17. /*******************************************************************
  18. * 函数声明
  19. *******************************************************************/
  20. static char *StrnCopy(char *dst, const char *src, uint32_t n);
  21. static void Print_Btn_Info(Button_t* btn);
  22. static void Add_Button(Button_t* btn);
  23. /************************************************************
  24. * @brief 按键创建
  25. * @param name : 按键名称
  26. * @param btn : 按键结构体
  27. * @param read_btn_level : 按键电平读取函数,需要用户自己实现返回uint8_t类型的电平
  28. * @param btn_trigger_level : 按键触发电平
  29. * @return NULL
  30. * @author jiejie
  31. * @github https://github.com/jiejieTop
  32. * @date 2018-xx-xx
  33. * @version v1.0
  34. * @note NULL
  35. ***********************************************************/
  36. void Button_Create(const char *name,
  37. Button_t *btn,
  38. uint8_t(*read_btn_level)(void),
  39. uint8_t btn_trigger_level)
  40. {
  41. if( btn == NULL)
  42. {
  43. PRINT_ERR("struct button is null!");
  44. ASSERT(ASSERT_ERR);
  45. }
  46. memset(btn, 0, sizeof(struct button)); //清除结构体信息,建议用户在之前清除
  47. StrnCopy(btn->Name, name, BTN_NAME_MAX); /* 创建按键名称 */
  48. btn->Button_State = NONE_TRIGGER; //按键状态
  49. btn->Button_Last_State = NONE_TRIGGER; //按键上一次状态
  50. btn->Button_Trigger_Event = NONE_TRIGGER; //按键触发事件
  51. btn->Read_Button_Level = read_btn_level; //按键读电平函数
  52. btn->Button_Trigger_Level = btn_trigger_level; //按键触发电平
  53. btn->Button_Last_Level = btn->Read_Button_Level(); //按键当前电平
  54. btn->Debounce_Time = 0;
  55. PRINT_DEBUG("button create success!");
  56. Add_Button(btn); //创建的时候添加到单链表中
  57. Print_Btn_Info(btn); //打印信息
  58. }
  59. /************************************************************
  60. * @brief 按键触发事件与回调函数映射链接起来
  61. * @param btn : 按键结构体
  62. * @param btn_event : 按键触发事件
  63. * @param btn_callback : 按键触发之后的回调处理函数。需要用户实现
  64. * @return NULL
  65. * @author jiejie
  66. * @github https://github.com/jiejieTop
  67. * @date 2018-xx-xx
  68. * @version v1.0
  69. ***********************************************************/
  70. void Button_Attach(Button_t *btn,Button_Event btn_event,Button_CallBack btn_callback)
  71. {
  72. uint8_t i;
  73. if( btn == NULL)
  74. {
  75. PRINT_ERR("struct button is null!");
  76. //ASSERT(ASSERT_ERR); //断言
  77. }
  78. if(BUTTON_ALL_RIGGER == btn_event)
  79. {
  80. for(i = 0 ; i < number_of_event-1 ; i++)
  81. btn->CallBack_Function[i] = btn_callback; //按键事件触发的回调函数,用于处理按键事件
  82. }
  83. else
  84. {
  85. btn->CallBack_Function[btn_event] = btn_callback; //按键事件触发的回调函数,用于处理按键事件
  86. }
  87. }
  88. /************************************************************
  89. * @brief 删除一个已经创建的按键
  90. * @param NULL
  91. * @return NULL
  92. * @author jiejie
  93. * @github https://github.com/jiejieTop
  94. * @date 2018-xx-xx
  95. * @version v1.0
  96. * @note NULL
  97. ***********************************************************/
  98. void Button_Delete(Button_t *btn)
  99. {
  100. struct button** curr;
  101. for(curr = &Head_Button; *curr;)
  102. {
  103. struct button* entry = *curr;
  104. if (entry == btn)
  105. {
  106. *curr = entry->Next;
  107. }
  108. else
  109. {
  110. curr = &entry->Next;
  111. }
  112. }
  113. }
  114. /************************************************************
  115. * @brief 获取按键触发的事件
  116. * @param NULL
  117. * @return NULL
  118. * @author jiejie
  119. * @github https://github.com/jiejieTop
  120. * @date 2018-xx-xx
  121. * @version v1.0
  122. ***********************************************************/
  123. void Get_Button_EventInfo(Button_t *btn)
  124. {
  125. uint8_t i;
  126. //按键事件触发的回调函数,用于处理按键事件
  127. for(i = 0 ; i < number_of_event-1 ; i++)
  128. {
  129. if(btn->CallBack_Function[i] != 0)
  130. {
  131. PRINT_INFO("Button_Event:%d",i);
  132. }
  133. }
  134. }
  135. uint8_t Get_Button_Event(Button_t *btn)
  136. {
  137. return (uint8_t)(btn->Button_Trigger_Event);
  138. }
  139. /************************************************************
  140. * @brief 获取按键触发的事件
  141. * @param NULL
  142. * @return NULL
  143. * @author jiejie
  144. * @github https://github.com/jiejieTop
  145. * @date 2018-xx-xx
  146. * @version v1.0
  147. ***********************************************************/
  148. uint8_t Get_Button_State(Button_t *btn)
  149. {
  150. return (uint8_t)(btn->Button_State);
  151. }
  152. /************************************************************
  153. * @brief 按键周期处理函数
  154. * @param btn:处理的按键
  155. * @return NULL
  156. * @author jiejie
  157. * @github https://github.com/jiejieTop
  158. * @date 2018-xx-xx
  159. * @version v1.0
  160. * @note 必须以一定周期调用此函数,建议周期为20~50ms
  161. ***********************************************************/
  162. void Button_Cycle_Process(Button_t *btn)
  163. {
  164. uint8_t current_level = (uint8_t)btn->Read_Button_Level();//获取当前按键电平
  165. if((current_level != btn->Button_Last_Level)&&(++(btn->Debounce_Time) >= BUTTON_DEBOUNCE_TIME)) //按键电平发生变化,消抖
  166. {
  167. btn->Button_Last_Level = current_level; //更新当前按键电平
  168. btn->Debounce_Time = 0; //确定了是按下
  169. //如果按键是没被按下的,改变按键状态为按下(首次按下/双击按下)
  170. if((btn->Button_State == NONE_TRIGGER)||(btn->Button_State == BUTTON_DOUBLE))
  171. {
  172. btn->Button_State = BUTTON_DOWM;
  173. }
  174. //释放按键
  175. else if(btn->Button_State == BUTTON_DOWM)
  176. {
  177. btn->Button_State = BUTTON_UP;
  178. TRIGGER_CB(BUTTON_UP); // 触发释放
  179. PRINT_DEBUG("释放了按键");
  180. }
  181. }
  182. switch(btn->Button_State)
  183. {
  184. case BUTTON_DOWM : // 按下状态
  185. {
  186. if(btn->Button_Last_Level == btn->Button_Trigger_Level) //按键按下
  187. {
  188. #if CONTINUOS_TRIGGER //支持连续触发
  189. if(++(btn->Button_Cycle) >= BUTTON_CONTINUOS_CYCLE)
  190. {
  191. btn->Button_Cycle = 0;
  192. btn->Button_Trigger_Event = BUTTON_CONTINUOS;
  193. TRIGGER_CB(BUTTON_CONTINUOS); //连按
  194. PRINT_DEBUG("连按");
  195. }
  196. #else
  197. btn->Button_Trigger_Event = BUTTON_DOWM;
  198. if(++(btn->Long_Time) >= BUTTON_LONG_TIME) //释放按键前更新触发事件为长按
  199. {
  200. #if LONG_FREE_TRIGGER
  201. btn->Button_Trigger_Event = BUTTON_LONG;
  202. #else
  203. if(++(btn->Button_Cycle) >= BUTTON_LONG_CYCLE) //连续触发长按的周期
  204. {
  205. btn->Button_Cycle = 0;
  206. btn->Button_Trigger_Event = BUTTON_LONG;
  207. TRIGGER_CB(BUTTON_LONG); //长按
  208. }
  209. #endif
  210. if(btn->Long_Time == 0xFF) //更新时间溢出
  211. {
  212. btn->Long_Time = BUTTON_LONG_TIME;
  213. }
  214. PRINT_DEBUG("长按");
  215. }
  216. #endif
  217. }
  218. break;
  219. }
  220. case BUTTON_UP : // 弹起状态
  221. {
  222. if(btn->Button_Trigger_Event == BUTTON_DOWM) //触发单击
  223. {
  224. if((btn->Timer_Count <= BUTTON_DOUBLE_TIME)&&(btn->Button_Last_State == BUTTON_DOUBLE)) // 双击
  225. {
  226. btn->Button_Trigger_Event = BUTTON_DOUBLE;
  227. TRIGGER_CB(BUTTON_DOUBLE);
  228. PRINT_DEBUG("双击");
  229. btn->Button_State = NONE_TRIGGER;
  230. btn->Button_Last_State = NONE_TRIGGER;
  231. }
  232. else
  233. {
  234. btn->Timer_Count=0;
  235. btn->Long_Time = 0; //检测长按失败,清0
  236. #if (SINGLE_AND_DOUBLE_TRIGGER == 0)
  237. TRIGGER_CB(BUTTON_DOWM); //单击
  238. #endif
  239. btn->Button_State = BUTTON_DOUBLE;
  240. btn->Button_Last_State = BUTTON_DOUBLE;
  241. }
  242. }
  243. else if(btn->Button_Trigger_Event == BUTTON_LONG)
  244. {
  245. #if LONG_FREE_TRIGGER
  246. TRIGGER_CB(BUTTON_LONG); //长按
  247. #else
  248. TRIGGER_CB(BUTTON_LONG_FREE); //长按释放
  249. #endif
  250. btn->Long_Time = 0;
  251. btn->Button_State = NONE_TRIGGER;
  252. btn->Button_Last_State = BUTTON_LONG;
  253. }
  254. #if CONTINUOS_TRIGGER
  255. else if(btn->Button_Trigger_Event == BUTTON_CONTINUOS) //连按
  256. {
  257. btn->Long_Time = 0;
  258. TRIGGER_CB(BUTTON_CONTINUOS_FREE); //连发释放
  259. btn->Button_State = NONE_TRIGGER;
  260. btn->Button_Last_State = BUTTON_CONTINUOS;
  261. }
  262. #endif
  263. break;
  264. }
  265. case BUTTON_DOUBLE :
  266. {
  267. btn->Timer_Count++; //时间记录
  268. if(btn->Timer_Count>=BUTTON_DOUBLE_TIME)
  269. {
  270. btn->Button_State = NONE_TRIGGER;
  271. btn->Button_Last_State = NONE_TRIGGER;
  272. }
  273. #if SINGLE_AND_DOUBLE_TRIGGER
  274. if((btn->Timer_Count>=BUTTON_DOUBLE_TIME)&&(btn->Button_Last_State != BUTTON_DOWM))
  275. {
  276. btn->Timer_Count=0;
  277. TRIGGER_CB(BUTTON_DOWM); //单击
  278. btn->Button_State = NONE_TRIGGER;
  279. btn->Button_Last_State = BUTTON_DOWM;
  280. }
  281. #endif
  282. break;
  283. }
  284. default :
  285. break;
  286. }
  287. }
  288. /************************************************************
  289. * @brief 遍历的方式扫描按键,不会丢失每个按键
  290. * @param NULL
  291. * @return NULL
  292. * @author jiejie
  293. * @github https://github.com/jiejieTop
  294. * @date 2018-xx-xx
  295. * @version v1.0
  296. * @note 此函数要周期调用,建议20-50ms调用一次
  297. ***********************************************************/
  298. void Button_Process(void)
  299. {
  300. struct button* pass_btn;
  301. for(pass_btn = Head_Button; pass_btn != NULL; pass_btn = pass_btn->Next)
  302. {
  303. Button_Cycle_Process(pass_btn);
  304. }
  305. }
  306. /************************************************************
  307. * @brief 遍历按键
  308. * @param NULL
  309. * @return NULL
  310. * @author jiejie
  311. * @github https://github.com/jiejieTop
  312. * @date 2018-xx-xx
  313. * @version v1.0
  314. * @note NULL
  315. ***********************************************************/
  316. void Search_Button(void)
  317. {
  318. struct button* pass_btn;
  319. for(pass_btn = Head_Button; pass_btn != NULL; pass_btn = pass_btn->Next)
  320. {
  321. PRINT_INFO("button node have %s",pass_btn->Name);
  322. }
  323. }
  324. /************************************************************
  325. * @brief 处理所有按键回调函数
  326. * @param NULL
  327. * @return NULL
  328. * @author jiejie
  329. * @github https://github.com/jiejieTop
  330. * @date 2018-xx-xx
  331. * @version v1.0
  332. * @note 暂不实现
  333. ***********************************************************/
  334. void Button_Process_CallBack(void *btn)
  335. {
  336. uint8_t btn_event = Get_Button_Event(btn);
  337. switch(btn_event)
  338. {
  339. case BUTTON_DOWM:
  340. {
  341. PRINT_INFO("添加你的按下触发的处理逻辑");
  342. break;
  343. }
  344. case BUTTON_UP:
  345. {
  346. PRINT_INFO("添加你的释放触发的处理逻辑");
  347. break;
  348. }
  349. case BUTTON_DOUBLE:
  350. {
  351. PRINT_INFO("添加你的双击触发的处理逻辑");
  352. break;
  353. }
  354. case BUTTON_LONG:
  355. {
  356. PRINT_INFO("添加你的长按触发的处理逻辑");
  357. break;
  358. }
  359. case BUTTON_LONG_FREE:
  360. {
  361. PRINT_INFO("添加你的长按释放触发的处理逻辑");
  362. break;
  363. }
  364. case BUTTON_CONTINUOS:
  365. {
  366. PRINT_INFO("添加你的连续触发的处理逻辑");
  367. break;
  368. }
  369. case BUTTON_CONTINUOS_FREE:
  370. {
  371. PRINT_INFO("添加你的连续触发释放的处理逻辑");
  372. break;
  373. }
  374. }
  375. }
  376. /**************************** 以下是内部调用函数 ********************/
  377. /************************************************************
  378. * @brief 拷贝指定长度字符串
  379. * @param NULL
  380. * @return NULL
  381. * @author jiejie
  382. * @github https://github.com/jiejieTop
  383. * @date 2018-xx-xx
  384. * @version v1.0
  385. * @note NULL
  386. ***********************************************************/
  387. static char *StrnCopy(char *dst, const char *src, uint32_t n)
  388. {
  389. if (n != 0)
  390. {
  391. char *d = dst;
  392. const char *s = src;
  393. do
  394. {
  395. if ((*d++ = *s++) == 0)
  396. {
  397. while (--n != 0)
  398. *d++ = 0;
  399. break;
  400. }
  401. } while (--n != 0);
  402. }
  403. return (dst);
  404. }
  405. /************************************************************
  406. * @brief 打印按键相关信息
  407. * @param NULL
  408. * @return NULL
  409. * @author jiejie
  410. * @github https://github.com/jiejieTop
  411. * @date 2018-xx-xx
  412. * @version v1.0
  413. * @note NULL
  414. ***********************************************************/
  415. static void Print_Btn_Info(Button_t* btn)
  416. {
  417. PRINT_INFO("button struct information:\n\
  418. btn->Name:%s \n\
  419. btn->Button_State:%d \n\
  420. btn->Button_Trigger_Event:%d \n\
  421. btn->Button_Trigger_Level:%d \n\
  422. btn->Button_Last_Level:%d \n\
  423. ",
  424. btn->Name,
  425. btn->Button_State,
  426. btn->Button_Trigger_Event,
  427. btn->Button_Trigger_Level,
  428. btn->Button_Last_Level);
  429. Search_Button();
  430. }
  431. /************************************************************
  432. * @brief 使用单链表将按键连接起来
  433. * @param NULL
  434. * @return NULL
  435. * @author jiejie
  436. * @github https://github.com/jiejieTop
  437. * @date 2018-xx-xx
  438. * @version v1.0
  439. * @note NULL
  440. ***********************************************************/
  441. static void Add_Button(Button_t* btn)
  442. {
  443. btn->Next = Head_Button;
  444. Head_Button = btn;
  445. }