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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

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

51單片機按鍵數碼管顯示 時間片輪轉+狀態機 源程序

  [復制鏈接]
跳轉到指定樓層
樓主
ID:750420 發表于 2021-11-17 11:00 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
前段時間看到了分層思想、時間片輪轉和狀態機的相關文章正好近期手上有一些小項目,于是就進行了一些嘗試。相關的概念就不在細說了,很多嵌入式的公眾號文章都有介紹過,下面只敘述下我開發的經歷幫助后來者少走彎路也是我個人的一個記錄。
我在看到講述相關思想的文章后在腦子里想著架構出一個相對比較完善的系統。
分層思想不用多說根據相應的軟硬件結構進行分層即可,其中的好處會在代碼復用時體現出來。
時間片輪轉思想在我個人實踐的過程中走了很多彎路,本人使用的硬件為清翔電子的最小系統板,在最開始進行開發時使用定時器的方式對固定延時變量(REF20MS等)進行相應的環形累加(if(REF20MS==0)REF20MS=NUM20MS)(NUM20MS為宏定義的定時器計數記錄到對應時間所需要的值)。然后當相應的變量計數完成后對相應的標志位進行計數。
在我最初的構想中,希望能夠完成一個多個需要相同的延時時間的任務對同一個標記位的檢測即可完成延時的效果,但是在實際實現過程中遇到了很多問題。
1、如何判定任務1完成了20ms延時(僅作為舉例),判定相應的延時時間的話需要對REF20MS的值進行記錄當該變量再一次到達記錄值時則說明完成20ms延時,這有一個問題就是定時器中斷的時間一定時比單片機主函數中運行的時間要慢的于是當該變量進行記錄時定時器未能及時對延時記錄變量進行增減從而導致沒有延時的現象,當然這種問題可以通過再增加一個記錄次數的標記位來解決但是還有更好的解決方式我下面會講。
2、如何多個任務同時標記并使用同一個延時變量,這個問題使用變量記錄加標記位的方式可以去解決但是結構復雜較為繁瑣。
在遇到上述問題后我改變了想法,使用一個u32位(u64更好但是51不支持u64)的變量(u32 TimeRef)作為統一的一個時間片(定時器125us中斷一次,足夠使用一周左右),對每個任務定義一個_DELAY變量(如按鍵:u32 KEY_DELAY) 在每次需要延時時KEY_DELAY=TimeRef+NUM_20MS;(NUM20MS為宏定義的定時器計數記錄到對應時間所需要的值),在使用狀態機的思想進行狀態轉移即可。能夠較為簡單的時間一些任務輪轉的功能,整體代碼理解起來也比較簡單。整體單片機代碼如下:
  1. #include<reg52.h>
  2. #include<intrins.h>
  3. //嘗試分層思想與時間片輪轉

  4. #define u8  unsigned char
  5. #define u16 unsigned int
  6. #define u32 unsigned long int
  7. //按鍵引腳映射
  8. sbit         KEY1=P3^5;
  9. sbit         KEY2=P3^4;
  10. sbit         KEY3=P3^3;
  11. sbit         KEY4=P3^2;
  12. sbit         LED1=P1^0;
  13. u8                 KEY_DAT=0;//按鍵寄存器按鍵為1存儲當前被按下的按鍵鍵值,0為無按鍵

  14. u8 SEG7[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};

  15. //時間片為125us
  16. #define NUM_1MS                 8
  17. #define NUM_2MS                 16
  18. #define NUM_5MS                        40
  19. #define NUM_20MS                 160
  20. #define NUM_100MS         800
  21. #define NUM_200MS         1600
  22. #define NUM_500MS         4000
  23. #define NUM_1000MS         8000

  24. //時間片輪轉變量
  25. u32 TimeRef=0;




  26. //任務延時變量
  27. //按鍵任務
  28. u32 KEY_DELAY                                =0;
  29. u8  KEY_STATE                                =0;
  30. u8         KEY_DATx                                =0;
  31. //顯示任務
  32. u32 SEG_DELAY                =0;
  33. u8  SEG_STATE                =0;//0位標記是否第一次進入
  34. u8         SEG_NUM[4]        ={0,0,0,0};
  35. u8         SEG_I                          =0;

  36. /////////////////////////函數聲明/////////////////////////////////
  37. //讀按鍵鍵值
  38. u8 ReadKeyDat(void);
  39. //讀按鍵寄存器
  40. u8 ReadKeyReg(void);
  41. //中斷初始化函數
  42. void IsrInit(void);
  43. //數碼管顯示控制函數
  44. void SegDisplay(u16 num);

  45. void main(void)
  46. {
  47.         u16 num=0;
  48.         u8 key=0;
  49.         IsrInit();
  50.         while(1)
  51.         {               
  52.                 SegDisplay(num);
  53.                 key = ReadKeyDat();
  54.                 if(key==1)
  55.                         num++;
  56.                 if(key==2)
  57.                         num--;
  58. //                if(key==3)
  59. //                        LED1=0;
  60. //                if(key==4)
  61. //                        LED1=1 ;
  62.         }
  63.         
  64. }
  65. //數碼管顯示控制函數
  66. void SegDisplay(u16 num)
  67. {
  68.         u8 i=0;
  69.         if(SEG_STATE==0)//分割字符狀態
  70.         {
  71.                 SEG_I=0;
  72.                 for(i=0;i<4;i++)
  73.                 {
  74.                         SEG_NUM[SEG_I++]=num%10;
  75.                         num=num/10;
  76.                 }
  77.                 SEG_STATE=1;
  78.                
  79.         }
  80.                           
  81.         if(SEG_STATE==1)//顯示狀態
  82.         {
  83.                 P0=SEG7[SEG_NUM[4-SEG_I]];//[];
  84.                 P2=~(0x01<<(SEG_I-1));
  85.                 SEG_I--;
  86.                 SEG_DELAY=TimeRef+NUM_5MS;
  87.                 SEG_STATE=2;
  88.         }

  89.         if(SEG_STATE==2)//延時等待狀態
  90.         {
  91.                 if(TimeRef >= SEG_DELAY)
  92.                 {
  93.                         //判斷是否為最后一次延時
  94.                         if(SEG_I==0)
  95.                                 SEG_STATE=0;
  96.                         else
  97.                                 SEG_STATE=1;
  98.                 }
  99.         }
  100.         
  101. }



  102. //讀按鍵鍵值
  103. u8 ReadKeyDat(void)
  104. {
  105.         ReadKeyReg();
  106.         if(KEY_STATE == 0)//第一次讀取狀態
  107.         {
  108.                 if(KEY_DAT!=0)//讀取到按鍵
  109.                 {
  110.                         KEY_DATx=KEY_DAT;
  111.                         KEY_DELAY=TimeRef+NUM_100MS;
  112.                         KEY_STATE=1;
  113.                 }
  114.         }
  115.         
  116.         if(KEY_STATE == 1)//延時狀態
  117.         {
  118.                 if(TimeRef >= KEY_DELAY)
  119.                 {
  120.                         KEY_STATE=2;
  121.                 }
  122.         }
  123.         if(KEY_STATE == 2)//第二次讀取狀態
  124.         {
  125.                 if(KEY_DATx == KEY_DAT)//讀取到按鍵
  126.                 {
  127.                         KEY_STATE=0;
  128.                         return KEY_DATx;
  129.                 }
  130.                 KEY_STATE=0;
  131.         }
  132.         return 0;
  133. }

  134. //讀按鍵寄存器
  135. u8 ReadKeyReg(void)
  136. {
  137.         if(KEY1==0)
  138.         {
  139.                 KEY_DAT=1;
  140.                 return 1;
  141.         }
  142.         if(KEY2==0)
  143.         {
  144.                 KEY_DAT=2;
  145.                 return 1;
  146.         }
  147.         if(KEY3==0)
  148.         {
  149.                 KEY_DAT=3;
  150.                 return 1;
  151.         }
  152.         if(KEY4==0)
  153.         {
  154.                 KEY_DAT=4;
  155.                 return 1;
  156.         }
  157.         KEY_DAT=0;
  158.         return 0;
  159. }

  160. //中斷初始化函數
  161. void IsrInit(void)
  162. {
  163.         EA=1;
  164.         
  165.         //使能定時器中斷并開啟定時器
  166. //        ET0=1;
  167. //        TR0=1;
  168.         //ET1=1;
  169.         //使能兩個外部中斷并將其設定為跳沿觸發
  170. //        EX0=1;
  171. //        IT0=1;
  172. //        EX1=1;
  173. //        IT1=1;
  174.         //定時器0,方式2,計數器
  175.         TMOD|=0x02;
  176.         TH0=0x8d;//125us 中斷一次
  177.         TL0=0x8d;
  178.         ET0=1;
  179.         TR0=1;
  180. //        //使用定時器1,方式2,計數器
  181. //        TMOD|=0x20;
  182. //        TH1=0x8d;//125us 中斷一次
  183. //        TL1=0x8d;
  184. }
  185. //定時器0,提供基礎時鐘125us中斷1次
  186. //////////////////////////統一時間完成標志位可能沒有意義//////////////////////////////////////
  187. int Tim0Isr() interrupt 1 using 1
  188. {
  189.         TimeRef++;        
  190. //        P0=SEG7[TimeRef/100%10];//[];
  191. //        P2=0xfe;
  192. }
復制代碼
Keil代碼下載: 1、按鍵檢測控制數碼管顯示.7z (16.25 KB, 下載次數: 119)

評分

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

查看全部評分

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

使用道具 舉報

沙發
ID:262 發表于 2021-11-18 06:01 | 只看該作者
好資料,51黑有你更精彩!!!
回復

使用道具 舉報

板凳
ID:70035 發表于 2021-11-23 11:06 | 只看該作者
結構清晰!贊!
回復

使用道具 舉報

地板
ID:189875 發表于 2022-4-9 16:58 | 只看該作者
學習受教了,很有用
回復

使用道具 舉報

5#
ID:914666 發表于 2022-8-3 15:19 | 只看該作者
51黑有你更精彩,學習使人進步
回復

使用道具 舉報

6#
ID:983641 發表于 2022-9-8 12:12 | 只看該作者
正對這方面感興趣。
回復

使用道具 舉報

7#
ID:88154 發表于 2022-10-13 10:42 | 只看該作者
學習使人進步
回復

使用道具 舉報

8#
ID:34149 發表于 2022-10-16 15:18 | 只看該作者
動態掃描,最近在學習595驅動。謝謝分享
回復

使用道具 舉報

9#
ID:933601 發表于 2022-10-17 06:40 | 只看該作者
時間片輪轉+狀態機,精彩
回復

使用道具 舉報

10#
ID:46750 發表于 2022-10-18 13:11 | 只看該作者
時間片輪轉+狀態機,精彩
回復

使用道具 舉報

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

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 99精品视频在线观看免费播放 | 国产日韩精品在线 | 精品国产一区二区三区久久狼黑人 | 91亚洲一区 | 日韩国产免费观看 | h在线看 | 一区二区三区精品在线视频 | 草草视频在线播放 | 亚洲免费一 | 成人在线中文字幕 | 国产一区二区在线免费 | 国产黄色av电影 | 91视频国产一区 | 婷婷国产一区二区三区 | 毛片免费看 | 中文字幕在线视频免费视频 | 成人国产在线视频 | 一级a性色生活片久久毛片 一级特黄a大片 | 久优草| 羞羞视频网站免费观看 | 久久久国产一区 | 成人午夜在线 | 亚洲国产欧美一区二区三区久久 | 欧美二三区| 欧洲精品码一区二区三区免费看 | 亚洲精品成人在线 | 日韩在线免费视频 | 欧美精品在线观看 | 欧美日韩国产精品一区二区 | 久久久免费观看视频 | www.日韩 | 一区二区三区视频在线观看 | 亚洲精品久久久一区二区三区 | 国产精品高潮呻吟久久aⅴ码 | 天天插天天射天天干 | av永久免费| 成人综合一区 | 手机av网| 一区二区三区视频在线观看 | 亚洲福利网站 | 大象视频一区二区 |