找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開始

搜索
查看: 4735|回復(fù): 2
打印 上一主題 下一主題
收起左側(cè)

PIC單片機(jī)單個(gè)按鍵實(shí)現(xiàn)多功能:長(zhǎng)按、短按次數(shù)識(shí)別程序

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
春節(jié)放假?zèng)]有回老家,于是寫了個(gè)多功能按鍵識(shí)別小程序!
按鍵分為長(zhǎng)按識(shí)別(長(zhǎng)按3秒),短按識(shí)別(記錄識(shí)別當(dāng)前按的次數(shù)),以節(jié)約單片I/O!

用我自制的PIC16F887+I2C BD2004試驗(yàn)板測(cè)試如下圖:


單片機(jī)源程序如下:
  1. #include<pic.h>  
  2. #define uint unsigned int
  3. #define uchar unsigned char

  4. //--------------//

  5. //配合8M頻率
  6. //開關(guān)使用情況:
  7. //長(zhǎng)按約2秒 生置鍵生效
  8. //單擊 +  雙擊 -
  9. //三擊及以上未使用

  10. //--------------//
  11. #define  sw1 RA4   //
  12. #define  long_time  200  //長(zhǎng)按按鍵時(shí)間預(yù)設(shè) 約2秒
  13. #define  re_time1   46   //第一次按下開關(guān)等待第二次按下開關(guān)的時(shí)長(zhǎng)
  14. #define  re_push    0    //第二次及之后的按住開關(guān)的時(shí)長(zhǎng) 為零時(shí)雙擊效率增加
  15. #define  re_time2   55   //第二次及之后等待再次按下開關(guān)的時(shí)長(zhǎng)
  16. bit     read_one;
  17. bit     push_one;
  18. bit     push_hold;
  19. bit     sw_one_flag;
  20. bit     re_push_lock;
  21. bit     key_long_flag;
  22. bit     push_one_flag;
  23. bit     jian_temp_flag;
  24. bit     long_lock_flag;
  25. bit     sec_push_flag;
  26. bit     long_flag;
  27. bit     sen;
  28. bit     set_sw_flag,short_temp_flag;
  29. bit    to_noli_flag;
  30. bit    thr_flag;
  31. bit    jiao_set_flag;

  32. bit   up_flag;        //加按鍵
  33. bit   dn_flag;        //減按鍵
  34. bit   se_flag;

  35. uint    cont;
  36. uchar   key_cont;
  37. uchar   key_num;
  38. uint   sw_open_cont,sw_open_cont1,re_push_cont;

  39. char     set_mode;  // 長(zhǎng)按+

  40. void push_scan();   //長(zhǎng)短及連按計(jì)次處理
  41. void key_scan();    //對(duì)應(yīng)按次處理

  42. /*
  43. ////以下這段長(zhǎng)短按鍵識(shí)別計(jì)數(shù)器 復(fù)制到TMR0中斷內(nèi)執(zhí)行效率更高////////////
  44. //--------------------//
  45. if(sw1==0&&sw_one_flag==0&&cont<long_time)    //
  46. {
  47. cont++;if(cont>=long_time) long_flag=1;  //長(zhǎng)按時(shí)間約2秒
  48. }
  49. else cont=0;
  50. //--------------------//
  51. if(push_one==1)
  52. {
  53. if(sw1==1&&push_hold==0) //第一次按下開關(guān)等待第二次按下開關(guān)的時(shí)長(zhǎng)
  54. {sw_open_cont1++;
  55. }

  56. if(push_hold)
  57. {
  58. //if(sw1==0&&re_push_lock==0){re_push_cont++;}//再次按下時(shí)間限制,用于不能太快松開
  59. if(sw1==1&&re_push_lock==0)sw_open_cont++;//第二次及之后等待再次按下開關(guān)的時(shí)長(zhǎng)
  60. }

  61. }
  62. //--------------------//
  63. ////長(zhǎng)短按鍵識(shí)別計(jì)數(shù)end////////////
  64. */


  65. ///////////////////
  66. //----------------------------//
  67. //單按鍵長(zhǎng)、短按識(shí)別
  68. //長(zhǎng)按輸出結(jié)果:key_long_flag 為1時(shí)有效,
  69. //短按計(jì)次輸出:key_num; key_num=1~10     
  70. void push_scan(void)
  71. {
  72. /////長(zhǎng)按鍵處理//////
  73. if(sw1==0&&push_hold==0)    //
  74. {
  75. //cont++;if(cont>=long_time) long_flag=1;  //長(zhǎng)按時(shí)間約3秒 在中TMR0中斷內(nèi)執(zhí)行提高計(jì)時(shí)穩(wěn)定
  76. if(long_flag&&sw_one_flag==0)   //處理長(zhǎng)按鈕
  77. {
  78. key_long_flag=1;
  79. //didi(1);
  80. sw_one_flag=1;
  81. long_lock_flag=1;
  82. }  
  83. } else {if(sw1==1&&sw_one_flag){ cont=0;sw_one_flag=0;long_flag=0;}}
  84. /////長(zhǎng)按鍵處理完成//////

  85. //------短按處理--//
  86. //---第一次按下后再放開按鍵的處理--//
  87. if(sw1==0&&push_one_flag==0){push_one_flag=1;key_num=0;}//第一次壓下開關(guān)檢測(cè) 并清除舊的key_num
  88. else if(push_one_flag==1&&sw1==1){push_one_flag=0;push_one=1;}//當(dāng)?shù)谝淮螇合路砰_后置位壓一次標(biāo)志避免與長(zhǎng)按沖突
  89. //---第一次按下后再放開按鍵完成--//

  90. //---當(dāng)檢測(cè)到第一次壓下并放開后--//
  91. if(push_one)
  92. {
  93. //---是否有第二次按壓處理--//
  94. if(sw1==0&&push_hold==0&&sec_push_flag==0)//檢測(cè)有第二次壓下
  95. {
  96. if(push_hold==0) key_cont=1;//有第二次壓下時(shí)將上次的按鍵次數(shù) 先清零 導(dǎo)入開關(guān)后應(yīng)關(guān)閉
  97. push_hold=1;                //有第二次壓下開關(guān)時(shí)置位開關(guān)按過(guò)的標(biāo)志,
  98. sec_push_flag=1;
  99. }

  100. else if(sw1==1&&push_hold==0) //若無(wú)第二次按開關(guān) 清零按過(guò)標(biāo)志
  101. {//sw_open_cont1++;         //在中TMR0中斷內(nèi)執(zhí)行提高計(jì)時(shí)穩(wěn)定   
  102. if(sw_open_cont1>re_time1)//超過(guò)指定間隔時(shí)間未按開關(guān)
  103. {sec_push_flag=0;push_one=0;sw_open_cont1=0;
  104. if(long_lock_flag)
  105. {key_cont=0;long_lock_flag=0;}
  106. else {key_cont=1;}}
  107. }
  108. //---第二次是否按壓處理完成--//

  109. //---第二次及之后按壓計(jì)數(shù)處理--//
  110. if(push_hold)//第二次壓下開始作業(yè)計(jì)數(shù)
  111. {
  112. if(sw1==0&&re_push_lock==0)//再次按壓開關(guān)
  113. { sw_open_cont=0;//有再次按下開關(guān)則清零松開計(jì)數(shù)器
  114. re_push_cont++;
  115. if(re_push_cont>re_push)//再次按下時(shí)間限制,用于不能太快松開
  116. {key_cont++;re_push_lock=1;}
  117. }  
  118. else if(sw1==1&&re_push_lock==1){re_push_cont=0;re_push_lock=0;}

  119. else if(sw1==1)//標(biāo)記有按過(guò)按鍵再放開時(shí)間判定
  120. {
  121. //sw_open_cont++;            //在中TMR0中斷內(nèi)執(zhí)行提高計(jì)時(shí)穩(wěn)定
  122. if(sw_open_cont>re_time2)
  123. { push_hold=0;sw_open_cont=0;//超過(guò)指定時(shí)間標(biāo)記位
  124. push_one=0;sw_open_cont1=0;sec_push_flag=0;long_flag=0;
  125. }

  126. }

  127. }
  128. //---第二次及之后按壓計(jì)數(shù)完成--//
  129. }   
  130. //---短按處理完成 提取健值--//
  131. if(sw1==1&&push_one_flag==0&&push_hold==0)//確認(rèn)沒(méi)有按鍵動(dòng)作時(shí)
  132. {
  133. if(key_cont>0&&read_one==0)
  134. {
  135. key_num=key_cont;//dis=key_cont;
  136. key_cont=0;
  137. read_one=1;
  138. }else if(read_one==1)read_one=0;
  139. }
  140. //短按之后沒(méi)有及時(shí)放開按鍵 當(dāng)?shù)竭_(dá)長(zhǎng)按上限時(shí)當(dāng)作按鍵結(jié)束
  141. else if(sw1==0&&key_cont>0&&push_hold==1&&long_flag==1)
  142. {
  143. if(key_cont>0&&read_one==0)
  144. {
  145. key_num=key_cont;//dis=key_cont;
  146. key_cont=0;
  147. read_one=1;
  148. //不清除會(huì)導(dǎo)致第二次單按時(shí)觸發(fā)長(zhǎng)按累計(jì)
  149. }else if(read_one==1){read_one=0;}long_flag=0;
  150. }
  151. ///

  152. }
  153. //////長(zhǎng)短按鍵處理end///////

  154. void key_scan()
  155. {
  156. push_scan();
  157. se_flag=key_long_flag; key_long_flag=0; //設(shè)置鍵
  158. //if(key_num==1) {up_flag=1;key_num=0;}//加鍵
  159. //if(key_num==2) {dn_flag=1;key_num=0;}//減鍵
  160. //if(set_mode==0&&key_num==3) {thr_flag=1;key_num=0;}//按三次

  161. //----設(shè)置鍵-----//

  162. //---------------------//
  163. if(se_flag&&set_sw_flag==0)  //長(zhǎng)按處理分別進(jìn)入時(shí)分﹑年﹑月日的校正
  164. {
  165. set_mode++;
  166. if(set_mode>7)set_mode=0;
  167. set_sw_flag=1;
  168. se_flag=0;
  169. } else if(se_flag==0&&set_sw_flag==1) set_sw_flag=0;
  170. //---------------------//
  171. }
復(fù)制代碼

以上圖文的Word格式文檔下載(內(nèi)容和本網(wǎng)頁(yè)上的一模一樣,方便大家保存):
多功能按鍵.doc (598 KB, 下載次數(shù): 30)

評(píng)分

參與人數(shù) 1黑幣 +50 收起 理由
admin + 50 共享資料的黑幣獎(jiǎng)勵(lì)!

查看全部評(píng)分

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏5 分享淘帖 頂 踩
回復(fù)

使用道具 舉報(bào)

沙發(fā)
ID:297903 發(fā)表于 2022-2-5 10:17 | 只看該作者
視頻沒(méi)法上傳!
回復(fù)

使用道具 舉報(bào)

板凳
ID:46750 發(fā)表于 2022-2-6 12:26 | 只看該作者
樓主開源精神敬佩,方便分享整個(gè)工程嗎?
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表