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

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

QQ登錄

只需一步,快速開始

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

51單片機(jī)按鍵數(shù)碼管顯示 時(shí)間片輪轉(zhuǎn)+狀態(tài)機(jī) 源程序

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

  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存儲(chǔ)當(dāng)前被按下的按鍵鍵值,0為無按鍵

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

  15. //時(shí)間片為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. //時(shí)間片輪轉(zhuǎn)變量
  25. u32 TimeRef=0;




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

  36. /////////////////////////函數(shù)聲明/////////////////////////////////
  37. //讀按鍵鍵值
  38. u8 ReadKeyDat(void);
  39. //讀按鍵寄存器
  40. u8 ReadKeyReg(void);
  41. //中斷初始化函數(shù)
  42. void IsrInit(void);
  43. //數(shù)碼管顯示控制函數(shù)
  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. //數(shù)碼管顯示控制函數(shù)
  66. void SegDisplay(u16 num)
  67. {
  68.         u8 i=0;
  69.         if(SEG_STATE==0)//分割字符狀態(tài)
  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)//顯示狀態(tài)
  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)//延時(shí)等待狀態(tài)
  90.         {
  91.                 if(TimeRef >= SEG_DELAY)
  92.                 {
  93.                         //判斷是否為最后一次延時(shí)
  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)//第一次讀取狀態(tài)
  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)//延時(shí)狀態(tài)
  117.         {
  118.                 if(TimeRef >= KEY_DELAY)
  119.                 {
  120.                         KEY_STATE=2;
  121.                 }
  122.         }
  123.         if(KEY_STATE == 2)//第二次讀取狀態(tài)
  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. //中斷初始化函數(shù)
  161. void IsrInit(void)
  162. {
  163.         EA=1;
  164.         
  165.         //使能定時(shí)器中斷并開啟定時(shí)器
  166. //        ET0=1;
  167. //        TR0=1;
  168.         //ET1=1;
  169.         //使能兩個(gè)外部中斷并將其設(shè)定為跳沿觸發(fā)
  170. //        EX0=1;
  171. //        IT0=1;
  172. //        EX1=1;
  173. //        IT1=1;
  174.         //定時(shí)器0,方式2,計(jì)數(shù)器
  175.         TMOD|=0x02;
  176.         TH0=0x8d;//125us 中斷一次
  177.         TL0=0x8d;
  178.         ET0=1;
  179.         TR0=1;
  180. //        //使用定時(shí)器1,方式2,計(jì)數(shù)器
  181. //        TMOD|=0x20;
  182. //        TH1=0x8d;//125us 中斷一次
  183. //        TL1=0x8d;
  184. }
  185. //定時(shí)器0,提供基礎(chǔ)時(shí)鐘125us中斷1次
  186. //////////////////////////統(tǒng)一時(shí)間完成標(biāo)志位可能沒有意義//////////////////////////////////////
  187. int Tim0Isr() interrupt 1 using 1
  188. {
  189.         TimeRef++;        
  190. //        P0=SEG7[TimeRef/100%10];//[];
  191. //        P2=0xfe;
  192. }
復(fù)制代碼
Keil代碼下載: 1、按鍵檢測控制數(shù)碼管顯示.7z (16.25 KB, 下載次數(shù): 119)

評(píng)分

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

查看全部評(píng)分

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

使用道具 舉報(bào)

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

使用道具 舉報(bào)

板凳
ID:70035 發(fā)表于 2021-11-23 11:06 | 只看該作者
結(jié)構(gòu)清晰!贊!
回復(fù)

使用道具 舉報(bào)

地板
ID:189875 發(fā)表于 2022-4-9 16:58 | 只看該作者
學(xué)習(xí)受教了,很有用
回復(fù)

使用道具 舉報(bào)

5#
ID:914666 發(fā)表于 2022-8-3 15:19 | 只看該作者
51黑有你更精彩,學(xué)習(xí)使人進(jìn)步
回復(fù)

使用道具 舉報(bào)

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

使用道具 舉報(bào)

7#
ID:88154 發(fā)表于 2022-10-13 10:42 | 只看該作者
學(xué)習(xí)使人進(jìn)步
回復(fù)

使用道具 舉報(bào)

8#
ID:34149 發(fā)表于 2022-10-16 15:18 | 只看該作者
動(dòng)態(tài)掃描,最近在學(xué)習(xí)595驅(qū)動(dòng)。謝謝分享
回復(fù)

使用道具 舉報(bào)

9#
ID:933601 發(fā)表于 2022-10-17 06:40 | 只看該作者
時(shí)間片輪轉(zhuǎn)+狀態(tài)機(jī),精彩
回復(fù)

使用道具 舉報(bào)

10#
ID:46750 發(fā)表于 2022-10-18 13:11 | 只看該作者
時(shí)間片輪轉(zhuǎn)+狀態(tài)機(jī),精彩
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

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

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

快速回復(fù) 返回頂部 返回列表
主站蜘蛛池模板: a黄视频 | 羞羞视频免费在线观看 | 91精品国产综合久久香蕉麻豆 | 亚洲成人av| 精品日韩一区二区三区av动图 | 最新国产精品 | 久久人人爽人人爽 | 成人在线观看亚洲 | 国产高清精品一区二区三区 | 国产a视频| 久久久久99 | 亚洲精品在线免费观看视频 | 国产在线精品区 | 涩爱av一区二区三区 | 日本三级在线网站 | 国产一区二区三区四区 | 青青久在线视频 | 久久综合狠狠综合久久综合88 | 亚洲一区二区久久 | 国家一级黄色片 | 中国一级大黄大片 | 欧产日产国产精品视频 | 久久九九99| 欧美日韩一区二区视频在线观看 | 国产探花在线精品一区二区 | 久久久久国产一区二区三区 | 亚洲精品视频在线看 | 97精品国产97久久久久久免费 | 91大片 | 久草在线在线精品观看 | 91一区二区 | 国内精品免费久久久久软件老师 | 欧美日韩在线视频观看 | 国产精品亚洲片在线播放 | 99精品视频在线观看 | 欧美日韩精品久久久免费观看 | 天天色天天色 | 国产a区| 久久中文字幕在线 | 欧美一级在线观看 | www.一级毛片 |