單片機(jī)的延時(shí)與中斷問(wèn)題及解決方法
一、單片機(jī)延時(shí)問(wèn)題20問(wèn)
1、單片機(jī)延時(shí)程序的延時(shí)時(shí)間怎么算的?
答:如果用循環(huán)語(yǔ)句實(shí)現(xiàn)的循環(huán),沒(méi)法計(jì)算,但是可以通過(guò)軟件仿真看到具體時(shí)間,但是一般精精確延時(shí)是沒(méi)法用循環(huán)語(yǔ)句實(shí)現(xiàn)的。
如果想精確延時(shí),一般需要用到定時(shí)器,延時(shí)時(shí)間與晶振有關(guān)系,單片機(jī)系統(tǒng)一般常選用11.059 2 MHz、12 MHz或6 MHz晶振。第一種更容易產(chǎn)生各種標(biāo)準(zhǔn)的波特率,后兩種的一個(gè)機(jī)器周期分別為1 μs和2 μs,便于精確延時(shí)。本程序中假設(shè)使用頻率為12 MHz的晶振。最長(zhǎng)的延時(shí)時(shí)間可達(dá)216=65 536 μs。若定時(shí)器工作在方式2,則可實(shí)現(xiàn)極短時(shí)間的精確延時(shí);如使用其他定時(shí)方式,則要考慮重裝定時(shí)初值的時(shí)間(重裝定時(shí)器初值占用2個(gè)機(jī)器周期)。
2、求個(gè)單片機(jī)89S51 12M晶振 用定時(shí)器延時(shí)10分鐘,控制1個(gè)燈就可以
答:可以設(shè)50ms中斷一次,定時(shí)初值,TH0=0x3c、TL0=0xb0。中斷20次為1S,10分鐘的話,需中斷12000次。計(jì)12000次后,給一IO口一個(gè)低電平(如功率不夠,可再加擴(kuò)展),就可控制燈了。
而且還要看你用什么語(yǔ)言計(jì)算了,匯編延時(shí)準(zhǔn)確,知道單片機(jī)工作周期和循環(huán)次數(shù)即可算出,但不具有可移植性,在不同種類單片機(jī)中,匯編不通用。用c的話,由于各種軟件執(zhí)行效率不一樣,不會(huì)太準(zhǔn),通常用定時(shí)器做延時(shí)或做一個(gè)不準(zhǔn)確的延時(shí),延時(shí)短的話,在c中使用匯編的nop做延時(shí)
3、51單片機(jī)C語(yǔ)言for循環(huán)延時(shí)程序時(shí)間計(jì)算 ,設(shè)晶振12MHz,即一個(gè)機(jī)器周期是1us。
for(i=0,i<100;i++)
for(j=0,j<100;j++)
我覺(jué)得時(shí)間是100*100*1us=10ms,怎么會(huì)是100ms
答:
不可能的,是不是你的編譯有錯(cuò)的啊
我改的晶振12M,在KEIL 4.0 里面編譯的,為你得出的結(jié)果最大也就是40ms,這是軟件的原因,
不可能出現(xiàn)100ms那么大的差距,是你的軟件的原因。
不信你實(shí)際編寫(xiě)一個(gè)秒鐘,利用原理計(jì)算編寫(xiě)一個(gè)燒進(jìn)單片機(jī)和利用軟件測(cè)試的秒程序燒進(jìn)單片機(jī),你會(huì)發(fā)現(xiàn)原理計(jì)算的程序是正確的
4 、51單片機(jī)c語(yǔ)言 _nop_()是一個(gè)空指令?短時(shí)間延時(shí)的?空幾個(gè)機(jī)器周期?
答:這個(gè)_nop_()等效與匯編里面的,NOP指令,也就是空一個(gè)機(jī)器周期,如果是傳統(tǒng)51單片機(jī)的話,等于空12個(gè)時(shí)鐘周期
5、51單片機(jī) 延時(shí)500ms 用機(jī)器周期疊加怎么算?
答:DELAY:
MOV R7,#4
D2:MOV R6,#250
D1:MOV R5,#250
DJNZ R5,$
DJNZ R6,D1
DJNZ R7,D2
RET
假設(shè)晶振為12MHz
剛延時(shí)時(shí)間為:
250*250*4*2=500MS
6、51單片機(jī)C語(yǔ)言程序中延時(shí)函數(shù)delay的原理是什么?
現(xiàn)在找到兩個(gè)函數(shù)
第一:
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
{;}
}
}
現(xiàn)有幾個(gè)疑問(wèn):
(1):延時(shí)函數(shù)的原理?
(2):兩個(gè)for循環(huán)的作用?
(3):i、j的取值有什么規(guī)律和依據(jù)?是不是和單片機(jī)接的晶振頻率有關(guān)?所能延時(shí)的最小單位時(shí)間是怎么計(jì)算的?
延時(shí)時(shí)間怎么計(jì)算啊!假如用的是AT89C51RC+11.0592M的晶振呢?
答:
1:原理:僅僅執(zhí)行一些,沒(méi)有實(shí)質(zhì)性影響的所謂“無(wú)意義指令”,比如做比大小啊,做某個(gè)int的自加運(yùn)算啊之類的
2:兩重for的作用:簡(jiǎn)單的說(shuō),就像高中數(shù)學(xué)中的“乘法原理”一樣,這樣可以很輕易的迅速增加上述“無(wú)意義指令”的數(shù)目
3:關(guān)于取值大小:這個(gè)如果是在C下變成,這個(gè)值不僅僅與晶振、單片機(jī)本身運(yùn)算速度有關(guān),而且還與C的編譯器有關(guān),所以說(shuō),這個(gè)值雖說(shuō)是可以精確計(jì)算的,但大多數(shù)情況下,程序員用的都是“經(jīng)驗(yàn)值”——當(dāng)然,如果用匯編編程,情況就不一樣了,因?yàn)槊恳粭l指令所使用的機(jī)器周期是一定的,你當(dāng)然可以根據(jù)所有指令使用的總時(shí)間,精確的算出具體延時(shí)的總時(shí)間
綜合你的的問(wèn)題,我給你一點(diǎn)建議,就是剛學(xué)單片機(jī)的時(shí)候,還是一定要老老實(shí)實(shí)的從匯編編程學(xué)起——這樣,在你以后接觸到C之后,你才能明白,這中間實(shí)際上經(jīng)歷了一個(gè)什么樣的過(guò)程,只有這樣你才能真正理解單片機(jī)。當(dāng)然,等最終你完全拿下一種單片機(jī)之后,盡量使用C編程,無(wú)疑是歷史所肯定的。
7、51單片機(jī),晶振為6M,求一個(gè)10ms的延時(shí)程序
答:延時(shí)有很多種方法,有一種是讓單片機(jī)去做無(wú)聊的循環(huán),還有一種是用定時(shí)器。
第一種的算法是:
晶振的周期T1=1/f; 這里f=6MHz 所以T1=1/6 us;(微秒)
單片機(jī)花12個(gè)T1去執(zhí)行一個(gè)指令,
所以一個(gè)機(jī)器周期等于12個(gè)晶振周期,
T2=12*T1=2us
10ms=1000 0us
所以你要得到10ms的延時(shí)就要想辦法讓機(jī)器去做5000條“無(wú)聊的指令”
所以
DEL: MOV R5,#05H
F1: MOV R6,#05H
F2: MOV R7,#32H
F3: DJNZ R7,F3
DJNZ R6,F2
DJNZ R5,F1
RET
這種方法是用于對(duì)時(shí)間要求不高的地方,我說(shuō)的是其思想,程序中可能有錯(cuò)的地方
用定時(shí)器的方法我不太會(huì)就不誤人了 (補(bǔ)充一下就是這個(gè)是用匯編寫(xiě)的,你在主程序中用ACALL DEL調(diào)用就延時(shí)了。
8、今天我用單片機(jī)做“眨眼的LED”實(shí)驗(yàn)時(shí),程序運(yùn)行,每次只令燈亮或滅都沒(méi)問(wèn)題,但是一開(kāi)延時(shí)不能出現(xiàn)期盼的燈亮燈滅的現(xiàn)象,這是怎么回事?
實(shí)驗(yàn)的硬件條件是:STC89C52,編譯環(huán)境:keil 3。
下面是我寫(xiě)的程序,請(qǐng)教高手!??!
#include
#define uchar unsigned char //宏定義,方便以后程序的書(shū)寫(xiě)
#define uint unsigned int
sbit P1_0 = P1 ^ 0; //位變量定義
void Delay(uint t)
{
uchar i;
while(--t)
{
for(i = 0; i < 125; i++) //延時(shí)1MS,在這里我們用的晶振是是12M,根據(jù)機(jī)器周期的計(jì)算,我們
{;} //可算得本次循環(huán)延時(shí)約1MS
}
}
void main(void)
{
while(1)
{
P1_0 = 0; //點(diǎn)亮LED燈
Delay(1000); //應(yīng)單片執(zhí)行程序的時(shí)間很快,所以必須延時(shí),要不看不到實(shí)驗(yàn)現(xiàn)象
P1_0 = 1; //熄滅LED燈
}
補(bǔ)充提問(wèn):我是讓P1.0先低然后延時(shí)之后再高,即燈先亮再滅,然后開(kāi)始循環(huán)的
答:應(yīng)該這樣寫(xiě)
while(1)
{
P1_0 = 0; //點(diǎn)亮LED燈
Delay(1000); //應(yīng)單片執(zhí)行程序的時(shí)間很快,所以必須延時(shí),要不看不到實(shí)驗(yàn)現(xiàn)象
P1_0 = 1; //熄滅LED燈
Delay(1000);
補(bǔ)充問(wèn)題:?jiǎn)栴}恰恰就錯(cuò)在這了,循環(huán)完一遍之后燈由滅到亮根本沒(méi)有時(shí)間延時(shí),即第一次循環(huán)中燈還沒(méi)來(lái)的機(jī)滅呢,就進(jìn)入到第二輪循環(huán)中的亮了,所以原因就在這,這錯(cuò)誤太低級(jí)了,以后引以為鑒吧
9、單片機(jī)延時(shí)函數(shù)的問(wèn)題
void delay(uchar i)
{
uchar j;
while(i--)
{
for(j=125;j>0;j--)
;
}
}
這個(gè)函數(shù)中的i,j的大小有嗎?
答:這個(gè)函數(shù)中j的大小和你定義的數(shù)據(jù)類型有關(guān),因?yàn)槟愣x的為無(wú)符號(hào)字符型,為單字節(jié)數(shù)據(jù),所以最大為255。.
如果你需要增大,可以改變j的數(shù)據(jù)類型定義,如unsigned int (2字節(jié))可以到65535;無(wú)符號(hào)長(zhǎng)整形unsigned long(4字節(jié)) 可以到4294967295。 而上面所所256是-1,而你定義的是無(wú)符號(hào)字符型。
10、請(qǐng)教一個(gè)AVR單片機(jī)延時(shí)的問(wèn)題
外部晶振用的是8MHz,延時(shí)1微秒的程序如下:
void delay_us(unsigned int delay_counter)//延時(shí)1us
{
do
{
delay_counter--;
}
while(delay_counter>1);
}
請(qǐng)問(wèn),為什么能延時(shí)1微秒啊?
答:8MHZ表示單片機(jī)的運(yùn)行周期為1/8us,也就是0.125us執(zhí)行一步
你使用的是軟件延時(shí)
那么包括程序的提取,執(zhí)行等都要花費(fèi)時(shí)間
比如,你提取這個(gè)函數(shù)可能花去一步,那現(xiàn)在就使用了0.125us啦
接著你執(zhí)行這個(gè)函數(shù),在單片機(jī)內(nèi)部,運(yùn)算是通過(guò)寄存器的移來(lái)移去實(shí)現(xiàn)的
這都需要時(shí)間,可能你看到的就一句counter--這個(gè)指令,可能會(huì)花費(fèi)好幾個(gè)時(shí)鐘周期來(lái)實(shí)現(xiàn)
舉個(gè)例子:
c=a+b,只有一句,但實(shí)際上花費(fèi)的時(shí)間并不短
mov a,#data1;//數(shù)據(jù)data1放入a寄存器
mov b,#data2;//數(shù)據(jù)data2放入b寄存器
add a,b;//寄存器a的值與b相加,結(jié)果放入a
mov c,a;//將a的值放入c
這樣才是單片機(jī)內(nèi)部真正執(zhí)行的指令,這需要花費(fèi)至少4個(gè)時(shí)鐘周期,而不是1個(gè)
至于晶體管級(jí)的我就不解釋了,你得好好學(xué)習(xí)匯編才能理解單片機(jī)的運(yùn)作。
至于這個(gè)函數(shù)為什么能延時(shí)1ms,這個(gè)是靠經(jīng)驗(yàn)來(lái)判斷的,最直接的方法就是用示波器看,以上均為推論。
本文引用地址:http://butianyuan.cn/article/201611/318542.htm11、PIC單片機(jī)的延時(shí)問(wèn)題 晶振4Mhz:
void delay()
{
unsigned int d=1000;
while(--d){;}
}
此函數(shù)在4M晶體下產(chǎn)生10003us的延時(shí),也就是10MS。
問(wèn)題:我剛算了一下他應(yīng)該執(zhí)行了999條指令,1條單周期的指令也才1US,那就是999us,為什么會(huì)有10ms的延時(shí)?
1:for(x=100;--x;){;} : 2: for(x=0;x<100;x++){;} 2句話相同
第一句:X的值范圍是不是 1~99?為什么?
第二句:X的范圍是不是0~99?為什么?這么算的。我知道符號(hào)在前在后的區(qū)別。2句話應(yīng)該是不一樣的才對(duì)??!
答:
問(wèn)題1:“我剛算了一下他應(yīng)該執(zhí)行了999條指令”因?yàn)槟闼沐e(cuò)了。延時(shí)時(shí)間是由產(chǎn)生的匯編代碼所決定的,C語(yǔ)言語(yǔ)句只是個(gè)假象,千萬(wàn)不要以為C語(yǔ)言一行就是一條指令!此處由于涉及到雙字節(jié)減法,因此會(huì)有額外的判斷,編譯結(jié)果每次循環(huán)耗費(fèi)幾十個(gè)周期毫不奇怪。
問(wèn)題2:前一句x從100開(kāi)始遞減,遞減至1時(shí)退出循環(huán)。后一句x從0開(kāi)始遞增,遞增到100時(shí)退出循環(huán)。所謂“2句話”相同僅僅是指這兩個(gè)循環(huán)體的循環(huán)次數(shù)相同。實(shí)際上兩個(gè)循環(huán)的執(zhí)行過(guò)程是完全不同的,所消耗時(shí)間也有可能不同。
12、stc單片機(jī)的延時(shí)問(wèn)題 ,STC10F08XE單片機(jī),晶振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_();
}
}
}
當(dāng)uldata=1時(shí)延時(shí)多少秒?
請(qǐng)給出具體算法…………
答:用keil轉(zhuǎn)換成匯編語(yǔ)句,然后對(duì)照指令表計(jì)算就行了
13、我想用單片機(jī)連接不斷地向電腦發(fā)數(shù),如下:
while (1)
{
send_char(9);
delay(n);
}
如每發(fā)送一個(gè)數(shù),應(yīng)延時(shí)多少微妙好呢?即一般最短能延時(shí)多少微米呢?如延時(shí)太長(zhǎng)的話,那發(fā)送很多數(shù)據(jù)不就用很長(zhǎng)時(shí)間嗎?
答:不做太多的串口處理分析,只順著你的問(wèn)題和你的方法說(shuō)說(shuō):
先考慮下串口的速率 假設(shè)9600,那么發(fā)送一個(gè)字符要多久?
(9600bit/S) / 10bit(一個(gè)字符1+8+1) = 960字符/秒 約 1ms/byte
也就是說(shuō)你如果在1ms內(nèi)發(fā)送超過(guò)一個(gè)字符就沒(méi)意義了,硬件速度達(dá)不到。
while(1)
{
send_char(9);
delay(n);
}
這個(gè)循環(huán)是執(zhí)行周期也就十幾微秒+delay()的延遲,所以任何小于1040微秒的延遲對(duì)串口硬件來(lái)說(shuō)沒(méi)意義,上一個(gè)還沒(méi)處理完,下一個(gè)就來(lái)了根本執(zhí)行不了嘛。
如果你send_char()里面有while(!TI);TI = 0;這樣的語(yǔ)句或有串口中斷TI的處理的話,那么實(shí)際上你的delay()已經(jīng)在發(fā)送函數(shù)里了,while(!TI);這部就是延遲等待嗎?那根本不需要主函數(shù)去延遲了,直接發(fā)就行了。
14、一個(gè)單片機(jī)延時(shí)子程序的問(wèn)題,在延時(shí)子程序那里,一直搞不明白,給r7和r6賦予0,然后下面的djnz r7,delayloop不就一直循環(huán)了,那還怎么接下去的程序?
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
答: 你的延時(shí)程序不是因?yàn)橹禐?,而是跳轉(zhuǎn)位置不對(duì),改為如下:
delay: mov r6,#0
delayloop:mov r7,#0
:djnz r7,$
djnz r6,delayloop
ret
R7,R6初值為0,但是當(dāng)DJNZ執(zhí)行時(shí),這條指令是先減1再判斷,所以0-1=255,判斷的話也不為0,仍然循環(huán)256次。
0-1=255的解釋:
0000 0000
- 0000 0001
-------------------------
1111
15、我想提兩個(gè)單片機(jī)延時(shí)與按鍵的問(wèn)題
1:如果一個(gè)程序中延時(shí)和按鍵,如果延時(shí)子程序比較長(zhǎng)(假如2秒),怎樣確保按鍵能夠得到及時(shí)響應(yīng)(假如PC正在執(zhí)行延時(shí)子程序,正在這時(shí)候有按鍵輸入,不是響應(yīng)不了)——,,,前提是不能用定時(shí)器定時(shí)掃描,和中斷來(lái)做,因?yàn)槎〞r(shí)器和中斷我另有其他用途
2:?jiǎn)纹瑱C(jī)沒(méi)有串口。怎樣才能使得他與24C02進(jìn)行通信(24C02是具有2K內(nèi)存的EEPROM)
答:
首先明確一點(diǎn)你說(shuō)單片機(jī)沒(méi)有串口,應(yīng)該是指沒(méi)有I2C口吧。
1 在延時(shí)程序里面加入按鍵的檢測(cè)
2 用IO口模擬I2C時(shí)序讀寫(xiě)
16、51單片機(jī)延時(shí)小程序,求高手解釋什么意思?
delay200ms:
mov r2,#82
l0:mov r1,#116
l1:mov r0,#9
djnz r0,$
djnz r1,l1
djnz r2,l0
ret
答:以下是每條指令的時(shí)間,T為一個(gè)機(jī)器周期
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
以上共三層循環(huán),忽略部分指令,最簡(jiǎn)單算法是:
2*9*116*82=171216
不忽略指令是:
1+(1+(1+2*9+2)*116+2)*82+2=200001
因此延時(shí)時(shí)間大約為200ms
17、于51單片機(jī)延遲時(shí)間的問(wèn)題
uchar i;i--;
uint i;i--;
這兩條語(yǔ)句在12M晶振下運(yùn)行時(shí)間分別是多少??
答:一個(gè)時(shí)鐘周期,2us,共4us
18、周期為6MHZ的單片機(jī)延時(shí)10秒的子程序的怎么編?
答:/
* 名稱 : Delay()
* 功能 : 延時(shí),延時(shí)時(shí)間為 10ms * del。這是通過(guò)軟件延時(shí),有一定誤差。
* 輸入 : del
* 輸出 : 無(wú)
*/
void Delay(uint del)
{
uint i,j;
for(i=0; ifor(j=0; j<1827; j++) //這個(gè)是通過(guò)軟件仿真得出的數(shù)
;
}
這個(gè)是晶振為12mhz的單片機(jī)延時(shí)10ms的程序,你只要在這個(gè)基礎(chǔ)上減小一倍就行了,當(dāng)然至于具體值還是要調(diào)試下的。
19、片機(jī)的有些程序需要調(diào)用延時(shí)程序,如何能合理的安排循環(huán)次數(shù)以及空操作的個(gè)數(shù)?
答:用匯編的話就根據(jù)你的當(dāng)前晶振頻率去推算你的指令周期,然后結(jié)合你需要延遲的時(shí)間,編寫(xiě)延遲程序,用C的話還是要看最后生成的匯編碼是什么樣的了。最簡(jiǎn)單的方法就是寫(xiě)好程序以后再編譯器里軟仿真看時(shí)間。贊同2| 評(píng)論(1)
20、單片機(jī)延時(shí)程序問(wèn)題
延時(shí)程序 void delay(uint dt)
{
uchar bt;
for(;dt;dt--);
for(bt=0;bt<255;bt++);
}
編譯時(shí)有警告C:DOCUMENTS AND SETTINGSADMINISTRATOR桌面字 310 點(diǎn)陣LED顯示.C(46): warning C235: parameter 1: different types
為什么?求大俠指點(diǎn)
答:某個(gè)函數(shù)傳參類型與聲明類型不符。
另外你這個(gè)for(;dt;dt--);沒(méi)有起到外層循環(huán)的作用……
二、單片機(jī)中斷問(wèn)題30例
1、單片機(jī)外中斷INT0為下降沿觸發(fā),當(dāng)中斷被觸發(fā)后cpu執(zhí)行中斷程序,若本次中斷的程序還未執(zhí)行完INT0又來(lái)了一個(gè)相同的下降沿中斷信號(hào)怎么辦?cpu會(huì)怎么處理?若是定時(shí)器中斷呢?串口中斷呢?求解釋
答:再來(lái)一個(gè)INT0信號(hào)不會(huì)執(zhí)行。相同的優(yōu)先級(jí)不會(huì)打斷正在執(zhí)行的中斷。
一. 如果是高優(yōu)先級(jí)的中斷來(lái)了,會(huì)打斷低優(yōu)先級(jí)的正在執(zhí)行的中斷而執(zhí)行高優(yōu)先級(jí)的中斷。
51單片機(jī)的默認(rèn)(此時(shí)的IP寄存器不做設(shè)置)中斷優(yōu)先級(jí)為:
外部中斷0 > 定時(shí)/計(jì)數(shù)器0 > 外部中斷1 > 定時(shí)/計(jì)數(shù)器1 > 串行中斷;
當(dāng)同時(shí)有幾種中斷到達(dá)時(shí),高優(yōu)先級(jí)中斷會(huì)先得到服務(wù)。
例如:當(dāng)計(jì)數(shù)器0中斷和外部中斷1(優(yōu)先級(jí) 計(jì)數(shù)器0中斷>外部中斷1)同時(shí)到達(dá)時(shí),會(huì)進(jìn)入計(jì)時(shí)器0的中斷服務(wù)函數(shù);但是在外部中斷1的中斷服務(wù)函數(shù)正在服務(wù)的情況下,這時(shí)候任何中斷都是打斷不了它的,包括邏輯優(yōu)先級(jí)比它高的外部中斷0計(jì)數(shù)器0中斷。
51單片機(jī)的中斷優(yōu)先級(jí)控制寄存器IP可以把默認(rèn)的中斷優(yōu)先級(jí)設(shè)置為高或低級(jí),
例如默認(rèn)是外部中斷0 > 定時(shí)/計(jì)數(shù)器0 > 外部中斷1 > 定時(shí)/計(jì)數(shù)器1 > 串行中斷;
現(xiàn)在設(shè)為定時(shí)1 和串行中斷為高優(yōu)先級(jí) 其它為低 ,那么中斷0執(zhí)行時(shí)會(huì)被定時(shí)器1 或串行中斷打斷,如果設(shè)定的兩個(gè)高優(yōu)先級(jí)定時(shí)/計(jì)數(shù)器1 和串行中斷同時(shí)響應(yīng),會(huì)再自然排隊(duì),先執(zhí)行定時(shí)1中斷再執(zhí)行串行中斷。
2、單片機(jī)中斷問(wèn)題,中斷3為什么不執(zhí)行,整個(gè)程序有什么不對(duì)的地方呢?
#include
#define uint unsigned int
#define uchar unsigned char
sbit p1_0=P1^0;
sbit p1_1=P1^1;
sbit p1_2=P1^2;
sbit p1_3=P1^3;
sbit p1_4=P1^4;
sbit p1_5=P1^5;
uchar PWM_T1 = 0;
uchar PWM_T2 = 0;
uint i,m;
void delay(uint z)
{
for(i=z;i>0;i--)
for(m=0;m<110;m++);
}
void PWM_value_left(int pwm_set)
{
PWM_T1=pwm_set;
}
void PWM_value_right(int pwm_set)
{
PWM_T2=pwm_set;
}
void main(void)
{
bit flag = 1;
uint n;
TMOD=0x22;
TH0=241;
TH1=241;
TL0=241;
TL1=241;
TR0=1;
TR1=1;
ET0=1;
ET1=1;
EA=1;
P1=0xf0;
delay(20);
PWM_value_left(7);
PWM_value_right(10);
delay(100);
PWM_value_left(8);
PWM_value_right(9);
delay(100);
PWM_value_left(9);
PWM_value_right(8);
delay(100);
PWM_value_left(10);
PWM_value_right(7);
}
timer0() interrupt 1 using 2
{
static uint t ;
t++;
if(t==10)
{
t=0;
p1_0=1;
p1_1=0;
}
if(PWM_T1==t)
P1=P1&0xfc;
}
timer1() interrupt 3
{
static uint t1 ;
t1++;
if(t1==10)
{
t1=0;
p1_2=1;
p1_3=0;
}
if(PWM_T2==t1)
P1=P1&0xf3;
}
答:沒(méi)有主循環(huán),
沒(méi)有等到中斷3
程序運(yùn)行一次就跑飛了?。。?br />在
void main(void)
{
//...你的程序
//在這里加 死循環(huán),等待中斷
while(1)
{
;
}
}
而且,中斷響應(yīng)函數(shù)里必須要清中斷標(biāo)志位(你的沒(méi)有)!
3、各位大俠幫我看一下我寫(xiě)的51單片機(jī)C程序中斷有沒(méi)有問(wèn)題,執(zhí)行中斷后不能繼續(xù)執(zhí)行主程序,注:P3.2口一直接
注:P3.2口一直接地,程序如下:
#include
sbit dula=P2^6;
sbit wela=P2^7;
sbit d0=P1^0;
sbit d1=P1^1;
sbit d2=P1^2;
sbit d3=P1^3;
sbit d4=P1^4;
sbit d5=P1^5;
sbit d6=P1^6;
sbit d7=P1^7;
#define uchar unsigned char
#define uint unsigned int
uchar num;
uchar code table[]={
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71};
void delay(uint z);
void main()
{
EA=1;
EX0=1;
IT0=0;
wela=1;
P0=0xc0;
wela=0;
while(1)
{
for(num=0;num<16;num++)
{
dula=1;
P0=table[num];
dula=0;
delay(1000);
}
}
}
void delay(uint z)
{
uint a,b;
for(a=z;a>0;a--)
for(b=110;b>0;b--);
}
void exter0() interrupt 0
{
uint c;
for(c=0;c<25000;c++);
d0=0;
for(c=0;c<25000;c++);
d0=1;
for(c=0;c<25000;c++);
d1=0;
for(c=0;c<25000;c++);
d1=1;
for(c=0;c<25000;c++);
d2=0;
for(c=0;c<25000;c++);
d2=1;
for(c=0;c<25000;c++);
d3=0;
for(c=0;c<25000;c++);
d3=1;
for(c=0;c<25000;c++);
d4=0;
for(c=0;c<25000;c++);
d4=1;
for(c=0;c<25000;c++);
d5=0;
for(c=0;c<25000;c++);
d5=1;
for(c=0;c<25000;c++);
d6=0;
for(c=0;c<25000;c++);
d6=1;
for(c=0;c<25000;c++);
d7=0;
for(c=0;c<25000;c++);
d7=1;
}
答:
IT0=0;//低電平觸發(fā),只要單片機(jī)監(jiān)測(cè)到是低電平,就觸發(fā)中斷
你P3.2一直接地,一直是低電平,那中斷就不斷的執(zhí)行,當(dāng)然回不到主程序中了。
改成IT0=1;//下降沿觸發(fā),單片機(jī)監(jiān)測(cè)到高電平到電平跳變,就觸發(fā)中斷
就算P3.2一直接地,也只觸發(fā)一次,中斷執(zhí)行完了,就回到主程序中了。
4、我的單片機(jī)這個(gè)程序?yàn)槭裁床荒芡耆珗?zhí)行整個(gè)程序誰(shuí)能告訴我!就是沒(méi)法執(zhí)行3次亮暗的!
2010-10-20 21:40 提問(wèn)者:3865203bin3 | 懸賞分:10
ORG 0000H
AG:MOV A,#11111110B
AG1:RL A
MOV P0,A
ACALL DELAY
DJNZ R0,AG1
ACALL DELAY
MOV A,#11111111B
MOV P1,A
ACALL DELAY
MOV P0,#00000000B
ACALL DELAY
MOV P0,#11111111B
ACALL DELAY
MOV P0,#00000000B
ACALL DELAY
MOV P0,#11111111B
ACALL DELAY
SJMP AG
DELAY:MOV R3,#10
D3:MOV R2,#200
D1:MOV R1,#250
D2JNZ R1,D2
DJNZ R2,D1
DJNZ R3,D3
RET
END
我是想執(zhí)行完流水燈亮.就然后執(zhí)行全亮全暗3次 !可是就是不會(huì)跳到全亮全暗3次~~
答:
R0沒(méi)有賦初值!另外建議不要使用前2B個(gè)地址,因?yàn)?1中斷矢量就在這個(gè)空間里。建議從0030H開(kāi)始。以下程序在keil4中仿真成功。
ORG 0000H
AJMP AG
ORG 0030H
AG:MOV A,#11111110B
MOV R0,#8
AG1:RL A
MOV P0,A
ACALL DELAY
DJNZ R0,AG1
ACALL DELAY
MOV A,#11111111B
MOV P1,A
ACALL DELAY
MOV P0,#00000000B
ACALL DELAY
MOV P0,#11111111B
ACALL DELAY
MOV P0,#00000000B
ACALL DELAY
MOV P0,#11111111B
ACALL DELAY
SJMP AG
DELAY:MOV R3,#10
D3:MOV R2,#200
D1:MOV R1,#250
D2JNZ R1,D2
DJNZ R2,D1
DJNZ R3,D3
RET
END
5、STC89C52通過(guò)兩個(gè)外部中斷P3.2和P3.3,來(lái)控制P1.0和P1.1的數(shù)碼管亮和滅,一定keil C
說(shuō)明:通過(guò)外部中斷0,P1.0的數(shù)碼管亮,中斷結(jié)束后,數(shù)碼管滅;再由外部中斷1,P1.1的數(shù)碼管亮,次中斷結(jié)束后,數(shù)碼管滅;簡(jiǎn)言之就是一個(gè)中斷只控制一個(gè)數(shù)碼管,中斷之間在功能上沒(méi)有必然的聯(lián)系,編程環(huán)境keil C51。P1.0和P1.1口上接的都是普通LED小燈,數(shù)碼管=LED小燈。
以下是我編的程序,就是一個(gè)中斷控制一個(gè)數(shù)碼管,但是當(dāng)有兩個(gè)中斷時(shí),我就抓瞎了
#include
sbit D1=P1^0;
void main()
{
D1=1;
EA=1;
EX0=1;
}
void exter() interrupt 0
{
D1=0;
}
求高手幫我改改程序,改成兩個(gè)中斷的那種,功能要求都寫(xiě)在上面了~3Q,我會(huì)去keil里面模擬的~~o()^))o
答:
/*模塊低電平有效、外部中斷0、1為低電平出發(fā)*/
#include "reg52.h"
void delay( char i)
{
unsigned char t;
while(i--)
{
for(t=0;t<108;t++);
}
}
void INT0_ROUTING() interrupt 0//外部中斷0子程序
{
P0=0xfe;//LED0點(diǎn)亮
while((P3|0xfb)==0xff);//等待外部中斷0口(P3^2松開(kāi))
delay(10);//延時(shí)去抖動(dòng)
P0=0xff;//LED0熄滅
}
void INT0_ROUTING() interrupt 2
{
P0=0xfd;//LED1點(diǎn)亮
while((P3|0xf7)==0xff);//等待外部中斷1口(P3^3松開(kāi))
delay(10);//延時(shí)去抖動(dòng)
P0=0xff;//LED1熄滅
}
void main()
{
EA=1;//中斷總開(kāi)關(guān)
EX0=1;//外部中斷0開(kāi)
EX1=1;//外部中斷1開(kāi)
/*默認(rèn)低電平觸發(fā)*/
while(1);//死循環(huán) 防止跑飛
}
6、單片機(jī)中斷問(wèn)題,下面這段程序不知道為什么只進(jìn)一次中斷,就沒(méi)有反應(yīng)了呢?
#include
#define uint unsigned int
sbit key1=P1^4;
sbit key2=P1^5;
void delay1ms(uint i)
{
uchar j;
while(i--)
{
for(j=0;j<125;j++) //1ms基準(zhǔn)延時(shí)程序
{
;
}
}
}
void init()
{
EA=1; //開(kāi)總中斷
ES=1; //開(kāi)串口中斷
TMOD= 0x21; //定時(shí)器1定時(shí)方式2,定時(shí)器1工作于8位自動(dòng)重載模式, 用于產(chǎn)生波特率
SCON = 0x50; // 設(shè)定串行口工作方式1 允許接收
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
TH1= 0xfd; //11.0592M 波特率9600
TL1= 0xfd;
PCON =0x00; // 波特率不倍增
TR1= 1; //啟動(dòng)定時(shí)器T1
TR0=1; //啟動(dòng)定時(shí)器T0
ET0=1; //打開(kāi)T0中斷
}
void key()
{
if(key2==0)
P0=0x3f;
delay1ms(5000);
P0=0xf3;
}
void mainxh()
{
while(1)
{
key();
P0=0x32;
}
}
void keybreak()
{
P0=0xf1;
delay1ms(5000);
P0=0x1f;
mainxh();
}
void main(void)
{
init();
mainxh();
}
void Time0(void) interrupt 1
{
TH0=(65536-50000)/256; //定時(shí)器T0的高8位重新賦初值
TL0=(65536-50000)%256; //定時(shí)器T0的高8位重新賦初值
if(key1==0)
keybreak();
}
這個(gè)程序上電后P0口顯示0x32;按下key2顯示0x3f;key1用于中斷,每20ms檢測(cè)是否有按下key1鍵,有的話,P0口顯示0xf1。
答 :
ORG 0000H AJMP MAIN ORG 0001H LJMP INT_0 ORG 30H MAIN:MOV SP,#8FH MOV P0,#0FFH MOV P3,#0FFH SETB IT0 SETB EA SETB EX0 LJMP START START: MOV A,#10000000B LOOP: MOV P0,A RLC A LCALL DELAY LCALL DELAY LJMP LOOP LJMP START;
這句是多余的 根本不會(huì)執(zhí)行 INT_0: PUSH ACC ;
由于p中1斷中1A被設(shè)為10所以5中7斷返回后對(duì)A移位沒(méi)有意義,o A一e直為10 ,并不d是只能中斷一1次 .
還有,不清楚key1是什么中斷,貌似是鍵盤掃描吧,
while(1)
{
key();
P0=0x32;
}
都進(jìn)入死循環(huán)了,所以跳不出來(lái),就一次中斷了。
7、新手學(xué)習(xí)avr單片機(jī)ATmage 128 遇到問(wèn)題,中斷程序被忽略問(wèn)題,找不到原因。
avr studio 4 軟件仿真時(shí),編譯通過(guò)了,單在編譯信息欄卻看到中斷程序被忽略。在軟件仿真時(shí)也發(fā)現(xiàn)中斷程序沒(méi)有執(zhí)行。不知道問(wèn)題出在哪里,我用的是avr studio 4 ATmage 128 單片機(jī).
程序如下
#include
#include
void main() //用的是TC0 溢出中斷,來(lái)控制八位LED 一秒閃爍
{
PORTE = 0xFF; //LED 關(guān) 端口高電平位關(guān)
DDRE = 0xFF;
MCUCR |=(1<
TIMSK|=(1<
TCCR0 |= (1 << CS01); //8分頻
while (1);
}
volatile unsigned int j =0;
#pragma interrupt_handler timer0_ovf_isr:17
void timer0_ovf_isr(void)
{
TCNT0 = 156; //設(shè)初值
j++;
if(j <= 5000) //中斷5000次后 執(zhí)行LED 電平翻轉(zhuǎn)
PORTE ^= 0xFF; //LED 電平翻轉(zhuǎn)
}
../lesson2.c:18: warning: ignoring #pragma interrupt_handler timer0_ovf_isr
上面是寫(xiě)的程序。還有編譯信息欄里的話。
答:
不是,你那句#pragma interrupt_handler timer0_ovf_isr:17是ICCAVR編譯軟件中寫(xiě)中斷的方式,而看你的頭文件#include 和#include 應(yīng)該是用avr studio裝GCCavr編譯軟件的寫(xiě)法,你加上把中斷成
SIGNAL(SIG_OVERFLOW0)
{
TCNT0 = 156; //設(shè)初值
j++;
if(j <= 5000) //中斷5000次后 執(zhí)行LED 電平翻轉(zhuǎn)
PORTE ^= 0xFF; //LED 電平翻轉(zhuǎn)
}
看看,記住,這是GCCAVR 編譯軟件的寫(xiě)法
8新學(xué)的C51單片機(jī),編了個(gè)電平觸發(fā)式中斷程序,不知道為什么和跳變沿的一樣了,諸位幫忙看看.
#include
#define uchar unsigned char
#define uint unsigned int
sbit d1=P1^0;
sbit dula=P2^6;
sbit wela=P2^7;
void delay(uint z);
uchar code table[]={
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71};
void main()
{
EA=1;
EX0=1;
IT0=0;
while(1)
{ d1=1;
dula=1;
P0=table[1];
dula=0;
P0=0xff;
wela=1;
P0=0xfe;
wela=0;
delay(500);
dula=1;
P0=table[2];
dula=0;
P0=0xff;
wela=1;
P0=0xfd;
wela=0;
delay(500);
dula=1;
P0=table[3];
dula=0;
P0=0xff;
wela=1;
P0=0xfb;
wela=0;
delay(500);
dula=1;
P0=table[4];
dula=0;
P0=0xff;
wela=1;
P0=0xf7;
wela=0;
delay(500);
dula=1;
P0=table[5];
dula=0;
P0=0xff;
wela=1;
P0=0xef;
wela=0;
delay(500);
dula=1;
P0=table[6];
dula=0;
P0=0xff;
wela=1;
P0=0xdf;
wela=0;
delay(500);
}
}
void delay(uint z)
{
uint x,y;
for(x=100;x>0;x--)
for(y=z;y>0;y--);
}
void enter() interrupt 0
{
d1=0;
}
答: 你這個(gè)程序中設(shè)置IT0=0,說(shuō)明是低電平觸發(fā),所以只要P3^2口一直是低電平那么主程序停止,所以發(fā)光二極管點(diǎn)亮,如果P3^2口變?yōu)楦唠娖?,主程序繼續(xù),發(fā)光二極管熄滅。另一種情況是當(dāng)IT0=1的時(shí)候是負(fù)跳變觸發(fā),就是當(dāng)P3^2口檢測(cè)到一個(gè)又高電平到低電平的跳變后,觸發(fā)中斷,在中斷函數(shù)中點(diǎn)亮燈,立即出中斷,執(zhí)行到d1=1時(shí)熄燈??吹降默F(xiàn)象就是燈閃一下,直到又檢測(cè)到一個(gè)負(fù)跳變,燈又閃一下。兩種觸發(fā)方式的現(xiàn)象是不一樣的,如果你硬件沒(méi)問(wèn)題的話。你可以把中斷函數(shù)寫(xiě)成d1=!d1試試。
9、在C51單片機(jī)中,中斷服務(wù)程序怎么撤銷中斷引腳上的低電平?
我用的是,第一個(gè)單片機(jī)輸出低電平到第二個(gè)單片機(jī)的P3^2,第二個(gè)單片機(jī)是電平觸發(fā)方式中斷
低電平觸發(fā)方式:要求低電平保持到CPU實(shí)際響應(yīng)為止,為了避勉CPU再次響應(yīng)中斷,在中斷服務(wù)程序中應(yīng)該撤除中斷引腳上的低電平。請(qǐng)問(wèn),怎么撤銷?在中斷服務(wù)程序中怎么寫(xiě)? 直接寫(xiě)P3^2=1;行嗎?
答:
第一個(gè)單片機(jī)的程序,是誰(shuí)來(lái)編寫(xiě)? 如果也是樓主,那就好辦了。
第二個(gè)單片機(jī)完成了中斷的功能,在退出之前,可以向第一個(gè)單片機(jī)回送一個(gè)脈沖;
第一個(gè)單片機(jī)收到這個(gè)脈沖,就應(yīng)該撤消送到第二個(gè)單片機(jī)的中斷申請(qǐng)信號(hào)。
----
另外,如果能算出來(lái)完成中斷的時(shí)間,第一個(gè)單片機(jī)送來(lái)的申請(qǐng)信號(hào),就不要超過(guò)這個(gè)時(shí)間,應(yīng)該及時(shí)、自動(dòng)的撤消申請(qǐng)信號(hào)。
第一個(gè)單片機(jī)送來(lái)的申請(qǐng)信號(hào),也不可過(guò)短,應(yīng)該能讓對(duì)方檢測(cè)到。
10、程序如下,我想要得到的效果是1秒左邊的電動(dòng)機(jī)轉(zhuǎn)動(dòng),同時(shí)黃燈亮,1秒右邊轉(zhuǎn)動(dòng),藍(lán)燈亮,以此循環(huán)下去,但是這個(gè)程序用上去后,左邊轉(zhuǎn)》右邊轉(zhuǎn)》左邊轉(zhuǎn)》之后就一直是左邊了,不切換了,誰(shuí)能幫我解決下問(wèn)題,感激不盡??!
#include
sbit m=P2^0;
sbit b=P2^6;
sbit y=P2^7;
unsigned char count;
void main()
{
TMOD=0x01;
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
TR0=1;
ET0=1;
EA=1;
count=0;
m=!0;
b=!1;
y=!0;
while(1)
{
if(TF0==1)
{
count++;
if(count==20)
{
m=0;
b=1;
y=0;
}
if(count==40)
{
m=!0;
b=!1;
y=!0;
}
TF0=0;
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
}
}
}
答案
#include
sbit m=P2^0;
sbit b=P2^6;
sbit y=P2^7;
unsigned char count;
void main()
{
TMOD=0x01;
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
TR0=1;
count=0;
m=!0;
b=!1;
y=!0;
while(1) {
if(TF0==1) {
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
TF0=0;
count++;
if(count==20) {
m=0; b=1; y=0;
}
if(count==40) {
count=0; //加上這句.
m=!0; b=!1; y=!0;
}
}
}
}!
用T0定時(shí)50ms,溢出20次,溢出40次,分別代表了具體的時(shí)間。 溢出40次之后,應(yīng)該從頭開(kāi)始統(tǒng)計(jì)溢出次數(shù),所以,此處應(yīng)該有count=0;。 樓主原來(lái)的程序,缺少count=0;,那么它就會(huì)繼續(xù)增加,直到65536,才自動(dòng)回到0。 這樣,時(shí)間,就難以控制了。
11、求助關(guān)于51單片機(jī)外部中斷的問(wèn)題,小弟最近在學(xué)單片機(jī),剛做了一個(gè)鍵盤掃描程序。發(fā)現(xiàn)如果外部中斷為電平觸發(fā),程序能正常運(yùn)行。但如果改為邊沿觸發(fā),在將鍵值送給顯示重開(kāi)中斷指令為EX0=1后,中斷竟然還會(huì)被觸發(fā)一次,這之后,再按鍵就不能觸發(fā)中斷了。如果將中斷程序中關(guān)中斷語(yǔ)句去掉,按鍵能被掃描,但引起中斷的次數(shù)不好說(shuō)了。請(qǐng)大俠們看看哪出問(wèn)題了。謝謝
uchar keynum,//定義全局變量按鍵時(shí)的鍵值
dpnum,//顯示值
time1,//延時(shí)計(jì)數(shù)值
topen,//延時(shí)計(jì)數(shù)控制
keyin;//外部中斷0向主程序傳遞有中斷標(biāo)識(shí),有鍵按下
keydeal;//按鍵程序調(diào)用標(biāo)志
uchar keytable[4][4]={7,8,9,/,4,5,6,*,1,2,3,-,c,0,=,+};//按實(shí)際鍵盤編值
uchar keyboard();//鍵盤掃描程序,負(fù)責(zé)鍵值掃描,判斷鍵釋放由主函數(shù)完成
void display(uchar,uchar);// 顯示子程序,
sbit keysign=P3^2;//P3.2為中斷0入口,此定義用于程序判斷是否真有鍵按下及鍵是否釋放
void main()
{uchar keybiao,keybiao1;//有鍵按下標(biāo)志,鍵放開(kāi)標(biāo)志
IE=0x89;//開(kāi)總中斷,外部中斷0,定時(shí)器中斷1
IT0=1;//中斷觸發(fā)方式
PT1=1;//中斷優(yōu)先級(jí)
TMOD=0x90;//定時(shí)器1工作方式1
TH1=(65536-5000)/256;//定時(shí)器初值高8位(定時(shí)5ms)
TL1=(65536-5000)%256;
TR1=1;//開(kāi)始計(jì)時(shí)
P2=0xf0;//給鍵盤列高電平,行低電平
keydeal=0x00;//讓鍵處理初值為0,既未處理
while(1)
{if(keyin==1) //可能有鍵按下
{
if(time1>=2)//已延時(shí)10ms;計(jì)數(shù)2次,
{if(keysign==0&&keydeal==0)
{keynum=keyboard();
keybiao=1;
keydeal=1;
topen=0;//關(guān)延時(shí)計(jì)數(shù)
}//判斷是否真有鍵按下,調(diào)用鍵盤掃描程序
else if(keybiao==0&&time1>=2&&keybiao1==0)
{EX0=1;
keyin=0;
topen=0;
}//如果沒(méi)鍵按下,重開(kāi)外部中斷0,中斷標(biāo)志清0
}
if(keybiao==1&&keysign!=0)
{keybiao=0;
time1=0;
keybiao1=1;//為防止前一次time1的影響而設(shè)的標(biāo)志
topen=1;
}
if(keybiao1==1&&time1>=2)
{keybiao1=0;
topen=0;
EX0=1;
keyin=0;//重開(kāi)外部中斷0,中斷標(biāo)志清0
keydeal=0;//重開(kāi)鍵未處理,讓程序可調(diào)用處理程序
dpnum=keynum;//將鍵值傳給顯示
}
}
}
}
void display(uchar x,uchar i)//中斷控制顯示,顯示一直持續(xù)到下次中斷到
uchar keyboard()
{uchar con1,con2,i,j;
con1=P2|0x0f;//只保留P2口高四位,便于switch
switch(con1)//通過(guò)cp可得到列為0的位
{case 0x7f:j=3;break;//j為列值
case 0xbf:j=2;break;
case 0xdf:j=1;break;
case 0xef:j=0;break;
}
for(i=0;i<=3;i++)
{P2=_crol_(0xfe,i);//依次給行賦0
con2=P2|0x0f;// 只保留P2口高四位,便于比較
if(con2!=0xff) break;
}
P2=0xf0;//給鍵盤列高電平,行低電平
return(keytable[i][j]);
}
void T1_time()interrupt 3
{TH1=(65536-5000)/256;//定時(shí)器初值高8位(定時(shí)5ms)
TL1=(65536-5000)%256;
time1++;
if(topen!=1) time1=0;//如果延時(shí)標(biāo)志不為1,不開(kāi)始計(jì)時(shí)
display(dpnum,5);
}
void int0()interrupt 0
{EX0=1;
keyin=1;//向主程序傳遞鍵按下
topen=1;//10ms延時(shí)計(jì)數(shù)開(kāi)始
}
由于字?jǐn)?shù)有限,有部分程序給刪了,顯示等部分程序應(yīng)該沒(méi)問(wèn)題,我在其它地方能正常運(yùn)行。
答:
不需要每次在進(jìn)入中斷程序后開(kāi)一次中斷;EX0=1可以去掉。
實(shí)際上,外部中斷工作在邊沿觸發(fā)方式的時(shí)候,第一次電平跳變觸發(fā)后進(jìn)入中斷程序,然后硬件自動(dòng)清除IE0中斷標(biāo)志位。但是在執(zhí)行中斷程序的過(guò)程中,如果中斷引腳再次檢測(cè)到電平跳變(負(fù)到高),那么IE0會(huì)被再次置1 。如果在退出中斷程序之前沒(méi)及時(shí)清0,那么就會(huì)再次引發(fā)一次中斷。
而按鍵的過(guò)程,不包括按下和松開(kāi)時(shí)的電平抖動(dòng),至少會(huì)產(chǎn)生兩次電平跳轉(zhuǎn)。
因此,只需在你中斷程序里適當(dāng)加一點(diǎn)延遲,再將EX=1, 改成IE0=0 。
12、我用的單片機(jī)是8051F的單片機(jī),在程序中我用了兩個(gè)中斷。一個(gè)是定時(shí)計(jì)數(shù)器2產(chǎn)生的中斷100MS一次的數(shù)據(jù)采集。另一個(gè)是向上位機(jī)發(fā)送采集來(lái)的數(shù)據(jù),使用的串口來(lái)實(shí)現(xiàn)的,用的單片機(jī)的UART來(lái)實(shí)現(xiàn)。也是一個(gè)中斷。這兩個(gè)中斷在一起工作時(shí)需要注意些什么?我的中斷程序出了一些問(wèn)題。
(就是默認(rèn)情況下,UART的中斷級(jí)別更高,但是有的時(shí)候UART的中斷不能及時(shí)響應(yīng),這是為甚?)
答:
之前和你做的一樣就兩個(gè)中斷 UART0加一個(gè)定時(shí)器 我用的是C8051F040
你向上位機(jī)發(fā)送數(shù)據(jù)使用UART0時(shí) 要確認(rèn)定時(shí)器工作完畢
T2定時(shí)中斷后 你加一個(gè)完成標(biāo)志如T2FLAG
if(T2FLAG==1) 將采集的數(shù)據(jù)放入 UART0的SBUF0 是UART0工作
你100ms的中斷時(shí)間 C8051這么快速的單片機(jī)怎么都該發(fā)送完成了吧。
13、MSP430單片機(jī)中斷嵌套,如何跳出中斷?
當(dāng)進(jìn)行A中斷時(shí),來(lái)了一個(gè)B中斷,我想讓B中斷程序執(zhí)行完后不繼續(xù)
執(zhí)行A中斷而跳出整個(gè)中斷,去執(zhí)行主程序,請(qǐng)問(wèn)這個(gè)怎么設(shè)置呢?
答:
中斷的時(shí)候會(huì)把SR狀態(tài)跟中斷下來(lái)要執(zhí)行語(yǔ)句的地址放進(jìn)堆棧中,實(shí)現(xiàn)處理完中斷以后cpu要執(zhí)行的語(yǔ)句,注意是地址先進(jìn),SR后進(jìn),出棧時(shí)SR先出,地址后出,當(dāng)然了在中斷里面可以嵌套中斷的,對(duì)可屏蔽中斷來(lái)說(shuō),主要是CPU響應(yīng)中斷以后,GIE會(huì)自動(dòng)復(fù)位,所以不能對(duì)可屏蔽中斷進(jìn)行嵌套,如果在中斷中要嵌套可屏蔽中斷的話可以開(kāi)GIE,但要注意的是如果此時(shí)正在響應(yīng)的中斷標(biāo)志還是置位的情況下會(huì)反復(fù)進(jìn)入此中斷,就像死循環(huán)一樣,這時(shí)會(huì)引起堆棧的溢出,而在響應(yīng)可屏蔽中斷時(shí),不可屏蔽中斷不受此影響,因?yàn)樗皇蹽IE的影響,只受自己?jiǎn)为?dú)的使能位影響。在堆棧中的操作原理類似。
14、MSP430單片機(jī)有幾個(gè)需要軟件清除的中斷標(biāo)志?如何清除?
(1)清除各個(gè)端口的外中斷用:PxIFG,相應(yīng)的位置0即可;
(2)清除Timer中斷用:TAIFG,TBIFG,相應(yīng)的位置0即可;
答:
MSP430的16個(gè)外中斷比如軟件清除Flag,在進(jìn)入外中斷后,首先要做的就是把相應(yīng)的PxIFG清0;
而定時(shí)器Timer中斷是自動(dòng)清除Flag;
還有在中斷嵌套的時(shí)候會(huì)用到,在進(jìn)入中斷后,MCU會(huì)自動(dòng)把全局中斷位GIE清零,這樣在進(jìn)入本中斷后就不會(huì)再相應(yīng)其他中斷,若要進(jìn)行中斷嵌套,必須在進(jìn)入中斷后把GIE再置1.
15、MCS-51系列單片機(jī)的有幾個(gè)中斷源?各中斷標(biāo)志是如何產(chǎn)生的?如何清除各中斷標(biāo)志?
答:
標(biāo)準(zhǔn)51有5個(gè)中斷向量(不算復(fù)位),分別是外部中斷0,定時(shí)器0,外部中斷1,定時(shí)器1,串行口;總共有6個(gè)中斷標(biāo)志,串行口的發(fā)送和接受共享一個(gè)中斷向量。
各個(gè)終端標(biāo)志產(chǎn)生情況如下:
外部中斷可以設(shè)置邊沿觸發(fā)或者電平觸發(fā),邊沿觸發(fā)進(jìn)入中斷程序后硬件自動(dòng)清中斷標(biāo)志,電平觸發(fā)需要軟件清標(biāo)志位;
定時(shí)器T0,T1計(jì)數(shù)溢出產(chǎn)生中斷,進(jìn)入中斷程序硬件自動(dòng)清標(biāo)志位;
串行口發(fā)送完成或者接收到數(shù)據(jù)就觸發(fā)中斷,由于是兩個(gè)中斷標(biāo)志共享一個(gè)中斷向量,所以需要在中斷程序里由軟件判斷是發(fā)送中斷還是接受中斷,并且只能由軟件清標(biāo)志位;
以上是標(biāo)準(zhǔn)51的中斷系統(tǒng),52由于多了一個(gè)T2定時(shí)器(T2定時(shí)器跟T0,T1功能相差很大,T2要強(qiáng)大很多),因此多了一個(gè)中斷向量2個(gè)中斷標(biāo)志(溢出中斷和T2外部中斷),T2中斷標(biāo)志必須由軟件清除標(biāo)志位
中斷使能位于IE寄存器
各中斷標(biāo)志位于相應(yīng)的模塊控制寄存器里面
模塊 位地位 位名稱 說(shuō)明
T1 TCON.7 TF1 T1溢出標(biāo)志
T0 TCON.5 TF0 T0溢出標(biāo)志
T2 T2CON.7 TF2 T2溢出中斷標(biāo)志
T2CON.6 EXF2 T2外部中斷標(biāo)志
外部中斷1 TCON.3 IE1 外部中斷1標(biāo)志
外部中斷0 TCON.1 IE0 外部中斷0標(biāo)志
串行口 SCON.1 TI 發(fā)送中斷標(biāo)志
SCON.0 RI 接受中斷標(biāo)志
16、MCS51單片機(jī)的匯編語(yǔ)言的中斷服務(wù)程序最多有幾個(gè)?
答:一般而言有5個(gè)對(duì):2個(gè)外中斷 ,2個(gè)定時(shí)器中斷, 1個(gè)串口中斷。
但是單片機(jī)的中斷服務(wù)資源是根據(jù)硬件的結(jié)構(gòu)設(shè)計(jì),會(huì)有不同的數(shù)量和類型的中斷服務(wù),,,因此中斷并不是對(duì)語(yǔ)言來(lái)講的,而是對(duì)于硬件資源來(lái)講的。比如52有6個(gè)中斷。
基于語(yǔ)言編譯器來(lái)講,我就舉例個(gè)人感覺(jué)最好的開(kāi)發(fā)51大系列的開(kāi)發(fā)環(huán)境Keil,其編譯器最多支持32個(gè)中斷服務(wù),,,,因此中斷對(duì)編譯來(lái)說(shuō),是一個(gè)“模擬”的概念。
17、單片機(jī)中斷改變頻率,為什么幾個(gè)輸出頻率無(wú)法改變? 程序如下?
#include
#define uchar unsigned char
#define uint unsigned int
uchar T,t1;
unsigned char data table[5] = {486,236,151,111,86} ;
sbit CLK=P2^3 ;
sbit EN=P2^0 ;
void init();
void main()
{
init();
}
void init()
{
EN=1;
T=0;
TMOD=0x01;
EA=1;
TR0=1;
ET0=1;
t1=table[T];
TH0=(65536-t1)/256;
TL0=(65536-t1)%256;
}
void timer0() interrupt 1
{
TMOD=0x01;
EA=1;
TR0=1;
ET0=1;
t1=table[T];
TH0=(65536-t1)/256;
TL0=(65536-t1)%256;
CLK=~CLK;
}
答:
T你只付了0值,怎么會(huì)變化頻率呢?你在主函數(shù)里加個(gè)T的賦值語(yǔ)句就行了,例如:while(T){T--;delay1s();}
18、單片機(jī)中斷程序的書(shū)寫(xiě)步驟?
答:
標(biāo)準(zhǔn)形式:
void 函數(shù)名(void)interrupt n using m
{函數(shù)體語(yǔ)句}
n ----中斷編號(hào)
m-----要使用工作寄存器組號(hào)
19、我想知道單片機(jī)的蜂鳴器音樂(lè)程序中斷是如何響應(yīng)的?從main主程序中如何到中斷程序?具體步驟是啥?謝謝!
#include
sbit speaker = P1^5;
unsigned char timer0h, timer0l, time;
//--------------------------------------
//單片機(jī)晶振采用11.0592MHz
// 頻率-半周期數(shù)據(jù)表 高八位 本軟件共保存了四個(gè)八度的28個(gè)頻率數(shù)據(jù)
code unsigned char FREQH[] = {
0xF2, 0xF3, 0xF5, 0xF5, 0xF6, 0xF7, 0xF8, //低音1234567
0xF9, 0xF9, 0xFA, 0xFA, 0xFB, 0xFB, 0xFC, 0xFC,//1,2,3,4,5,6,7,i
0xFC, 0xFD, 0xFD, 0xFD, 0xFD, 0xFE, //高音 234567
0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFF}; //超高音 1234567
// 頻率-半周期數(shù)據(jù)表 低八位
code unsigned char FREQL[] = {
0x42, 0xC1, 0x17, 0xB6, 0xD0, 0xD1, 0xB6, //低音1234567
0x21, 0xE1, 0x8C, 0xD8, 0x68, 0xE9, 0x5B, 0x8F, //1,2,3,4,5,6,7,i
0xEE, 0x44, 0x6B, 0xB4, 0xF4, 0x2D, //高音 234567
0x47, 0x77, 0xA2, 0xB6, 0xDA, 0xFA, 0x16}; //超高音 1234567
//--------------------------------------
//世上只有媽媽好數(shù)據(jù)表 要想演奏不同的樂(lè)曲, 只需要修改這個(gè)數(shù)據(jù)表
code unsigned char sszymmh[] = {5,1,1,5,1,1,6,1,2,5,1,2,1,2,2,7,1,4,5,1,1,5,1,1,6,1,2,5,1,2,2,2,2,1,2,4,
5,1,1,5,1,1,5,2,2,3,2,2,1,2,2,7,1,2
};
//--------------------------------------
void t0int() interrupt 1 //T0中斷程序,控制發(fā)音的音調(diào)
{
TR0 = 0; //先關(guān)閉T0
speaker = !speaker; //輸出方波, 發(fā)音
TH0 = timer0h; //下次的中斷時(shí)間, 這個(gè)時(shí)間, 控制音調(diào)高低
TL0 = timer0l;
TR0 = 1; //啟動(dòng)T0
}
//--------------------------------------
void delay(unsigned char t) //延時(shí)程序,控制發(fā)音的時(shí)間長(zhǎng)度
{
unsigned char t1;
unsigned long t2;
for(t1 = 0; t1 < t; t1++) //雙重循環(huán), 共延時(shí)t個(gè)半拍
for(t2 = 0; t2 < 8000; t2++); //延時(shí)期間, 可進(jìn)入T0中斷去發(fā)音
TR0 = 0; //關(guān)閉T0, 停止發(fā)音
}
//--------------------------------------
void song() //演奏一個(gè)音符
{
TH0 = timer0h; //控制音調(diào)
TL0 = timer0l;
TR0 = 1; //啟動(dòng)T0, 由T0輸出方波去發(fā)音
delay(time); //控制時(shí)間長(zhǎng)度
}
//--------------------------------------
void main(void)
{
unsigned char k, i;
TMOD = 1; //置T0定時(shí)工作方式1
ET0 = 1; //開(kāi)T0中斷 IE=0x82;
EA = 1; //開(kāi)CPU中斷
while(1) {
i = 0;
time = 1;
while(time) {
k = sszymmh[i] + 7 * sszymmh[i + 1] - 1;
//第i個(gè)是音符, 第i+1個(gè)是第幾個(gè)八度
timer0h = FREQH[k]; //從數(shù)據(jù)表中讀出頻率數(shù)值
timer0l = FREQL[k]; //實(shí)際上, 是定時(shí)的時(shí)間長(zhǎng)度
time = ssz
ymmh[i + 2]; //讀出時(shí)間長(zhǎng)度數(shù)值
i += 3;
song(); //發(fā)出一個(gè)音符
}
}
}
答:
你看main()函數(shù)就行了,首先進(jìn)行k、i的定義,然后是定義中斷的類型(程序中用的是定時(shí)器中斷),這個(gè)定時(shí)器有點(diǎn)特殊,它的作用是定義頻率的,頻率間隔小則聲調(diào)高,反之聲調(diào)低。這個(gè)頻率就是時(shí)間的倒數(shù)唄,所以TH的值越大,聲調(diào)越高;TL的值越小,聲調(diào)越低。接著往下走,while(1) 就是等待中斷的意思,這個(gè)程序中的定時(shí)器中斷沒(méi)有設(shè)置初值,所以中斷幾乎沒(méi)有等待,時(shí)時(shí)觸發(fā)(要是有等待時(shí)間,音樂(lè)不就連不上了么)。綜上:這個(gè)定時(shí)器中斷完成兩個(gè)任務(wù):1、使單片機(jī)時(shí)時(shí)觸發(fā)(等待時(shí)間幾乎為0);2、控制了音符的演奏頻率。
再往下 while(time) 的循環(huán)就是為演奏的音符賦值的操作了。
20、單片機(jī)中斷該什么時(shí)候進(jìn)如?
答:
中斷看是外部中斷、定時(shí)器還是串行口中斷了。
如果是外部中斷,就是p3.2、p3.3檢測(cè)到這兩個(gè)口電平變化時(shí)(假設(shè)這兩個(gè)口接上按鍵,那么當(dāng)按鍵按下時(shí)表明產(chǎn)生中斷),然后跳到中斷程序執(zhí)行。
如果是定時(shí)器中斷的話,有個(gè)中斷標(biāo)志位TFx(x表示0或者1),比如說(shuō)你設(shè)置一個(gè)1S的定時(shí)器程序,你以50ms為基準(zhǔn),20次產(chǎn)生1s的時(shí)間,然后當(dāng)50ms一過(guò),標(biāo)志位就產(chǎn)生變化,進(jìn)入定時(shí)器中斷程序執(zhí)行!
串行口中斷也是一樣有一個(gè)標(biāo)志位,接受或者發(fā)送數(shù)據(jù)滿了以后,標(biāo)志位就發(fā)生變化,然后進(jìn)入中斷執(zhí)行!
21、PIC單片機(jī)AD中斷什么時(shí)候開(kāi)啟,對(duì)AD中斷應(yīng)該怎樣理解。
答:
AD模數(shù)轉(zhuǎn)換,是把模擬電壓數(shù)值采樣進(jìn)來(lái),然后轉(zhuǎn)換成數(shù)字信號(hào)。這一采樣和轉(zhuǎn)換是需要時(shí)間的。并不是一開(kāi)AD就能讀到數(shù)字信號(hào)數(shù)據(jù)。
一般來(lái)說(shuō)其時(shí)間都只有幾微秒到幾百微秒(根據(jù)設(shè)置不同而定)。如果單片機(jī)沒(méi)有其他工作的時(shí)候,可以用循環(huán)等待的方式等AD轉(zhuǎn)換結(jié)束(轉(zhuǎn)換結(jié)束后DONE位會(huì)被置位)。但如果你的單片機(jī)還有其他工作,那就沒(méi)必要在等待它上面花費(fèi)時(shí)間。可以開(kāi)AD操作后,繼續(xù)執(zhí)行其他程序。而轉(zhuǎn)換結(jié)束后,AD中斷可以暫時(shí)斷開(kāi)現(xiàn)有炒作,而把AD數(shù)據(jù)讀進(jìn)來(lái)。這就是AD中斷的作用。
2251單片機(jī)的五個(gè)中斷分別在什么時(shí)候(什么情況)執(zhí)行里面的程序!
答:
外部中斷0 :P3.2口有低電平(IT0=0)/ 下降沿(IT0=1)。
外部中斷1 :P3.3口有低電平(IT1=0)/ 下降沿(IT1=1)。
定時(shí)器0中斷:當(dāng)定時(shí)器0計(jì)數(shù)到FFFF溢出時(shí)
定時(shí)器1中斷:當(dāng)定時(shí)器1計(jì)數(shù)到FFFF溢出時(shí)
串口中斷:串口接收到一幀?;虬l(fā)送完一幀數(shù)據(jù)都會(huì)產(chǎn)生中斷。
你網(wǎng)上找一下TCON和SCON。什么條件讓中斷標(biāo)志位的值改變。 那么就會(huì)進(jìn)入中斷服務(wù)程序去。
23、51單片機(jī),如果中斷函數(shù)比較長(zhǎng),執(zhí)行到一半又觸發(fā)了這個(gè)中斷,程序會(huì)停止從頭執(zhí)行,還是執(zhí)行結(jié)束后響應(yīng)中
答:
51單片機(jī)中,中斷分高低兩個(gè)優(yōu)先級(jí),高優(yōu)先級(jí)的中斷能打斷低優(yōu)先級(jí)的中斷。
但同級(jí)中斷是不能打斷同級(jí)中斷的!無(wú)論該中斷函數(shù)有多長(zhǎng),在執(zhí)行到一半這個(gè)中斷又發(fā)生了,還是要等到該中斷函數(shù)執(zhí)行完畢,并再執(zhí)行了一條主程序指令后才會(huì)再次進(jìn)入該中斷。
不過(guò),若樓主恰好在這個(gè)低優(yōu)先級(jí)中斷服務(wù)程序中修改了該中斷為高優(yōu)先級(jí),那么如果該中斷函數(shù)比較長(zhǎng),執(zhí)行到一半又觸發(fā)了這個(gè)中斷,則該中斷函數(shù)就會(huì)被重新從頭開(kāi)始執(zhí)行(中斷嵌套)。這是因?yàn)槌谥袛嘁酝獾钠渌袛?,?CPU 響應(yīng)該中斷,程序轉(zhuǎn)入該中斷函數(shù)前就已經(jīng)將該中斷的中斷標(biāo)志清零了。
另外,51的串口中斷比較特別,因?yàn)樾枰浖宄谥袛鄻?biāo)志,所以只要在未清串口中斷標(biāo)志前,是不會(huì)發(fā)生上述這樣的中斷嵌套的。
24、求51單片機(jī)程序,兩個(gè)計(jì)數(shù)器,主要是中斷函數(shù)的函數(shù)名以及初始化設(shè)置
答:
void into_into() interrupt 1 定時(shí)器0中斷入口函數(shù)
{
。。。。中斷服務(wù)程序。。。。
TH0=0;//
TL0=0;// 重新給T0賜值
}
void into_into() interrupt 3 定時(shí)器1中斷入口函數(shù)
{
。。。。中斷服務(wù)程序。。。。
TH1=0;//
TL1=0;// 重新給T1賜值
}
void to_to()
{
TMOD=0x11; //頂時(shí)器T0和T1工作方式1
TH0=0;//
TL0=0;// T0賜初值
TH1=0;//
TL1=0// T1賜初值
TR0=1;// 開(kāi)始記數(shù)
ET0=1;// 允許T0中斷
TR1=1;// 開(kāi)始記數(shù)
ET1=1;// 允許T1中斷
EA=1; // 打開(kāi)總中斷
}
void main()
{
INIT_T0(); //定時(shí)器中斷初始化
while(1)
{
...........
}
25、請(qǐng)教一個(gè)單片機(jī)中斷的問(wèn)題:比如來(lái)了一個(gè)脈沖,開(kāi)始中斷,但中斷里的程序執(zhí)行到一半時(shí),又來(lái)了一個(gè)脈沖,請(qǐng)問(wèn)這時(shí)中斷里的程序是從頭開(kāi)始呢還是繼續(xù)呢?
我的意思是程序就一個(gè)中斷A,來(lái)了一個(gè)脈沖,A執(zhí)行,A執(zhí)行到一半時(shí),又來(lái)了一個(gè)脈沖,通知A執(zhí)行。這時(shí)A是從頭執(zhí)行還是先不理會(huì)呢?
答:
需要具體情況具體分析,因?yàn)椴煌膯纹瑱C(jī)在中斷機(jī)制上有細(xì)微的差別,需要查他的資料。
一般來(lái)說(shuō),一個(gè)中斷源請(qǐng)求中斷,對(duì)CPU來(lái)說(shuō),是一次性的做了一個(gè)“中斷掛號(hào)”。假如當(dāng)時(shí)因條件不滿足(例如CPU正在“關(guān)中斷”,即沒(méi)有打開(kāi)“中斷允許”),而沒(méi)有響應(yīng)中斷,則掛號(hào)信息還在,這樣,將來(lái)一旦打開(kāi)了中斷允許,仍然會(huì)響應(yīng),只是晚了一點(diǎn)而已。
而中斷響應(yīng)以后,必須有辦法把這個(gè)“中斷掛號(hào)”消除掉。有的CPU的功能是:只要響應(yīng)了這個(gè)中斷,掛號(hào)就自動(dòng)消除了。也有的CPU不能自動(dòng)清除掛號(hào),必須在中斷服務(wù)程序中編入“清除中斷掛號(hào)”的操作,否則,一旦打開(kāi)了中斷允許,它又會(huì)重復(fù)發(fā)生中斷。
現(xiàn)在的大多數(shù)單片機(jī)里,中斷控制器和CPU是在同一個(gè)芯片中,它可以做到自動(dòng)消除中斷掛號(hào)。而過(guò)去許多種CPU,所配用的中斷控制器是另外一個(gè)芯片,自然就無(wú)法自動(dòng)消除了。
也有的CPU中有另外一種“不掛號(hào)”的中斷請(qǐng)求。它必須由外界(發(fā)出中斷請(qǐng)求的那個(gè)設(shè)備)來(lái)保持一直不停申請(qǐng),等到響應(yīng)中斷的時(shí)候,再設(shè)法(例如,在中斷服務(wù)程序中發(fā)出一個(gè)輸出信號(hào))通知那個(gè)設(shè)備撤銷申請(qǐng)。
大多數(shù)的CPU中,一旦響應(yīng)中斷進(jìn)入了服務(wù)程序,就把“中斷允許”關(guān)掉了。故此時(shí)如果又有下一個(gè)中斷請(qǐng)求來(lái)了,不能立即響應(yīng),只能掛一個(gè)號(hào),等以后“開(kāi)中斷”時(shí)才能再響應(yīng)。如果程序員希望能夠“嵌套中斷”(即在一次中斷服務(wù)程序的執(zhí)行中途又進(jìn)入了另一個(gè)中斷服務(wù)程序),就需要在服務(wù)程序內(nèi)編入“開(kāi)中斷”的操作。
“嵌套中斷”原則上允許“自己嵌套自己”,也就是說(shuō),一次中斷服務(wù)程序的執(zhí)行中途又被打斷并進(jìn)入了和自己一樣的中斷服務(wù)程序,并從頭到尾執(zhí)行一遍,結(jié)束后返回到先前打斷的那一點(diǎn),并繼續(xù)執(zhí)行后半截服務(wù)程序。這種情況會(huì)產(chǎn)生什么效果,是需要程序員自己考慮的。
也有的CPU具有“優(yōu)先次序”機(jī)制,可以在某一級(jí)的中斷服務(wù)程序里禁止優(yōu)先級(jí)不比自己高的其他中斷來(lái)打斷自己。同時(shí),也提供給程序員有“放棄優(yōu)先權(quán)”以及“修改優(yōu)先級(jí)”的靈活性。
而被優(yōu)先機(jī)制暫時(shí)“屏蔽”的那些較低優(yōu)先級(jí)的中斷申請(qǐng),同樣掛號(hào)仍在,以后高優(yōu)先級(jí)的中斷結(jié)束以后,還能響應(yīng)。
不過(guò)需要注意,大多數(shù)的CPU中,“中斷掛號(hào)”是只能掛一個(gè)的。也就是說(shuō),在前一次的中斷申請(qǐng)所掛的號(hào)還沒(méi)有被清除以前,又來(lái)了下一個(gè)中斷申請(qǐng),那么,第二個(gè)掛號(hào)是掛不上的。
不過(guò)某些處理器中,中斷掛號(hào)可能分成幾個(gè)層次:CPU里面是一層,外圍針對(duì)各個(gè)具體的設(shè)備,還有另外一級(jí)“預(yù)備掛號(hào)”,那就比較復(fù)雜了。
另外多說(shuō)幾句:上面已經(jīng)說(shuō),程序員可以自己決定你的中斷服務(wù)程序允許還是不允許“嵌套”。
如果不允許,您可以采用關(guān)中斷的辦法,或者利用優(yōu)先機(jī)制,來(lái)屏蔽同一中斷源的第二個(gè)中斷請(qǐng)求。
這樣,第二個(gè)中斷就不會(huì)被響應(yīng)。但它仍可以掛上一個(gè)號(hào)(只要它發(fā)生在上一個(gè)中斷掛號(hào)已經(jīng)被清除掉以后的時(shí)間)。然后,中斷服務(wù)程序結(jié)束時(shí),一般都會(huì)開(kāi)中斷并釋放優(yōu)先級(jí)屏蔽。然后,第二個(gè)中斷請(qǐng)求就會(huì)被響應(yīng),于是再一次執(zhí)行中斷服務(wù)程序。
如果允許“嵌套”,那就會(huì)如我上面所說(shuō):
一次中斷服務(wù)程序的執(zhí)行中途又被打斷并進(jìn)入了和自己一樣的中斷服務(wù)程序,并從頭到尾執(zhí)行一遍,結(jié)束后返回到先前打斷的那一點(diǎn),并繼續(xù)執(zhí)行后半截服務(wù)程序。
26、我用51單片機(jī)定時(shí)/計(jì)數(shù)器1計(jì)數(shù)為什么不計(jì)數(shù)?想讓它記數(shù)產(chǎn)生中斷讓蜂鳴器響。
sbit fengming=P1^6;
void main()
{
TMOD=0x50;
EA=1;
ET1=1;
TH1=0xff;//來(lái)一次中斷記一次數(shù)
TL1=0xff;
TR1=1;
}
void time1(void) interrupt 3
{
fengming=0;
}
答:
不知道是你在網(wǎng)頁(yè)上打錯(cuò)了,還是怎么回事。
void time1(void) interrupt 3-------》void timer1(void) interrupt 3
主程序最后,要加個(gè)死循環(huán):while(1){};
還有,你在這用了方式1,這個(gè)方式在你進(jìn)中斷后,TH1和TL1會(huì)變成0000H。你不對(duì)他重新賦值,你要等FFFFH次計(jì)數(shù),才會(huì)進(jìn)中斷。
27MCS-51 單片機(jī)定時(shí)器/計(jì)數(shù)器1的中斷入口地址是: 一共有四個(gè)A. 0003H B. 000BH C. 0013H D. 001BH,到底是是哪一個(gè)?
答:答案是D.1BH
因?yàn)椋?br />外中斷0——03h
定時(shí)器0——0bh
外中斷1——13h
定時(shí)器1——1bh
串口———23h
請(qǐng)背熟
28、我看很多程序都是主程序進(jìn)入while(1),就死在while(1)里了,然后等待外中斷。那么現(xiàn)在的問(wèn)題是我想讓它進(jìn)入外中斷完事后,跳過(guò)while(1),執(zhí)行下邊的程序,該怎么辦?
while里邊用break嗎?不知道好使不好使,還有標(biāo)志位我看是硬件自動(dòng)清零,查詢標(biāo)志應(yīng)該不能用吧,那該怎么辦呢?
答:
結(jié)束while(1)語(yǔ)句最好的方法就是使用break來(lái)跳出死循環(huán),關(guān)鍵就是選擇合適的flag(標(biāo)志位),如果說(shuō)中斷標(biāo)志位是硬件自動(dòng)清零的話,那么樓主不妨在中斷服務(wù)子程序中自己加入一個(gè)標(biāo)志位:如果用匯編語(yǔ)言的話,PSW中的F0位就可以很好的使用;如果用C的話,就可以隨便定義一個(gè)位變量,如bit a=0;。也就是說(shuō),樓主需要在程序中定義一個(gè)位變量a,在中斷服務(wù)子程序中將a置1,退出中斷后查詢a是否為1,例如:if(a) {a=0;break;}這樣就跳出了while語(yǔ)句了。
比方說(shuō),如果樓主想寫(xiě)一個(gè)等待按鍵按下中斷的程序,就可以用while(!a);而不用while(1)語(yǔ)句了。
29、我用外部中斷1,中斷一次顯示下一個(gè)數(shù),數(shù)碼管顯示沒(méi)問(wèn)題。但是我用P3-3口用導(dǎo)線連接,接觸一次地線,松開(kāi)一次,這時(shí)候數(shù)碼管顯示會(huì)亂跳,有時(shí)候加兩次數(shù),有時(shí)候加好多次數(shù),反正就是不穩(wěn)定。假如p3-3口通過(guò)按鍵接地的話,按一次按鍵一般情況會(huì)加一次數(shù),但有時(shí)候也是不穩(wěn)定,可能中斷好幾次。
程序如下:
#include
#define uint unsigned int
#define uchar unsigned char
uchar code table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
uchar times;
uchar i=0;
void delay(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=112;y>0;y--);
}
void main()
{
EA=1;
EX1=1;
IT1=1;
while(1)
{
P1=table[i];
P2=0x00;
}
}
void into() interrupt 2
{ delay(1000);
i++;
if(i==10) i=1;
}
答:
是抖動(dòng)的問(wèn)題。
應(yīng)該采取消抖措施,硬件、軟件方法皆可。
----
樓主在中斷函數(shù)中,延時(shí),時(shí)間看來(lái)很是不短!
但是延時(shí)后,并沒(méi)有檢測(cè)按鍵是否還在按下,這就不能算是軟件消抖。
30、 (1) 為什么單片機(jī)有兩個(gè)外部中斷0允許位?有什么作用?
(2)在51內(nèi)核單片機(jī)中,當(dāng)允許響應(yīng)外部中斷0的中斷請(qǐng)求時(shí),其特殊功能寄存器ie中的位必須為1 es exo ea et0?
答:
(1)兩個(gè)中斷是因?yàn)橐话愕膯纹瑱C(jī)有兩個(gè)中斷源,可以實(shí)現(xiàn)兩級(jí)中斷嵌套,在實(shí)現(xiàn)復(fù)雜功能上兩級(jí)中斷嵌套很有用。
(2)
EA--總中斷允許位,必須為1
ES--串行中斷允許位,不必開(kāi),為0
EX0--外部中斷0允許位,應(yīng)為1
ET0--定時(shí)計(jì)數(shù)溢出中斷允許位,不必開(kāi),為0
評(píng)論