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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 4207|回復: 13
收起左側

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

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

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


  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)                //延時函數(shù)
  10. {
  11.         uint i,j;
  12.         for(i = x; i > 0; i --)
  13.                 for(j = 125; j > 0; j --);               
  14. }

  15. void Show_Time()                                //數(shù)碼管動態(tài)掃描顯示
  16. {
  17.                 uchar i;
  18.         /*****************數(shù)據(jù)轉換*****************************/
  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.                                 主函數(shù)        
  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的計數(shù)
  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, 下載次數(shù): 4)

未按鍵時.png
回復

使用道具 舉報

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

使用道具 舉報

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

使用道具 舉報

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

使用道具 舉報

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

使用道具 舉報

ID:104797 發(fā)表于 2020-6-9 06:06 來自手機 | 顯示全部樓層
想明白了IE置1的問題,但是沒想出怎么解決。
回復

使用道具 舉報

ID:213173 發(fā)表于 2020-6-9 10:22 | 顯示全部樓層
lhpm641 發(fā)表于 2020-6-9 06:06
想明白了IE置1的問題,但是沒想出怎么解決。

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

  1. #include<reg51.h>
  2. #define uchar unsigned char
  3. #define uint unsigned int
  4. uchar Duan[] = {//共陽數(shù)碼管段碼"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)                //延時函數(shù)
  15. {
  16.         uint i,j;
  17.         for(i = x; i > 0; i --)
  18.                 for(j = 125; j > 0; j --);
  19. }*/

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

  25.         /*****************數(shù)據(jù)分解*****************************/
  26.         if(flag==0)//判斷啟動標志復位 處理數(shù)據(jù)
  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;//加小數(shù)點
  45.         else P0=Time_Buffer[k];
  46.         k++;k%=4;
  47. }

  48. /******************
  49.        主函數(shù)        
  50. ******************/
  51. void main()
  52. {
  53.         IT0 = 1;//下降沿觸發(fā)
  54.         IT1 = 1;
  55.         EX0 = 1;
  56.         EX1 = 1;
  57.         EA  = 1;  
  58.        
  59.         TMOD=0x02; //設置為自動重載方式
  60.         TH0=0x9c;  //設置為100us的計數(shù)
  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)         //判斷啟動狀態(tài) 與INT0互鎖
  91.         {
  92.                 TR0=0;        //停止計時
  93.                 flag=0;             //啟動標志復位
  94.                 Time=Time_Count;//讀取計數(shù)值
  95.         }
  96. }
復制代碼



回復

使用道具 舉報

ID:383215 發(fā)表于 2020-6-9 17:31 | 顯示全部樓層

AN2.jpg

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

使用道具 舉報

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

使用道具 舉報

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

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

使用道具 舉報

ID:104797 發(fā)表于 2020-6-10 21:01 | 顯示全部樓層
感謝大神們的指點,經(jīng)驗寶貴,多謝指教。剛入手,看來我要多和實際聯(lián)系起來,還有很長的路要走。剛入手了一塊試驗板,以后請大神們多傳授點經(jīng)驗。
回復

使用道具 舉報

ID:213173 發(fā)表于 2020-6-11 07:55 | 顯示全部樓層
kmsj 發(fā)表于 2020-6-10 14:47
你說的非常正確,我的單片機程序,只要有按鍵,就是“在任何條件下必須對按鍵抖動做處理”,很早以前我就 ...

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

使用道具 舉報

ID:383215 發(fā)表于 2020-6-11 15:53 | 顯示全部樓層
wulin 發(fā)表于 2020-6-11 07:55
與您這樣有思想,有經(jīng)驗,非人云亦云的壇友交流非常有益。在7樓回復中用protuse軟件仿真,當然不能算是實 ...

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

使用道具 舉報

ID:383215 發(fā)表于 2020-6-11 15:59 | 顯示全部樓層
lhpm641 發(fā)表于 2020-6-10 21:01
感謝大神們的指點,經(jīng)驗寶貴,多謝指教。剛入手,看來我要多和實際聯(lián)系起來,還有很長的路要走。剛入手了一 ...

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

使用道具 舉報

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

本版積分規(guī)則

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

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

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 在线看一区二区 | 草久久免费视频 | 久久99精品久久久久久青青日本 | 九九色综合 | 一级毛片在线播放 | 国产成在线观看免费视频 | 欧美黄色大片在线观看 | 在线观看视频一区 | 日韩视频免费在线 | 久久中文免费视频 | 中文字幕 欧美 日韩 | 国产在线一区二区三区 | 欧美激情国产日韩精品一区18 | 精品日韩一区二区 | aaaaaaa片毛片免费观看 | www.久久艹| 久久国产精品一区 | 久久国产综合 | 一区二区三区视频在线观看 | 欧美中文字幕 | 亚欧洲精品在线视频免费观看 | 91视频大全 | 亚洲精品久久久久久下一站 | 国产精品久久久久久 | 久久69精品久久久久久久电影好 | 羞羞视频在线观看免费观看 | 亚洲国产精品久久 | 成人国产在线视频 | 高清一区二区三区 | 亚洲精品久久久久中文字幕欢迎你 | av毛片| 亚洲一区二区成人 | 99精品国产一区二区三区 | 一区二区三区国产精品 | 国产亚洲精品一区二区三区 | 视频一区在线 | 国产99视频精品免视看9 | 成人午夜在线 | 欧美久久一区二区 | 中文字幕一区二区三区不卡 | 在线中文字幕亚洲 |