久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 1752|回復: 0
打印 上一主題 下一主題
收起左側

單片機單個按鍵狀態機編程控制5種不同LED閃法程序與仿真

[復制鏈接]
跳轉到指定樓層
樓主
LED流水燈堆疊設計,且按鍵不占用CPU時間,上電顯示第1功能,單個按鍵的單擊顯示第2種功能,單按第5次返回第1功能,任意功能長按2S以上返回第2功能.程序注釋全。附件包含程序源碼和PROTUSE仿真圖。

仿真原理圖如下(proteus仿真工程文件可到本帖附件中下載)


單片機源程序如下:
  1. /*****************************************************************************
  2. *名稱:頭文件,預定義。
  3. *功能:包含頭文件,預定義,端口定義
  4. ******************************************************************************/
  5. #include<reg51.h>             //包含 51 單片機寄存器定義的頭文件
  6. #define uchar unsigned char    //定義uchar可在函數中當unsign char使用,取值不超過255。
  7. #define uint unsigned int      //定義uint可在函數中當unsign int使用,取值不超過65535。
  8. sbit KEY=P1^0;             //定義按鍵KEY為P1.0
  9. #define LED P2            //定義LED為P2口
  10. #define KEY_STATE_0   0    //按鍵初始狀態
  11. #define KEY_STATE_1   1    //按鍵消抖
  12. #define KEY_STATE_2   2    //按鍵按下功能種類是單擊,雙擊還是長按
  13. #define KEY_STATE_3   3    //按鍵彈起

  14. #define SINGLE_KEY_TIME 3 //SINGLE_KEY_TIME*10MS = 30MS?判定單擊的時間長度,軟件消抖
  15. #define KEY_INTERVAL 30  //KEY_INTERVAL*10MS?= 300MS 判定雙擊的時間間隔
  16. #define LONG_KEY_TIME 200 //LONG_KEY_TIME*10MS? ?= 2S? ?判定長按的時間長度

  17. #define N_KEY   0   //按鍵沒動作
  18. #define S_KEY   1   //單擊
  19. #define L_KEY   2   //長按
  20. #define D_KEY   3  //雙擊
  21. uchar code Zuoyi[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};   //左流水數組,低電平導通
  22. uchar code Youyi[]={0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe};   //右流水數組,低電平導通
  23. uchar keySu=0;            // 定義按鍵功能狀態變量
  24. uchar key_val;           // 按鍵值
  25. uchar time_10ms_ok=0;  //10MS定時標志
  26. //define LongCount 100; //延時長按變量100X10MS=1S
  27. /******************************************************************************
  28. ***函數名稱: void delay_ms(uint x)
  29. ***函數功能: MS延時(按下按鍵時,可以跳出循環體)
  30. ***輸入:     無
  31. ***輸出:     無
  32. ******************************************************************************/
  33. /*******/
  34. void delay_ms(uint x)           // 延時函數,延時x MS,
  35. {
  36.       uint i;                //定義無符號字符型變量j值域為0-65536.
  37. uchar j;                          //定義無符號字符型變量i值域為0-255.
  38. if(KEY)              //如果按鍵為1時,則執行延時循環
  39. {
  40.             for(i=0;i<x;i++)  //  循環x遍   
  41. {
  42.         for(j=0;j<112;j++)       
  43.                  ;                //空語句等待一個機器周期
  44.              }
  45.       }
  46.       else               //如果按鍵按下則跳出循環  
  47.       return;
  48. }


  49. /******************************************************************************
  50. ***函數名稱: void move_l(void)
  51. ***函數功能: 左流水(P2口低位向高位流動跑馬)
  52. ***輸入:     無
  53. ***輸出:     無
  54. ******************************************************************************/
  55. /******/

  56. void move_l(void)                   //1.左流水函數
  57. {
  58. uchar b;                    //循環變量b
  59. while(1)                    //死循環
  60. {
  61.                   for(b=0;b<8;b++)     // 循環8遍           
  62. {
  63.                    LED=Zuoyi[b]; //調用左流水數組

  64.                    delay_ms(500);    //延時500MS
  65.                    if(KEY==0)        //如果有按鍵按下
  66.                          return;          //退出循環
  67.             }
  68.                   //if(KEY==0)            //此兩語句可以不用
  69.                       //return;
  70.      }
  71. }
  72. /******************************************************************************
  73. ***函數名稱: void move_r(void)
  74. ***函數功能: 右流水(P2口高位向低位流動跑馬)
  75. ***輸入:     無
  76. ***輸出:     無
  77. ******************************************************************************/
  78. /******/
  79. void move_r(void)                     //2.右流水函數
  80. {
  81. uchar b;                      //循環變量b
  82. while(1)                     //無限循環
  83.   {
  84.               for(b=0;b<8;b++)      // 循環8遍  
  85. {
  86.              LED=Youyi[b];    //調用右流水數組
  87. delay_ms(500);      //延時500MS
  88.        if(KEY==0)          //如果有按鍵按下則退出循環
  89.                    return;            //退出循環
  90.         }
  91.              //if(KEY==0)              //此兩語句可以不用
  92.                 //return;
  93. }
  94. }

  95. /******************************************************************************
  96. ***函數名稱: void flash(void)
  97. ***函數功能: 閃爍
  98. ***輸入:     無
  99. ***輸出:     無
  100. ******************************************************************************/
  101. /******/

  102. void flash(void)           //3.閃爍
  103. {
  104.    while(1)            //無限循環
  105.    {
  106.      LED=0x00;      //亮
  107. delay_ms(500);   //延時500MS
  108.        LED=0xff;      //滅
  109. delay_ms(500);  //延時500MS(毫秒)

  110. if(KEY==0)     //如果有按鍵按下則退出循環
  111.               return;        //退出循環
  112.    }
  113. }

  114. /******************************************************************************
  115. ***函數名稱: void Di_zeng1 (void)
  116. ***函數功能:.左遞增右遞減,,右遞增左遞減
  117. ***輸入:     無
  118. ***輸出:     無
  119. ******************************************************************************/
  120. /******/
  121. void Di_zeng1 (void)    //4.左遞增右遞減,,右遞增左遞減
  122. {
  123. while(1)
  124.         {
  125.       uchar m;     //循環變量
  126. uchar n=0;   //中間變量
  127. uchar n1=0;  //中間變量
  128. uchar n2=0;  //中間變量
  129. uchar n3=0;  //中間變量

  130.       for(m=0;m<8;m++)           //左遞增,循環8位
  131.         {
  132.            n +=(0x01<<m);       //  1左移m位再賦值給n
  133.                          LED=~n;            //n取反后點亮LED燈
  134.            delay_ms(500);     //延時500毫秒
  135.            if(KEY==0)        //如果按鍵按下
  136.                  return;          //退出循環
  137.                   }
  138.   
  139.         for(m=0;m<8;m++)      //右遞減,循環8位
  140.         {
  141.             n1 +=(0x80>>m);    // 1右移m位再賦值給n1
  142. LED=n1;           //n1取反后點亮LED燈
  143.             delay_ms(500);     //延時500毫秒

  144.             if(KEY==0)    //如果按鍵按下
  145.                   return;      //退出循環
  146. }
  147.                        

  148. for(m=0;m<8;m++)  //右遞增
  149. {
  150.       n2 +=(0x80>>m);
  151.             LED=~n2;
  152.       delay_ms(500);
  153.       if(KEY==0)
  154.             return;                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
  155.   }
  156. for(m=0;m<8;m++)     //左遞減
  157. {
  158.      n3=n3+(0x01<<m);
  159.            LED=n3;
  160.      delay_ms(500);
  161.      if(KEY==0)
  162.            return;
  163.   }
  164.          //if(KEY==0)       //此兩語句可以不用
  165.                   //return;
  166. }
  167. }

  168. /******************************************************************************
  169. ***函數名稱: void Di_zeng2 (void)
  170. ***函數功能:左遞增左遞減,,右遞增右遞減
  171. ***輸入:     無
  172. ***輸出:     無
  173. ******************************************************************************/
  174. /******/
  175. void Di_zeng2 (void)    //5.左遞增左遞減,,右遞增右遞減
  176. {
  177. while(1)
  178.         {
  179.       uchar m,n=0;
  180.       uchar n1=0;
  181.                 uchar n2=0;
  182.       uchar n3=0;
  183.       for(m=0;m<8;m++)   //左遞增
  184.         {
  185.            n=n+(0x01<<m);
  186.                          LED=~n;
  187.            delay_ms(500);
  188.            if(KEY==0)
  189.                  return;
  190.                   }
  191.   
  192.         for(m=0;m<8;m++)//左遞減
  193.         {
  194.             n1 +=(0x01<<m);
  195. LED=n1;
  196.             delay_ms(500);
  197.             if(KEY==0)
  198.                   return;
  199.         }
  200.                        

  201. for(m=0;m<8;m++)  //右遞增
  202. {
  203.       n2 +=(0x80>>m);
  204.             LED=~n2;
  205.        delay_ms(500);
  206.       if(KEY==0)
  207.             return;                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
  208.   }
  209. for(m=0;m<8;m++)     //右遞減
  210. {
  211.      n3=n3+(0x80>>m);
  212.            LED=n3;
  213.      delay_ms(500);
  214.      if(KEY==0)
  215.            return;
  216.   }
  217.        //if(KEY==0)       //此兩語句可以不用
  218.                 //return;
  219. }
  220. }


  221. /******************************************************************************
  222. ***函數名稱: uchar key_read(void)
  223. ***函數功能: 鍵盤掃描函數(按鍵狀態機方式)
  224. ***輸入:     無
  225. ***輸出:     返回值。單擊,長按,雙擊
  226. ******************************************************************************/
  227. /******/
  228. uchar key_read(void)
  229. {
  230. static uchar key_state = 0;    //按鍵初始狀態
  231. static uint key_time =0;      //按鍵時間間隔計時變量
  232. uchar key_press;            //按鍵是按下還是抬起變量
  233. uchar key_return;           //按鍵函數返回
  234. key_return=N_KEY;         //清除返回按鍵值
  235. key_press=KEY;           //讀取當前鍵值
  236. switch(key_state)
  237. {
  238. case KEY_STATE_0:  //按鍵初始狀態0:判斷有無按鍵按下
  239. if(!key_press)       //有按鍵按下
  240. {
  241. key_time=0;     //一次10ms,時間間隔計數器清0
  242. key_state=KEY_STATE_1;//然后進入轉到按鍵確認態1
  243. }
  244. break;
  245. case KEY_STATE_1:
  246. //按鍵確認狀態1:軟件消抖(確定按鍵是否有效,而不是誤觸)
  247. //按鍵有效的定義:按鍵持續按下超過設定的消抖時間
  248. if(!key_press)      //按鍵仍然按下
  249. {
  250. key_time++;     //一次10ms,時間間隔變量加1
  251.              //消抖時間為SINGLE_KEY_TIME*10MS=30MS
  252. if(key_time>=SINGLE_KEY_TIME) //如果大于消抖時間              
  253. {
  254. key_state = KEY_STATE_2;//按鍵仍然處于按下狀態
  255. }
  256. //如果按鍵時間超過消抖時間,即判定為按下的按鍵有效。
  257. //按鍵有效包括兩種:單擊或長按,繼續判定為那種有效按鍵
  258. }
  259. else //按鍵時間沒有超過,判定為誤觸,按鍵無效,返回狀態0
  260. {
  261. key_state = KEY_STATE_0;   //返回初始狀態
  262.             }
  263. break;          //跳出
  264.    case KEY_STATE_2:  //按鍵狀態2:判定按鍵有效的種類:是單擊,還是長按
  265. if(key_press)    //如果按鍵在設定的長按時間內釋放,則判定為單擊
  266. {
  267. key_time++; //一次10ms,時間間隔變量加1
  268. //按鍵彈起(高電平)后計時,計時大于雙擊30*10MS時間小于長按時間則為單擊
  269. if((key_time >=KEY_INTERVAL)&&( key_time < LONG_KEY_TIME))
  270. {
  271. key_return = S_KEY;         //返回有效按鍵值: 單擊
  272. key_time=0;                 //時間間隔變量清0
  273. key_state = KEY_STATE_0;   //返回按鍵狀態0繼續等待按鍵
  274.              }
  275.                  else //否則在此時間段為低電平則為雙擊
  276.                  {
  277. key_return = D_KEY;         //返回有效按鍵值: 雙擊
  278. key_time=0;               //時間間隔變量清0
  279. key_state = KEY_STATE_0;   //返回按鍵狀態0繼續等待按鍵
  280. }
  281.               }
  282. else    // 如果一直按下,則計算按下的時間
  283. {
  284. key_time++;
  285. //如果按鍵繼續按下時間超過設定的長按時間
  286. //(LONG_KEY_TIME*10ms=300*10ms=3000ms)則判定為長按

  287. if(key_time >= LONG_KEY_TIME)  
  288. {
  289. key_return = L_KEY;         //返回有效鍵值:長按
  290. key_time=0;                //時間間隔變量清0
  291. key_state = KEY_STATE_3;   //去狀態3,等待按鍵釋放
  292. }                              
  293. }
  294. break;
  295. case KEY_STATE_3:    //狀態3為長按按鍵釋放抬起
  296. if(key_press)  //如果按鍵為1,釋放狀態         
  297. {
  298. key_state = KEY_STATE_0; //按鍵彈起,進行下一次按鍵的判定
  299. }
  300. break;
  301. //特殊情況:key_state 是其他值的情況,清0key_state ,這種情況一般出現
  302. //在沒有初始key_state,第一次執行這個函數的時候
  303. default: key_state = KEY_STATE_0;
  304. break;

  305. }
  306. return key_return; //返回按鍵值
  307. }


  308. /******************************************************************************
  309. ***函數名稱: void Timer0Init()   
  310. ***函數功能: 定時器0初始化
  311. ***輸入:     無
  312. ***輸出:     無
  313. ******************************************************************************/
  314. /******/
  315. void Timer0Init()                  //10毫秒@12.00MHZ
  316. {
  317.       TMOD=0x01;            //設置定時器工作方式1
  318.       TH0=(65536-10000)/256;
  319.       TL0=(65536-10000)%256; //定時器0預設初值10000US=10MS
  320.       TR0=0;             //關閉定時器0,當按鍵按下才開啟定時器0,計算按下的時長
  321.       EA=1;             //開總中斷
  322.       ET0=1;            //允許定時器0中斷
  323.       TR0=1;           //啟動定時器0
  324. }


  325. /******************************************************************************
  326. ***函數名稱: void Timer0_Isr() interrupt 1
  327. ***函數功能: 定時器0中斷函數
  328. ***輸入:     無
  329. ***輸出:     無
  330. ******************************************************************************/
  331. /******/
  332. void Timer0_Isr() interrupt 1    //定時器0中斷服務函數
  333. {
  334.      TH0=(65536-10000)/256;    //預設初值50MS
  335.      TL0=(65536-10000)%256;   //預設初值50MS
  336.      time_10ms_ok=1;         //10毫秒到標志
  337. }


  338. /**********主程序*******/
  339. void main(void)
  340. {
  341. KEY=0x01;              //P1.0作為輸入口前必須輸出高電平
  342. Timer0Init();           //調用定時器0初始化函數
  343. while(1)
  344. {
  345.          if(time_10ms_ok)            //10MS定時時間到
  346.          {
  347.               time_10ms_ok=0;      //賦值0,10MS查詢一次按鍵狀態
  348. key_val=key_read();    //讀取按鍵的返回值
  349. if(key_val==S_KEY)     //如果是單擊
  350. {
  351.           keySu++;       //變量按鍵數加1
  352.           if(keySu==5)    //如果加到5
  353.           keySu=0;       //重新賦值0
  354. }
  355.       if(key_val==L_KEY)     //如果是長按
  356. {
  357.           keySu=1;       //按鍵數為1
  358. }
  359.         if(key_val==D_KEY)   //如果是雙擊
  360. {
  361.              keySu=2;      //按鍵數為2
  362. }

  363. switch(keySu)   //5路分支
  364. {
  365.         case 0: move_l();break;     //當按鍵數為0,執行左流水功能
  366. case 1: move_r();break;    //當按鍵數為1,執行右流水功能
  367. case 2: flash(); break;     //當按鍵數為2,執行閃爍功能
  368. case 3: Di_zeng1(); break; //當按鍵數為3執行左遞增右遞減,右遞增左遞減功能
  369. case 4: Di_zeng2(); break;//當按鍵數為4執行左遞增左遞減,右遞增右遞減功能
  370.         default : break;        //默認跳出
  371. }
  372. }
  373. }
  374. }
復制代碼

Keil代碼與Proteus8.8仿真下載:
單個按鍵狀態機編程控制5種功能.7z (75.63 KB, 下載次數: 38)


評分

參與人數 1黑幣 +50 收起 理由
admin + 50 共享資料的黑幣獎勵!

查看全部評分

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

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 午夜视频免费网站 | 在线观看视频你懂得 | 国产精品视频网站 | 污污免费网站 | 亚洲精品99 | 国产精品久久久久久久毛片 | 久久久www成人免费无遮挡大片 | 欧美xxxⅹ性欧美大片 | 欧美亚洲国产成人 | 亚洲视频免费在线播放 | 精品欧美一区二区三区精品久久 | 国产视频一区二区 | 国产中文字幕网 | 国产精品亚洲精品久久 | 国产xxx在线观看 | www.yw193.com| 一区二区三区回区在观看免费视频 | 凹凸日日摸日日碰夜夜 | 日本中出视频 | 国产亚洲高清视频 | 国产成人精品午夜 | 亚洲精品乱码久久久久久久久 | 久久亚洲视频 | 91精品国产91久久久久久最新 | 欧美一卡二卡在线观看 | 日韩资源| 成人网视频 | 国产一区二区免费 | 国产在线一区二区三区 | 在线视频成人 | 国产精品成人国产乱 | 999精品网 | 黄色国产大片 | 精产国产伦理一二三区 | 亚洲免费视频播放 | 日韩欧美一区二区三区 | 成人免费视频一区二区 | 久草免费在线视频 | 欧美日韩视频 | 日韩欧美三级电影在线观看 | 欧美精品一区二区三区四区五区 |