延時與中斷出錯,是單片機新手在單片機開發應用過程中,經常會遇到的問題,本文匯總整理了包含了MCS-51系列單片機、MSP430單片機、C51單片機、8051F的單片機、avr單片機、STC89C52、PIC單片機…..在內的各種單片機常見的延時與中斷問題及解決方法,希望對單片機新手們,有所幫助!
1、單片機延時程序的延時時間怎么算的?
答:如果用循環語句實現的循環,沒法計算,但是可以通過軟件仿真看到具體時間,但是一般精精確延時是沒法用循環語句實現的。
如果想精確延時,一般需要用到定時器,延時時間與晶振有關系,單片機系統一般常選用11.059 2 MHz、12 MHz或6 MHz晶振。第一種更容易產生各種標準的波特率,后兩種的一個機器周期分別為1 μs和2 μs,便于精確延時。本程序中假設使用頻率為12 MHz的晶振。最長的延時時間可達216=65 536 μs。若定時器工作在方式2,則可實現極短時間的精確延時;如使用其他定時方式,則要考慮重裝定時初值的時間(重裝定時器初值占用2個機器周期)。
2、求個單片機89S51 12M晶振 用定時器延時10分鐘,控制1個燈就可以
答:可以設50ms中斷一次,定時初值,TH0=0x3c、TL0=0xb0。中斷20次為1S,10分鐘的話,需中斷12000次。計12000次后,給一IO口一個低電平(如功率不夠,可再加擴展),就可控制燈了。
而且還要看你用什么語言計算了,匯編延時準確,知道單片機工作周期和循環次數即可算出,但不具有可移植性,在不同種類單片機中,匯編不通用。用c的話,由于各種軟件執行效率不一樣,不會太準,通常用定時器做延時或做一個不準確的延時,延時短的話,在c中使用匯編的nop做延時
3、51單片機C語言for循環延時程序時間計算 ,設晶振12MHz,即一個機器周期是1us。
for(i=0,i<100;i++)
for(j=0,j<100;j++)
我覺得時間是100*100*1us=10ms,怎么會是100ms
答:
不可能的,是不是你的編譯有錯的啊
我改的晶振12M,在KEIL 4.0 里面編譯的,為你得出的結果最大也就是40ms,這是軟件的原因,
不可能出現100ms那么大的差距,是你的軟件的原因。
不信你實際編寫一個秒鐘,利用原理計算編寫一個燒進單片機和利用軟件測試的秒程序燒進單片機,你會發現原理計算的程序是正確的
4 、51單片機c語言 _nop_()是一個空指令?短時間延時的?空幾個機器周期?
答:這個_nop_()等效與匯編里面的,NOP指令,也就是空一個機器周期,如果是傳統51單片機的話,等于空12個時鐘周期【即一個機器周期】
5、51單片機 延時500ms 用機器周期疊加怎么算?
答:DELAY:
MOV R7,#4
D2:MOV R6,#250
D1:MOV R5,#250
DJNZ R5,$
DJNZ R6,D1
DJNZ R7,D2
RET
假設晶振為12MHz
剛延時時間為:
250*250*4*2=500MS
6、51單片機C語言程序中延時函數delay的原理是什么?
現在找到兩個函數
第一:
void delay(void)
{ unsigned int i,j;
for(i=0;i<500;i++)
{ for(j=0;j<121;j++)
{;}
}
}
第二:
void delay(unsigned int k)
{ unsigned int i,j;
for(i=0;i
{ for(j=0;j<121;j++)
{;}
}
}
現有幾個疑問:
(1):延時函數的原理?
(2):兩個for循環的作用?
(3):i、j的取值有什么規律和依據?是不是和單片機接的晶振頻率有關?所能延時的最小單位時間是怎么計算的?
延時時間怎么計算啊!假如用的是AT89C51RC+11.0592M的晶振呢?
答:
1:原理:僅僅執行一些,沒有實質性影響的所謂“無意義指令”,比如做比大小啊,做某個int的自加運算啊之類的
2:兩重for的作用:簡單的說,就像高中數學中的“乘法原理”一樣,這樣可以很輕易的迅速增加上述“無意義指令”的數目
3:關于取值大小:這個如果是在C下變成,這個值不僅僅與晶振、單片機本身運算速度有關,而且還與C的編譯器有關,所以說,這個值雖說是可以精確計算的,但大多數情況下,程序員用的都是“經驗值”——當然,如果用匯編編程,情況就不一樣了,因為每一條指令所使用的機器周期是一定的,你當然可以根據所有指令使用的總時間,精確的算出具體延時的總時間
綜合你的的問題,我給你一點建議,就是剛學單片機的時候,還是一定要老老實實的從匯編編程學起——這樣,在你以后接觸到C之后,你才能明白,這中間實際上經歷了一個什么樣的過程,只有這樣你才能真正理解單片機。當然,等最終你完全拿下一種單片機之后,盡量使用C編程,無疑是歷史所肯定的。
7、51單片機,晶振為6M,求一個10ms的延時程序
答:延時有很多種方法,有一種是讓單片機去做無聊的循環,還有一種是用定時器。
第一種的算法是:
晶振的周期T1=1/f; 這里f=6MHz 所以T1=1/6 us;(微秒)
單片機花12個T1去執行一個指令,
所以一個機器周期等于12個晶振周期,
T2=12*T1=2us
10ms=1000 0us
所以你要得到10ms的延時就要想辦法讓機器去做5000條“無聊的指令”
所以
DEL: MOV R5,#05H
F1: MOV R6,#05H
F2: MOV R7,#32H
F3: DJNZ R7,F3
DJNZ R6,F2
DJNZ R5,F1
RET
這種方法是用于對時間要求不高的地方,我說的是其思想,程序中可能有錯的地方
用定時器的方法我不太會就不誤人了 (補充一下就是這個是用匯編寫的,你在主程序中用ACALL DEL調用就延時了。
8、今天我用單片機做“眨眼的LED”實驗時,程序運行,每次只令燈亮或滅都沒問題,但是一開延時不能出現期盼的燈亮燈滅的現象,這是怎么回事?
實驗的硬件條件是:STC89C52,編譯環境:keil 3。
下面是我寫的程序,請教高手!!!
#include// 文件包含處理
#define uchar unsigned char //宏定義,方便以后程序的書寫
#define uint unsigned int
sbit P1_0 = P1 ^ 0; //位變量定義
void Delay(uint t)
{
uchar i;
while(--t)
{
for(i = 0; i < 125; i++) //延時1MS,在這里我們用的晶振是是12M,根據機器周期的計算,我們
{;} //可算得本次循環延時約1MS
}
}
void main(void)
{
while(1)
{
P1_0 = 0; //點亮LED燈
Delay(1000); //應單片執行程序的時間很快,所以必須延時,要不看不到實驗現象
P1_0 = 1; //熄滅LED燈
}
補充提問:我是讓P1.0先低然后延時之后再高,即燈先亮再滅,然后開始循環的
答:應該這樣寫
while(1)
{
P1_0 = 0; //點亮LED燈
Delay(1000); //應單片執行程序的時間很快,所以必須延時,要不看不到實驗現象
P1_0 = 1; //熄滅LED燈
Delay(1000);
補充問題回復:問題恰恰就錯在這了,循環完一遍之后燈由滅到亮根本沒有時間延時,即第一次循環中燈還沒來的機滅呢,就進入到第二輪循環中的亮了,所以原因就在這,這錯誤太低級了,以后引以為鑒吧
9、單片機延時函數的問題
void delay(uchar i)
{
uchar j;
while(i--)
{
for(j=125;j>0;j--)
;
}
}
這個函數中的i,j的大小有**嗎?
答:這個函數中j的大小和你定義的數據類型有關,因為你定義的為無符號字符型,為單字節數據,所以最大為255。.
如果你需要增大,可以改變j的數據類型定義,如unsigned int (2字節)可以到65535;無符號長整形unsigned long(4字節) 可以到4294967295。 而上面所所256是-1,而你定義的是無符號字符型。
10、請教一個AVR單片機延時的問題
外部晶振用的是8MHz,延時1微秒的程序如下:
void delay_us(unsigned int delay_counter)//延時1us
{
do
{
delay_counter--;
}
while(delay_counter>1);
}
請問,為什么能延時1微秒啊?
答:8MHZ表示單片機的運行周期為1/8us,也就是0.125us執行一步
你使用的是軟件延時
那么包括程序的提取,執行等都要花費時間
比如,你提取這個函數可能花去一步,那現在就使用了0.125us啦
接著你執行這個函數,在單片機內部,運算是通過寄存器的移來移去實現的
這都需要時間,可能你看到的就一句counter--這個指令,可能會花費好幾個時鐘周期來實現
舉個例子:
c=a+b,只有一句,但實際上花費的時間并不短
mov a,#data1;//數據data1放入a寄存器
mov b,#data2;//數據data2放入b寄存器
add a,b;//寄存器a的值與b相加,結果放入a
mov c,a;//將a的值放入c
這樣才是單片機內部真正執行的指令,這需要花費至少4個時鐘周期,而不是1個
至于晶體管級的我就不解釋了,你得好好學習匯編才能理解單片機的運作。
至于這個函數為什么能延時1ms,這個是靠經驗來判斷的,最直接的方法就是用示波器看,以上均為推論。
11、PIC單片機的延時問題 晶振4Mhz:
void delay()
{
unsigned int d=1000;
while(--d){;}
}
此函數在4M晶體下產生10003us的延時,也就是10MS。
問題:我剛算了一下他應該執行了999條指令,1條單周期的指令也才1US,那就是999us,為什么會有10ms的延時?
1:for(x=100;--x;){;} : 2: for(x=0;x<100;x++){;} 2句話相同
第一句:X的值范圍是不是 1~99?為什么?
第二句:X的范圍是不是0~99?為什么?這么算的。我知道符號在前在后的區別。2句話應該是不一樣的才對啊!
答:
問題1:“我剛算了一下他應該執行了999條指令”因為你算錯了。延時時間是由產生的匯編代碼所決定的,C語言語句只是個假象,千萬不要以為C語言一行就是一條指令!此處由于涉及到雙字節減法,因此會有額外的判斷,編譯結果每次循環耗費幾十個周期毫不奇怪。
問題2:前一句x從100開始遞減,遞減至1時退出循環。后一句x從0開始遞增,遞增到100時退出循環。所謂“2句話”相同僅僅是指這兩個循環體的循環次數相同。實際上兩個循環的執行過程是完全不同的,所消耗時間也有可能不同。
12、stc單片機的延時問題 ,STC10F08XE單片機,晶振22.1184M
void delay(unsigned long uldata)
{
unsigned int j = 0;
unsigned int g = 0;
for (j=0;j<5;j++)
{
for (g=0;g
{
_nop_();
_nop_();
_nop_();
}
}
}
當uldata=1時延時多少秒?
請給出具體算法…………
答:用keil轉換成匯編語句,然后對照指令表計算就行了
13、我想用單片機連接不斷地向電腦發數,如下:
while (1)
{
send_char('9');
delay(n);
}
如每發送一個數,應延時多少微妙好呢?即一般最短能延時多少微米呢?如延時太長的話,那發送很多數據不就用很長時間嗎?
答:不做太多的串口處理分析,只順著你的問題和你的方法說說:
先考慮下串口的速率 假設9600,那么發送一個字符要多久?
(9600bit/S) / 10bit(一個字符1+8+1) = 960字符/秒 約 1ms/byte
也就是說你如果在1ms內發送超過一個字符就沒意義了,硬件速度達不到。
while(1)
{
send_char('9');
delay(n);
}
這個循環是執行周期也就十幾微秒+delay()的延遲,所以任何小于1040微秒的延遲對串口硬件來說沒意義,上一個還沒處理完,下一個就來了根本執行不了嘛。
如果你send_char()里面有while(!TI);TI = 0;這樣的語句或有串口中斷TI的處理的話,那么實際上你的delay()已經在發送函數里了,while(!TI);這部就是延遲等待嗎?那根本不需要主函數去延遲了,直接發就行了。
14、一個單片機延時子程序的問題,在延時子程序那里,一直搞不明白,給r7和r6賦予0,然后下面的djnz r7,delayloop不就一直循環了,那還怎么接下去的程序?
org 0000h
ljmp start
org 0030h
start: mov a,#0feh
mov r5,#8
output: mov p1,a
rl a
call delay
djnz r5,output
ljmp start
delay: mov r6,#0
mov r7,#0
delayloop:djnz r7,delayloop
djnz r6,delayloop
ret
end
答: 你的延時程序不是因為值為0,而是跳轉位置不對,改為如下:
delay: mov r6,#0
delayloop:mov r7,#0
:djnz r7,$
djnz r6,delayloop
ret
R7,R6初值為0,但是當DJNZ執行時,這條指令是先減1再判斷,所以0-1=255,判斷的話也不為0,仍然循環256次。
0-1=255的解釋:
0000 0000
- 0000 0001
-------------------------
1111
15、我想提兩個單片機延時與按鍵的問題
1:如果一個程序中延時和按鍵,如果延時子程序比較長(假如2秒),怎樣確保按鍵能夠得到及時響應(假如PC正在執行延時子程序,正在這時候有按鍵輸入,不是響應不了)——,,,前提是不能用定時器定時掃描,和中斷來做,因為定時器和中斷我另有其他用途
2:單片機沒有串口。怎樣才能使得他與24C02進行通信(24C02是具有2K內存的EEPROM)
答:
首先明確一點你說單片機沒有串口,應該是指沒有I2C口吧。
1 在延時程序里面加入按鍵的檢測
2 用IO口模擬I2C時序讀寫
16、51單片機延時小程序,求高手解釋什么意思?
delay200ms:
mov r2,#82
l0:mov r1,#116
l1:mov r0,#9
djnz r0,$
djnz r1,l1
djnz r2,l0
ret
答:以下是每條指令的時間,T為一個機器周期
delay200ms:
mov r2,#82;1T
l0:mov r1,#116;1T
l1:mov r0,#9;1T
djnz r0,$;2T
djnz r1,l1;2T
djnz r2,l0;2T
ret;2T
以上共三層循環,忽略部分指令,最簡單算法是:
2*9*116*82=171216
不忽略指令是:
1+(1+(1+2*9+2)*116+2)*82+2=200001
因此延時時間大約為200ms
17、于51單片機延遲時間的問題
uchar i;i--;
uint i;i--;
這兩條語句在12M晶振下運行時間分別是多少??
答:一個時鐘周期,2us,共4us
18、周期為6MHZ的單片機延時10秒的子程序的怎么編?
答:/********************************************************************
* 名稱 : Delay()
* 功能 : 延時,延時時間為 10ms * del。這是通過軟件延時,有一定誤差。
* 輸入 : del
* 輸出 : 無
***********************************************************************/
void Delay(uint del)
{
uint i,j;
for(i=0; i
for(j=0; j<1827; j++) //這個是通過軟件仿真得出的數
;
}
這個是晶振為12mhz的單片機延時10ms的程序,你只要在這個基礎上減小一倍就行了,當然至于具體值還是要調試下的。
19、片機的有些程序需要調用延時程序,如何能合理的安排循環次數以及空操作的個數?
答:用匯編的話就根據你的當前晶振頻率去推算你的指令周期,然后結合你需要延遲的時間,編寫延遲程序,用C的話還是要看最后生成的匯編碼是什么樣的了。最簡單的方法就是寫好程序以后再編譯器里軟仿真看時間。
20、單片機延時程序問題
延時程序 void delay(uint dt)
{
uchar bt;
for(;dt;dt--);
for(bt=0;bt<255;bt++);
}
編譯時有警告C:DOCUMENTS AND SETTINGSADMINISTRATOR桌面字 310 點陣LED顯示.C(46): warning C235: parameter 1: different types
為什么?求大俠指點
答:某個函數傳參類型與聲明類型不符。
另外你這個for(;dt;dt--);沒有起到外層循環的作用……
-
單片機
+關注
關注
6032文章
44518瀏覽量
633060
原文標題:單片機延時問題20問
文章出處:【微信號:weixin21ic,微信公眾號:21ic電子網】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論