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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

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

小白請教大神們幾個51單片機中斷的問題,請指點,謝謝!

[復制鏈接]
跳轉到指定樓層
樓主
20黑幣
小白請教大神們幾個51中斷的問題,請指點,謝謝!
我想利用89c51測量兩個按鍵按下先后時間間隔功能。先按啟動,再按停止然后數碼管顯示出兩者先后間隔時間,如果先按停止,不做處理。必須先按啟動,然后再按停止才能顯示時間,也就是啟動和停止有先后順序,順序后了不處理。利用中斷1和中斷0在下降沿觸發方式和定時器0方式2去實現,用prutues仿真,按一下啟動,再按一下停止,可以正常顯示時間。仿真時發現幾個問題。
1.按一下啟動,再按一下啟動,IE1就會置1,(為什么?)再按一下停止,顯示時間,但T0不停止,仍然計時,需再按一下停止,定時器T0停止,顯示時間。我想實現有功能是按下啟動,定時器啟動,再按啟動沒有反應,按下停止,停止計時,顯示時間,再按下停止或沒按啟動先按停止,沒有反應。但是現在如果按兩下啟動同,必須按兩下停止才能停止定時器。
2.按一下啟動,再按一下停止,顯示時間,但再按一下停止,TE0就會置1,(為什么?)此時按一下啟動,顯示就會變成00,定時器也不啟動,再按下啟動,定時器才會啟動。
請問大神們,出現這種情況是什么原因,如果不改變中斷1和中斷0在下降沿觸發方式和定時器0方式2,如何解決,源文件附后,請大神們指點。

新手小白一枚,送點黑幣意思一下,請大神們不吝賜教,謝謝!用protues仿真,所以按鍵沒有去抖,應該不是沒去抖的問題。



  1. #include<reg51.h>
  2. #define uchar unsigned char
  3. #define uint unsigned int

  4. uint Time=0;
  5. uint Time_Count=0;

  6. uchar Duan[] = {0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0xFF,0x7f};//段碼0-9+全暗+"."

  7. uchar Wei[4]={0x08,0x04,0x02,0x01};   //位的控制端        (仿真)

  8. uchar Time_Buffer[]={0,0,0,0};                                        //時間緩存

  9. void delayms(uint x)                //延時函數
  10. {
  11.         uint i,j;
  12.         for(i = x; i > 0; i --)
  13.                 for(j = 125; j > 0; j --);               
  14. }

  15. void Show_Time()                                //數碼管動態掃描顯示
  16. {
  17.                 uchar i;
  18.         /*****************數據轉換*****************************/
  19.         
  20.         
  21.                 Time_Buffer[0] = Time / 1000;                                //千位
  22.                 Time_Buffer[1] = Time % 1000 / 100;        //百位
  23.                 Time_Buffer[2] = Time % 100 /10;                //十位
  24.                 Time_Buffer[3] = Time % 10;                                        //個位

  25.                 if(Time_Buffer[0] == 0)        
  26.                         {        
  27.                                 Time_Buffer[0] = 10;
  28.                                 if(Time_Buffer[1] == 0)
  29.                                 {        
  30.                                         Time_Buffer[1] = 10;
  31.                                 }
  32.                         }               
  33.                
  34.                 for(i = 0;i < 4;i ++)
  35.                 {
  36.                         P0 = 0xFF;
  37.                         P1 = Wei[i];
  38.                         P0 = Duan[Time_Buffer[i]];
  39.                         delayms(2);
  40.                 }
  41. }

  42. /*************************************************************************
  43.                                 主函數        
  44. **************************************************************************/
  45. void main()
  46. {
  47.                 EX1=1;
  48.                 EX0=1;
  49.                 IT0=1;//低電平有效 下降沿有效
  50.                 IT1=1;
  51.                 EA=1;                                
  52.                
  53.                 TMOD=0x02;                //設置為自動重載方式
  54.                 TH0=0x9c;                        //設置為100us的計數
  55.                 TL0=0x9c;
  56.                 TR0=0;
  57.                 Time=1898;
  58.                 while(1)
  59.                 {
  60.                         Show_Time();
  61.                 }
  62. }


  63. void Start_ExInt1()interrupt 2
  64. {
  65.                 TR0=1;
  66.                 EX1=0;
  67.                 ET0=1;               
  68.                 EX0=1;
  69. }

  70. void Timer_T0() interrupt 1
  71. {
  72.                 Time_Count++;

  73.                 EX0=1;
  74.                 if ( Time_Count==9999) //計時范圍0-9999
  75.                 {
  76.                          Time_Count=0;
  77.                 }
  78. }
  79. void Stop_Int0() interrupt 0
  80. {
  81.                 TR0=0;
  82.                 Time= Time_Count;
  83.                 Time_Count=0;
  84.                
  85.                 EX1=1;
  86.                 EX0=0;
  87.                 ET0=0;
  88. }
復制代碼


KEY1-2.rar (62.48 KB, 下載次數: 4)


未按鍵時.png (50.34 KB, 下載次數: 131)

未按鍵時.png
分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復

使用道具 舉報

沙發
ID:383215 發表于 2020-6-7 23:51 | 只看該作者
你的程序根本不可能實現你想要的功能,主要原因是按鍵去抖動你沒有解決,你只有穩定得到鍵值才有可能測量出兩個按鍵的時間,兩個按鍵的時間大于0.5秒以上,不需要中斷,一個定時器足夠用了,初學單片機編程,不能濫用中斷,中斷用多的情況下問題更多,要想得到更高的精度,除非用RS觸發器搞個硬件去抖動,你現在的程序也許可以用,你這個程序,看似簡單,編好了還是不容易的,我不需要黑幣,你自己留著吧,這個論壇我需要的資料不太多。
回復

使用道具 舉報

板凳
ID:123289 發表于 2020-6-8 11:09 | 只看該作者
按鍵必須去抖動,方式很多,各有其特點。
你的命題對按鍵的先后次序有要求,所以要仔細規劃一下,去抖動的方式。
原則:按鍵按下時是有彈動的,即按一下,不只一下,短時內是多下。
你只認第一下,而短時內的其它下不認可就行了。
你是用中斷識別按鍵的,就在中斷里識別;
你是掃鍵識別的,就在掃鍵時識別。辦法自己想。
祝你成功。
回復

使用道具 舉報

地板
ID:104797 發表于 2020-6-8 22:31 | 只看該作者
謝謝兩位大神的指點。
我只是想要地protuse中仿真,不需要在硬件上實現(只是為了學習單片機,想實現這個功能)請問也需要去抖動嗎?
void Start_ExInt1()interrupt 2
{
                TR0=1;
                EX1=0;
                ET0=1;               
                EX0=1;
}
這段中斷代碼中,關斷了INT1,為什么再按一下IE1為什么會置1?如果不想讓它置位應該怎么做?用這種方法關關閉和打開中斷可以不?還有中斷和掃描哪種方法更可靠的采集到啟動和停止按鍵的信號?剛入手,所以很多細節問題沒弄明白。謝謝各位大神們。
回復

使用道具 舉報

5#
ID:383215 發表于 2020-6-8 23:57 | 只看該作者
IE還受IT影響,這個不是關鍵,關鍵之關鍵就是你必須得到穩定鍵值,我從來沒有搞過protuse仿真,我估計protuse仿真不太可能把按鍵之類的元器件真實仿真出來,不管什么單片機,效率最高的編程方式是實驗板+仿真器+示波器,沒有這些東西,編程效率太低太低了。
回復

使用道具 舉報

6#
ID:104797 發表于 2020-6-9 06:06 來自手機 | 只看該作者
想明白了IE置1的問題,但是沒想出怎么解決。
回復

使用道具 舉報

7#
ID:213173 發表于 2020-6-9 10:22 | 只看該作者
lhpm641 發表于 2020-6-9 06:06
想明白了IE置1的問題,但是沒想出怎么解決。

樓主想要完成上述預想的功能沒必要寫這么復雜,只要把邏輯關系捋清,很容易實現。不論仿真或實物也完全不需要按鍵消抖。給你改好了,你試試。

  1. #include<reg51.h>
  2. #define uchar unsigned char
  3. #define uint unsigned int
  4. uchar Duan[] = {//共陽數碼管段碼"0~f-. "
  5. 0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,
  6. 0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e,0xbf,0x7f,0xFF};
  7. uchar Wei[4]={0x01,0x02,0x04,0x08};   //位的控制端        (仿真)
  8. uchar Time_Buffer[4];  //時間緩存
  9. uint  Time=0;
  10. uint  Time_Count=0;
  11. uchar Cnt100us=0;
  12. bit   flag=0;
  13. /*
  14. void delayms(uint x)                //延時函數
  15. {
  16.         uint i,j;
  17.         for(i = x; i > 0; i --)
  18.                 for(j = 125; j > 0; j --);
  19. }*/

  20. void Show_Time() //數碼管動態掃描顯示
  21. {
  22.         uchar i;
  23.         uint  j;
  24.         static uchar k=0;

  25.         /*****************數據分解*****************************/
  26.         if(flag==0)//判斷啟動標志復位 處理數據
  27.         {
  28.                 j=Time;       
  29.                 for(i=4;i>0;i--)
  30.                 {
  31.                         Time_Buffer[i-1]=Duan[j%10];//由低位到高位保存
  32.                         j/=10;
  33.                 }
  34.         }
  35.         else       //等待計時結束
  36.         {
  37.                 for(i=4;i>0;i--)
  38.                 {
  39.                         Time_Buffer[i-1]=0xbf;//全部'-'
  40.                 }
  41.         }
  42.         P0 = 0xFF;
  43.         P1 = Wei[k];
  44.         if(k==0)P0=Time_Buffer[k]&0x7f;//加小數點
  45.         else P0=Time_Buffer[k];
  46.         k++;k%=4;
  47. }

  48. /******************
  49.        主函數        
  50. ******************/
  51. void main()
  52. {
  53.         IT0 = 1;//下降沿觸發
  54.         IT1 = 1;
  55.         EX0 = 1;
  56.         EX1 = 1;
  57.         EA  = 1;  
  58.        
  59.         TMOD=0x02; //設置為自動重載方式
  60.         TH0=0x9c;  //設置為100us的計數
  61.         TL0=0x9c;
  62.         ET0=1;
  63.         TR0=0;
  64.         while(1)
  65.         {
  66.                 Show_Time();
  67.         }
  68. }

  69. void Timer_T0() interrupt 1
  70. {
  71.         if(++Cnt100us>=10)       //1ms
  72.         {
  73.                 Cnt100us=0;
  74.                 if(++Time_Count>9999) //計時范圍0-9999
  75.                         Time_Count=0;      //10s
  76.         }
  77. }
  78. void Stop_Int0() interrupt 0
  79. {
  80.         if(TR0==0)       //與INT1互鎖
  81.         {
  82.                 flag=1;                  //啟動標志
  83.                 Cnt100us=0;   //初始值清0
  84.                 Time_Count=0; //初始值清0
  85.                 TR0=1;                  //開始計時
  86.         }
  87. }

  88. void Start_ExInt1()interrupt 2
  89. {
  90.         if(flag)         //判斷啟動狀態 與INT0互鎖
  91.         {
  92.                 TR0=0;        //停止計時
  93.                 flag=0;             //啟動標志復位
  94.                 Time=Time_Count;//讀取計數值
  95.         }
  96. }
復制代碼



回復

使用道具 舉報

8#
ID:383215 發表于 2020-6-9 17:31 | 只看該作者



笑話啊!好好看看吧,這是我用示波器捕捉的一個按鍵開關由高電平按鍵之后變為低電平的波形,這是實實際際測量出來的波形,我的示波器檔次太低,我又用了一個質量很好的按鈕開關,看起來抖動期才有300多微秒,只有幾次抖動,實際上不止這些,質量差的按鍵開關抖動期至少幾毫秒,抖動次數幾十次,我編下來的程序,幾十毫秒消除抖動的程序最好用,也最可靠,樓主看懂這個波形就知道為什么程序不可能編成功了,樓主只有踏踏實實的用硬件仿真,可以測試出不同按鍵的抖動期和抖動次數,并且找到去除抖動的編程方法,得到穩定的鍵值,接下來的編程就是小菜一碟了,我看了這個論壇的一些程序,能得到穩定的鍵值的程序并不多,不管是一個按鈕還是多個按鈕,編程方法都是一模一樣的,無非就是讀鍵值、去抖動、然后得到穩定鍵值,我說的這些才是學習單片機編程的捷徑,如果樓主抱著protuse仿真不放,再聽信一些人說的連去抖動都不用就能編出這個程序,那就是自己哄哄自己玩玩而已了,protuse不可能模擬出實際的按鍵開關抖動,protuse不可能把樓主的程序編好,就算可以編出來,也是毫無意義,還是自己哄自己。
回復

使用道具 舉報

9#
ID:213173 發表于 2020-6-10 07:45 | 只看該作者
任何機械開關切換時都會發生抖動,這是客觀存在的事實。按鍵沒有任何操作的情況下絕對不會發生抖動,只要發生抖動必然是有操作。如果認為在任何條件下必須對按鍵抖動做處理,其認識和應對方法還局限在教科書的層面。實踐是檢驗真理的唯一標準。
回復

使用道具 舉報

10#
ID:383215 發表于 2020-6-10 14:47 | 只看該作者
wulin 發表于 2020-6-10 07:45
任何機械開關切換時都會發生抖動,這是客觀存在的事實。按鍵沒有任何操作的情況下絕對不會發生抖動,只要發 ...

你說的非常正確,我的單片機程序,只要有按鍵,就是“在任何條件下必須對按鍵抖動做處理”,很早以前我就把按鍵去抖動程序編的非常穩定了,包括單個、多個、交叉矩陣、串行的按鍵去抖動。像樓主的程序,按鍵去抖動不需要任何延時程序,也不需要定時中斷,就用查詢的方法去抖動,我已經說的很清楚了,任何按鍵去抖動就是讀鍵值、去抖動、得到穩定鍵值,再說明白點,就是連續讀鍵值達到某個次數都是離鍵值,只要一次不為離鍵都不算離鍵,連續讀鍵值達到某個次數都是按鍵值,只要一次不為按鍵都不算按鍵,用這個方法,就能得到穩定鍵值,包括按下動作、彈開動作、單擊動作、雙擊動作、三擊動作、以及各種組合動作,都很容易編出來,至于兩個按鍵的時間,用一個定時器中斷就能判斷出來。需要更高精度,可以用RS觸發器做成硬件按鍵去抖動,單片機程序就不用編鍵盤去抖動的程序了,就能做到最高精度。
我編的單片機程序,不在乎有多復雜,只在乎占用CPU時間,占用CPU時間越短的程序,編程質量越高,我編的鍵盤去抖動程序很簡單,就算“在任何條件下必須對按鍵抖動做處理”,其實占用CPU時間很短。“在任何條件下必須對按鍵抖動做處理”,是按鍵動作程序最基本的要求,與任何一本教科書沒有關系。你說的實踐是檢驗真理的唯一標準,絕對正確,用protuse軟件仿真,不是實踐,僅僅是理論上的一個軟件模擬而已,樓主的這個程序,用我說的查詢去抖動的方法編程,protuse軟件估計可以模擬出來,但是,與實際的按鍵抖動肯定有差異,你們應該用硬件檢驗成功的程序,再用protuse軟件模擬仿真試試,就知道protuse軟件模擬仿真到底有多少價值了。樓主的這個程序,用硬件測試,花不了幾個錢,一個51單片機最小系統板,數碼管用1602液晶代替,再接兩個按鍵開關就夠了。我的51、AVR、STM32實驗板都是自制,基本夠我用了,仿真器和示波器是必須的,沒有這兩樣東西,我寧愿不編程序,因為編程效率實在太低了。
回復

使用道具 舉報

11#
ID:104797 發表于 2020-6-10 21:01 | 只看該作者
感謝大神們的指點,經驗寶貴,多謝指教。剛入手,看來我要多和實際聯系起來,還有很長的路要走。剛入手了一塊試驗板,以后請大神們多傳授點經驗。
回復

使用道具 舉報

12#
ID:213173 發表于 2020-6-11 07:55 | 只看該作者
kmsj 發表于 2020-6-10 14:47
你說的非常正確,我的單片機程序,只要有按鍵,就是“在任何條件下必須對按鍵抖動做處理”,很早以前我就 ...

與您這樣有思想,有經驗,非人云亦云的壇友交流非常有益。在7樓回復中用protuse軟件仿真,當然不能算是實踐。這只不過是按樓主意圖用樓主容易看明白方式理解程序而已。但為樓主提供的修改過的程序絕對經得住實物驗證。事實也是經實物驗證過是穩定可靠的。一般在實際應用中開關信號都是在主循環中查詢處理,滯后幾十毫秒響應無所謂。而必須用外部中斷處理的事件則要求及時響應(濫用外部中斷除外),滯后幾十毫秒響應就顯得很漫長。其實從來沒有用protuse軟件設計過產品,只是玩玩而已。實際開發產品都是用實驗板前期實驗,無誤后少量定制PCB打樣機。經48小時拷機,EMC、高/低溫及振動試驗。最后(往往不會一次通過)才能投入批量生產。若發生大批量召回事件是要讓老板破產的。
回復

使用道具 舉報

13#
ID:383215 發表于 2020-6-11 15:53 | 只看該作者
wulin 發表于 2020-6-11 07:55
與您這樣有思想,有經驗,非人云亦云的壇友交流非常有益。在7樓回復中用protuse軟件仿真,當然不能算是實 ...

那就奇怪了,本論壇用protuse軟件仿真的人,為什么那么多的問題解決不了?到處都有把程序大段大段的發上來讓大家幫著解決的人,我認為這是浪費自己的時間、浪費別人的時間、浪費論壇資源,我看這些程序,只要有硬件仿真器,只要可以設置斷點,只要可以單步執行,觀察變量,絕大多數的程序有問題自己都可以搞定,學習單片機編程,必須培養自己解決問題的能力,那接到項目搞不定也是發上論壇,沒有人幫解決難道要去喝西北風?protuse軟件怎么不能像硬件仿真器那樣可以設置斷點、單步執行、觀察變量?如果能為什么那么多問題解決不了?我的硬件仿真已經做的比較完善,不想研究protuse軟件了。本論壇用硬件仿真遇到問題發帖的人幾乎不見,別人不好說,我自己就是用硬件仿真,絕大多數的問題我自己都能解決,靠的就是仿真器、示波器,以及自制的開發板。我看過一些單片機教程,編個按鈕開關都要用掉外中斷、定時器,明顯就是濫用中斷、濫用資源,我編的按鍵開關程序,連延時都不需要,照樣編的很穩定,有一種單片機編程叫做CPU應用率,其實是單片機編程的最基本要求,可以把單片機資源運用的非常合理,編的程序既簡單又可靠,達到這個地步的人估計統統閉嘴了。
回復

使用道具 舉報

14#
ID:383215 發表于 2020-6-11 15:59 | 只看該作者
lhpm641 發表于 2020-6-10 21:01
感謝大神們的指點,經驗寶貴,多謝指教。剛入手,看來我要多和實際聯系起來,還有很長的路要走。剛入手了一 ...

學習單片機解決問題最快的方法就是用仿真器設置斷點、單步執行、觀察變量,一定要培養自己獨立解決問題的能力,51仿真器最好要買一、兩百元以上可以仿真所有IO口和所有資源的仿真器,可以在keil下硬件仿真,你學習51單片機的速度至少可以提高好幾倍,舍不得在開發工具上花錢,只會拖慢自己的學習速度和開發速度,51單片機只有學習價值,沒有運用價值了,要快速把51單片機弄懂,然后可以學一下AVR單片機,用洞洞板都可以自制一個JTAG仿真器和下載器,不是特別好用,對付一般學習開發基本夠用,最后還要學習STM32,STM32的jlink仿真器相當好用,價格也不貴。51單片機學會之后不能丟,我現在很多東西就是先用51單片機快速編出來,然后移植到AVR或者STM32,我覺得效率很高,你照我的話去做很快就能成為大神,我不是大神,這些東西只是我的業余愛好而已。
回復

使用道具 舉報

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

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 涩涩视频在线看 | 欧美日韩专区 | 国产一级免费视频 | 久久久精| 国产网站在线免费观看 | 午夜av免费 | 久久av综合 | 在线精品国产 | 久久综合伊人一区二区三 | 一级黄在线观看 | av电影手机在线看 | 一级黄a| 91就要激情 | 91啪亚洲精品 | 99成人免费视频 | 欧美精品一区在线 | 一级黄色片在线看 | 小草久久久久久久久爱六 | www.日韩| 亚洲日本成人 | 欧美日韩在线观看视频网站 | 亚洲成人av | 欧美日韩在线综合 | 欧美精品一二三区 | 亚洲精品在线观看网站 | 一区二区免费视频 | 亚洲激情一区二区 | 国产一区二区在线视频 | 欧美激情视频一区二区三区在线播放 | 色资源av| 四虎成人精品永久免费av九九 | 亚洲视频精品 | 日韩高清一区 | 欧美xxxx在线 | 久久专区 | 欧美黄色免费网站 | 黄色av免费网站 | 四虎在线视频 | 久久狠狠 | 一级h片| 国产一区二区三区四区三区四 |