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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

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

51單片機用定時器實現準確的延時程序 求思路

[復制鏈接]
跳轉到指定樓層
樓主
ID:988065 發表于 2021-12-4 20:59 來自手機 | 只看該作者 |只看大圖 回帖獎勵 |倒序瀏覽 |閱讀模式
用定時器實現準確的延時,準確地控制對應的燈閃爍的時間間
隔,并通過按鍵改變時間間隔。比如:開始時,第一個燈閃爍,時間
間隔為1s。當按下按鍵后,前兩個燈閃爍,時間間隔為2s,如此循環,
若在時間間隔為8s時按下按鍵,則返回開始時的狀態。
這道題我實在不會做,我寫的程序不能做到實時掃描按鍵次數,通過按鍵次數改變燈閃爍的頻率和閃爍的個數,這些我分開寫能寫,但是功能組到一起就不會了,求助思路,求助大佬們

IMG_20211204_202919.jpg (109.11 KB, 下載次數: 36)

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

使用道具 舉報

沙發
ID:624769 發表于 2021-12-4 22:09 | 只看該作者
你多多少少寫點出來,那么人家根據你的代碼,評估一下你的水平,適當的幫你改一改,也不是不可能。
你現在是出題?
然后,人家答題?
人家隨便扔個代碼上來,你確定你就能用了么?確定能看懂么?
回復

使用道具 舉報

板凳
ID:332444 發表于 2021-12-5 08:09 | 只看該作者
現在網絡提供的代碼較多了,可能是為了防止新生不學無術,題目都稍有改動新生就不能即刻復制粘貼了事,老師也是被逼無奈,為了新生的苦心!所以我現在看到稍有不同的題目直接不去回復,新生應該通過理解稍加修改即可。本題隨意設定定時器時間都只是基本的數學計算問題。比如定時50毫秒乘10就是半秒閃爍就是一秒,之后10乘以2就是2秒閃爍,如此類推,按鍵也是很簡單的控制一個量值即可實現循環控制。
回復

使用道具 舉報

地板
ID:332444 發表于 2021-12-5 10:41 | 只看該作者
本帖最后由 xianfajushi 于 2021-12-5 11:08 編輯
  1. 升級板+靜態數碼管顯示擋位
  2. unsigned int Js=0;
  3. void main()
  4. {
  5.         unsigned char Xd=0,xz=1,cs=1;
  6.         unsigned int wei=0,ss=10;
  7.         P0=1;
  8.         ZhongDuanSheZhi();
  9.         while(1)
  10.         {
  11.                 if(K1==0&&++Xd==0)
  12.                 {
  13.                         ss*=2;
  14.                         if(++cs>8){cs=1;ss=10}
  15.                         while(!K1);
  16.                 }
  17.                 P2=SmZiFu[cs];
  18.                 if(Js==ss)//設置定時器50毫秒
  19.                 {
  20.                         P0=~P0;
  21.                         Js=0;
  22.                 }
  23.         }
  24. }
復制代碼
回復

使用道具 舉報

5#
ID:139866 發表于 2021-12-5 12:31 | 只看該作者
首先你需要知道什么功能要放在while循環中讓他不斷重復,很明顯你這個按鍵檢測是必需的,燈的閃爍是根據按鍵的值被選擇的,至于定時器只起到了一個調整間隔的作用,你可以先寫按鍵檢測,在這個基礎上加入燈,每個模式封裝成一個函數,按鍵掃描的值存到一個變量中,根據這個變量來調用不同的模式,在不同模式下調整計時器
回復

使用道具 舉報

6#
ID:160500 發表于 2021-12-5 13:15 | 只看該作者
1、定時器定時1ms中斷,中斷程序里面用一個變量來記錄中斷次數。變量類型要能存儲足夠大的數據,能夠滿足你的要求。
2、主程序判斷這個變量,到1S(1000ms)做什么,到2S做什么......以此類推。
3、到最后把變量清零,重新開始。如果不清零變量就要特殊處理一下也可以。
回復

使用道具 舉報

7#
ID:988065 發表于 2021-12-5 16:07 來自手機 | 只看該作者
188610329 發表于 2021-12-4 22:09
你多多少少寫點出來,那么人家根據你的代碼,評估一下你的水平,適當的幫你改一改,也不是不可能。
你現在 ...

第一次提問,沒想到這個問題
回復

使用道具 舉報

8#
ID:988065 發表于 2021-12-5 16:15 來自手機 | 只看該作者
天ノ憶 發表于 2021-12-5 12:31
首先你需要知道什么功能要放在while循環中讓他不斷重復,很明顯你這個按鍵檢測是必需的,燈的閃爍是根據按 ...

我是想在主函數中用while死循環一直掃描按鍵按鈕次數并記錄,然后根據Switch還根據按鍵次數選擇燈的個數,在case里用個for循環來讓燈閃,然后用定時器寫個延時函數來控制燈閃的時間間隔,但是我寫不出來

IMG_20211205_161205.jpg (1.37 MB, 下載次數: 58)

IMG_20211205_161205.jpg

mmexport1638691943110.png (112.36 KB, 下載次數: 38)

mmexport1638691943110.png
回復

使用道具 舉報

9#
ID:988065 發表于 2021-12-5 16:16 來自手機 | 只看該作者
188610329 發表于 2021-12-4 22:09
你多多少少寫點出來,那么人家根據你的代碼,評估一下你的水平,適當的幫你改一改,也不是不可能。
你現在 ...

我是想在主函數中用while死循環一直掃描按鍵按鈕次數并記錄,然后根據Switch還根據按鍵次數選擇燈的個數,在case里用個for循環來讓燈閃,然后用定時器寫個延時函數來控制燈閃的時間間隔,但是我寫不出來

IMG_20211205_161205.jpg (1.37 MB, 下載次數: 38)

IMG_20211205_161205.jpg

mmexport1638691943110.png (112.36 KB, 下載次數: 40)

mmexport1638691943110.png
回復

使用道具 舉報

10#
ID:988065 發表于 2021-12-5 16:17 來自手機 | 只看該作者
liuzx66 發表于 2021-12-5 13:15
1、定時器定時1ms中斷,中斷程序里面用一個變量來記錄中斷次數。變量類型要能存儲足夠大的數據,能夠滿足你 ...

這跟我思路不一樣,我試試,感謝思路
回復

使用道具 舉報

11#
ID:988065 發表于 2021-12-5 16:18 來自手機 | 只看該作者
xianfajushi 發表于 2021-12-5 08:09
現在網絡提供的代碼較多了,可能是為了防止新生不學無術,題目都稍有改動新生就不能即刻復制粘貼了事,老師 ...

我是想在主函數中用while死循環一直掃描按鍵按鈕次數并記錄,然后根據Switch還根據按鍵次數選擇燈的個數,在case里用個for循環來讓燈閃,然后用定時器寫個延時函數來控制燈閃的時間間隔,但是我寫不出來,

IMG_20211205_161205.jpg (1.37 MB, 下載次數: 38)

IMG_20211205_161205.jpg

mmexport1638691943110.png (112.36 KB, 下載次數: 39)

mmexport1638691943110.png
回復

使用道具 舉報

12#
ID:988065 發表于 2021-12-5 16:27 來自手機 | 只看該作者
xianfajushi 發表于 2021-12-5 08:09
現在網絡提供的代碼較多了,可能是為了防止新生不學無術,題目都稍有改動新生就不能即刻復制粘貼了事,老師 ...

我是想在主函數中用while死循環一直掃描按鍵按鈕次數并記錄,然后根據Switch還根據按鍵次數選擇燈的個數,在case里用個for循環來讓燈閃,然后用定時器寫個延時函數來控制燈閃的時間間隔,但是我卡在用定時器寫個延時函數了,所以想求助一下其他思路

mmexport1638691943110.png (112.36 KB, 下載次數: 39)

mmexport1638691943110.png

IMG_20211205_161205.jpg (1.37 MB, 下載次數: 27)

IMG_20211205_161205.jpg
回復

使用道具 舉報

13#
ID:988065 發表于 2021-12-5 16:31 來自手機 | 只看該作者
xianfajushi 發表于 2021-12-5 08:09
現在網絡提供的代碼較多了,可能是為了防止新生不學無術,題目都稍有改動新生就不能即刻復制粘貼了事,老師 ...

我其實沒有想復制粘貼,交這個作業還要講解思路,而且我也是真心想學單片機
回復

使用道具 舉報

14#
ID:624769 發表于 2021-12-5 16:35 | 只看該作者
莉雅絲 發表于 2021-12-5 16:18
我是想在主函數中用while死循環一直掃描按鍵按鈕次數并記錄,然后根據Switch還根據按鍵次數選擇燈的個數 ...

如果,你用delay 延時來讓燈閃爍,你的按鍵,就必須用   中斷來檢測, 如果按鍵不想用 中斷,那么閃爍就必須用 定時器中斷來控時,總之, 要達到你的最終目的, 必須要有 1個以上的中斷。
回復

使用道具 舉報

15#
ID:624769 發表于 2021-12-5 17:15 | 只看該作者
本帖最后由 188610329 于 2021-12-5 20:30 編輯
莉雅絲 發表于 2021-12-5 16:27
我是想在主函數中用while死循環一直掃描按鍵按鈕次數并記錄,然后根據Switch還根據按鍵次數選擇燈的個數 ...

代碼如下,你要覺得能用就用,不能用就算了。


#include <STC89C5xRC.H>
typedef        unsigned char        u8;

#define Mainforse        24000000L
#define Timer_Base        (65536 - (Mainforse / 12 / 256))
u8        T0_Count,Sec_Count,Mode,Old_Mode,New_Mode;
sbit        Key = P3^2;

void main()
{
        TMOD        = 0x01;
        TL0        = Timer_Base % 256;
        TH0        = Timer_Base / 256;
        TCON        = 0x11;                //啟動TR0, INT0 下降沿中斷
        IE        = 0x83;  //EA = 1, EX0 =1 , ET0 = 1
        while(1)
        {
                New_Mode = Mode;
                if(New_Mode != Old_Mode)
                {
                        Old_Mode = New_Mode;
                        P1        = 0xff;
                }
                if(Sec_Count > Old_Mode)
                {
                        Sec_Count = Sec_Count - Old_Mode - 1;
                        switch(Old_Mode)
                        {
                                case 0:        P1 ^= 0x01;        break;
                                case 1:        P1 ^= 0x03;        break;
                                case 2:        P1 ^= 0x07;        break;
                                case 3:        P1 ^= 0x0F;        break;
                                case 4:        P1 ^= 0x1F;        break;
                                case 5:        P1 ^= 0x3F;        break;
                                case 6:        P1 ^= 0x7F;        break;
                                case 7:        P1 ^= 0xFF;        break;
                                default:        break;
                        }
                }
        }
}

void INT0(void) interrupt 0
{
        while(!Key);   //等待按鍵抬起, 如IT0 = 1, 可以不需要
        Mode++;
        Mode &= 0x07;  // Mode 0~7
}

void T0_INT(void) interrupt 1
{
        TL0        = Timer_Base % 256;
        TH0        = Timer_Base / 256;
        T0_Count++;
        if(T0_Count == 0)        Sec_Count++;
}
回復

使用道具 舉報

16#
ID:139866 發表于 2021-12-5 17:28 | 只看該作者
你這程序按鍵那個地方就不對,你隨便找本書,關于按鍵地方肯定會寫消抖,你這程序里并沒有消抖,這會導致數據出錯,當然也不是一定會出錯,只是出錯的幾率大大增加。
定時器設置直接抄書就可以,但是最好是自己理解清楚。
延時函數可以去燒錄那個軟件生成一個。
switch()里面為什么要這么寫,先說P1 = 0xFE;之后緊跟一句P1 = 0XFF;你這個寫法意思是人眼視覺停留時間比單片機運行一條指令的時間還短嗎,你中間不加個延時怎么用眼睛看到IO口變化,
其次,你這for循環也起不到改變間隔的作用,因為你if成立之后程序還要跑完剩下的for,加起來間隔是一樣的,
如果按你這個想法倒不如這樣寫
  1. while(1){
  2.        
  3.         keyscan();
  4.        
  5.         for(uchar i = 0; i < num; i++) {
  6.                 delay_ms(1000);
  7.         }
  8.        
  9.         switch(num){
  10.         case 1:
  11.                 P1 = 0xEE;
  12.                 delay_ms(100);
  13.                 P1 = 0xFF;
  14.         break;
  15. //后面自己寫吧
  16.         }
  17. }
復制代碼
但是這樣寫又不需要定時器了,或者說直接設置定時器1s中斷,for里面的延時改成這樣
  1. void main()
  2. {
  3.         while(1){
  4.                
  5.                 keyscan();
  6.                
  7.                 for(uchar i = 0; i < num; i++) {
  8.                         T0_count = 1;
  9.                         TR0 = 1;                // 啟動定時器T0
  10.                         while(T0_count);
  11.                 }
  12.         }
  13. }
  14. void userTimer0(void) interrupt 1 //假設這是1s,我沒算
  15. {
  16.     TR0 = 0;
  17.     T0_count = 0;
  18.     TH0 = 0xFC;               
  19.     TL0 = 0X4B;
  20. }

復制代碼
在中斷里加一個標志位就好。
好像這樣不知不覺就寫完了,最后,最重要的一點就是,你代碼的排版簡直爛透了,不要為了圖省事就隨便寫,代碼排版好看點對人對己都有好處
回復

使用道具 舉報

17#
ID:988065 發表于 2021-12-5 18:35 來自手機 | 只看該作者
188610329 發表于 2021-12-5 16:35
如果,你用delay 延時來讓燈閃爍,你的按鍵,就必須用   中斷來檢測, 如果按鍵不想用 中斷,那么閃爍就 ...

不太懂中斷這一塊,我能用定時器0寫一個延時函數,然后在case里調用嗎
回復

使用道具 舉報

18#
ID:624769 發表于 2021-12-5 19:36 | 只看該作者
本帖最后由 188610329 于 2021-12-6 02:02 編輯
莉雅絲 發表于 2021-12-5 16:27
我是想在主函數中用while死循環一直掃描按鍵按鈕次數并記錄,然后根據Switch還根據按鍵次數選擇燈的個數 ...

自己改 Mainforse 值為,你的晶振頻率

#include <STC89C5xRC.H>
typedef        unsigned char        u8;
#define Mainforse        24000000L
#define Timer_Base        (65536 - (Mainforse / 12 / 256))
u8        T0_Count,Sec_Count,Mode,Old_Mode,New_Mode;
sbit        Key = P3^2;

void main()
{
        TMOD        = 0x01;
        TL0        = Timer_Base % 256;
        TH0        = Timer_Base / 256;
        TCON        = 0x11;                //INT0 下降沿中斷
        IE        = 0x83;
        while(1)
        {
                New_Mode = Mode;
                if(New_Mode != Old_Mode)
                {
                        Old_Mode = New_Mode;
                        P1        = 0xff;
                }
                if(Sec_Count > Old_Mode)
                {
                        Sec_Count = Sec_Count - Old_Mode - 1;
                        switch(Old_Mode)
                        {
                                case 0:        P1 ^= 0x01;        break;
                                case 1:        P1 ^= 0x03;        break;
                                case 2:        P1 ^= 0x07;        break;
                                case 3:        P1 ^= 0x0F;        break;
                                case 4:        P1 ^= 0x1F;        break;
                                case 5:        P1 ^= 0x3F;        break;
                                case 6:        P1 ^= 0x7F;        break;
                                case 7:        P1 ^= 0xFF;        break;
                                default:        break;
                        }
                }
        }
}

void ET0_INT(void) interrupt 0
{
        while(!Key);   //等待按鍵抬起, 可以不需要
        Mode++;
        Mode &= 0x07;  // Mode 0~7
}

void T0_INT(void) interrupt 1
{
        TL0        = Timer_Base % 256;
        TH0        = Timer_Base / 256;
        T0_Count++;
        if(T0_Count == 0)        Sec_Count++;
}


回復

使用道具 舉報

19#
ID:988065 發表于 2021-12-5 21:42 來自手機 | 只看該作者
天ノ憶 發表于 2021-12-5 17:28
你這程序按鍵那個地方就不對,你隨便找本書,關于按鍵地方肯定會寫消抖,你這程序里并沒有消抖,這會導致數 ...

謝謝指導,幫助很多,剛初學沒有注意這個排版,辛苦了,買的板子還沒到,用仿真做的,就沒寫消抖了,以后一定注意排版π_π。
回復

使用道具 舉報

20#
ID:332444 發表于 2021-12-6 08:36 | 只看該作者
莉雅絲 發表于 2021-12-5 16:31
我其實沒有想復制粘貼,交這個作業還要講解思路,而且我也是真心想學單片機

真想學很好,會有人幫助的,我也不是專門說你,只是一時感慨而已,論壇上真想學的人和只想復制粘貼的人都遇到過,前天就有人向我索要圖片中的代碼,我問老婆她都不同意直接給代碼,不想學的人連圖片拿去識別都不做,
我有代碼,但回復大部分只給代碼圖片,為的就是不給直接復制了事,真想學的人要么就參考我的思路寫法,要么就自己照著動手打代碼,要么就去識別圖片,不管別人如何看待我用代碼圖片回復,只做認為該做的,當然不包括我博客發布的代碼可以復制,我學習時基本就是看別人的思路與寫法,不需要復制粘貼.
回復

使用道具 舉報

21#
ID:548551 發表于 2021-12-6 09:16 | 只看該作者
定時器假如1MS? 那么是不是可以在定時中斷函數里面給個標志位?比如F_1MS=1? WHILE(1){}里面我們把所有的程序都放在這個if(F_1MS){}里面可以不? 這就是前后臺程序架構。 對付8位單片機足矣。
回復

使用道具 舉報

22#
ID:332444 發表于 2021-12-6 09:18 | 只看該作者

回復

使用道具 舉報

23#
ID:332444 發表于 2021-12-6 09:25 | 只看該作者

回復

使用道具 舉報

24#
ID:988065 發表于 2021-12-10 16:36 來自手機 | 只看該作者
xianfajushi 發表于 2021-12-6 08:36
真想學很好,會有人幫助的,我也不是專門說你,只是一時感慨而已,論壇上真想學的人和只想復制粘貼的人都遇到 ...

您好,我想再請教一個問題,就是關于串口通信串口發送數據的問題,如題,我通過串口接收中斷,設置一個中斷標志位,然后在主函數根據標志位給計算機回復內容,但是題目要求回復中文,這個點我在網上沒找到太多的相關資料,好像是有關計算機內碼的內容,但是我找不到學習的教程等,想請您指個學習途徑。

IMG_20211210_163036.jpg (109.11 KB, 下載次數: 32)

IMG_20211210_163036.jpg
回復

使用道具 舉報

25#
ID:988065 發表于 2021-12-10 17:11 來自手機 | 只看該作者
xianfajushi 發表于 2021-12-6 09:25

我好像找到解決方案了,好像包括一個stdio.h庫文件就能用里面的函數輸出字符串了,不知道有沒有其他方法
回復

使用道具 舉報

26#
ID:887371 發表于 2021-12-13 10:21 | 只看該作者
本帖最后由 datouyuan 于 2021-12-13 10:57 編輯
莉雅絲 發表于 2021-12-10 17:11
我好像找到解決方案了,好像包括一個stdio.h庫文件就能用里面的函數輸出字符串了,不知道有沒有其他方法

printf("已點亮%bd個燈\n",x);//x為8bit數
用stdio.h的printf函數是最容易做的方法。你只要完成char putchar (char c) 這個函數就行。

void send(char* c);//串口發送字符
void sends(char* str,unsigned char len);//串口發送字符串
假如不用stdio.h,你需要完成上面2個函數。

sends("已點亮",6);
send(x/10+'0');send(x%10+'0');//x范圍00~99
sends("個燈\n",5);//一個中文字符算2個字節,ascii算1個字節,所以長度為5
回復

使用道具 舉報

27#
ID:883242 發表于 2021-12-13 11:27 | 只看該作者
莉雅絲 發表于 2021-12-10 17:11
我好像找到解決方案了,好像包括一個stdio.h庫文件就能用里面的函數輸出字符串了,不知道有沒有其他方法

stdio.h解決不了問題,要重定向putch才可以。
回復

使用道具 舉報

28#
ID:401564 發表于 2021-12-13 16:30 | 只看該作者
莉雅絲 發表于 2021-12-10 17:11
我好像找到解決方案了,好像包括一個stdio.h庫文件就能用里面的函數輸出字符串了,不知道有沒有其他方法

串口輸出字符串用sprintf函數最省事
sprintf可以自動輸出負號和小數點,也可以不輸出小數點,對于數據處理最省事,至少占用內存什么的,那是單片機累,我不累就行
char   k[10];                                                         //這里不能加code限定符,否則計算不正確,數組長度隨意,不出錯就可以
        char a;
        sprintf(k,"%.1f",Data_Send);                        //把浮點數據分割成字符串,并存放在k數組中,"%.1f"的2f表示小數點后再顯示1位數,不顯示小數就是0f
                for(a=0;(k[a]!='\0');a++)
                {
                        Send_Out_COM(k[a]);                                //發送(串口發送函數),發送的是ASCII碼,避免出現0x00數據
                }



void Send_Out_COM(unsigned char COM)        //發送一個字節數據(串口發送函數)
{
        while(Busy);                                                //等待上次發送完成,Busy在串口2完成發送后清除       
        Busy=1;
        S2BUF=COM;       
}

回復

使用道具 舉報

29#
ID:988065 發表于 2021-12-14 18:45 來自手機 | 只看該作者
datouyuan 發表于 2021-12-13 10:21
printf("已點亮%bd個燈\n",x);//x為8bit數
用stdio.h的printf函數是最容易做的方法。你只要完成char put ...

學到了很多,謝謝大佬
回復

使用道具 舉報

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

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 国产精品美女久久久久久不卡 | 天天爽夜夜爽精品视频婷婷 | 欧美福利 | 最新日韩精品 | 久久99蜜桃综合影院免费观看 | 91久久精品一区二区二区 | 国产精品一区二区在线播放 | 日本三级播放 | 台湾佬久久 | 成年无码av片在线 | 亚洲精品大片 | 国产精品3区| 四季久久免费一区二区三区四区 | 欧美日韩一区在线观看 | 国产黄色大片在线观看 | 国产精品久久二区 | 天啪 | 在线免费观看黄色 | 九九久久在线看 | 久操国产 | 亚洲av毛片 | 中文字幕电影在线观看 | 黄色大片在线视频 | 久久综合色综合 | 青青草av在线播放 | 亚洲综合电影 | 久久综合入口 | 天堂影院av | 91免费在线播放 | 亚洲一区二区电影网 | 在线免费观看黄色av | 成人免费视频在线观看 | 成人午夜网站 | 1000部精品久久久久久久久 | 免费一看一级毛片 | 欧洲性生活视频 | 成人免费观看男女羞羞视频 | 成人网在线观看 | 久久久久资源 | 久久网日本| 国产免费让你躁在线视频 |