一、單片機(jī)中斷問題30例
1、單片機(jī)外中斷INT0為下降沿觸發(fā),當(dāng)中斷被觸發(fā)后cpu執(zhí)行中斷程序,若本次中斷的程序還未執(zhí)行完INT0又來了一個相同的下降沿中斷信號怎么辦?cpu會怎么處理?若是定時器中斷呢?串口中斷呢?求解釋
答:再來一個INT0信號不會執(zhí)行。相同的優(yōu)先級不會打斷正在執(zhí)行的中斷。
一. 如果是高優(yōu)先級的中斷來了,會打斷低優(yōu)先級的正在執(zhí)行的中斷而執(zhí)行高優(yōu)先級的中斷。
51單片機(jī)的默認(rèn)(此時的IP寄存器不做設(shè)置)中斷優(yōu)先級為:
外部中斷0 > 定時/計(jì)數(shù)器0 > 外部中斷1 > 定時/計(jì)數(shù)器1 > 串行中斷;
當(dāng)同時有幾種中斷到達(dá)時,高優(yōu)先級中斷會先得到服務(wù)。
例如:當(dāng)計(jì)數(shù)器0中斷和外部中斷1(優(yōu)先級 計(jì)數(shù)器0中斷>外部中斷1)同時到達(dá)時,會進(jìn)入計(jì)時器0的中斷服務(wù)函數(shù);但是在外部中斷1的中斷服務(wù)函數(shù)正在服務(wù)的情況下,這時候任何中斷都是打斷不了它的,包括邏輯優(yōu)先級比它高的外部中斷0計(jì)數(shù)器0中斷。
51單片機(jī)的中斷優(yōu)先級控制寄存器IP可以把默認(rèn)的中斷優(yōu)先級設(shè)置為高或低級,
例如默認(rèn)是外部中斷0 > 定時/計(jì)數(shù)器0 > 外部中斷1 > 定時/計(jì)數(shù)器1 > 串行中斷;
現(xiàn)在設(shè)為定時1 和串行中斷為高優(yōu)先級 其它為低 ,那么中斷0執(zhí)行時會被定時器1 或串行中斷打斷,如果設(shè)定的兩個高優(yōu)先級定時/計(jì)數(shù)器1 和串行中斷同時響應(yīng),會再自然排隊(duì),先執(zhí)行定時1中斷再執(zhí)行串行中斷。
2、單片機(jī)中斷問題,中斷3為什么不執(zhí)行,整個程序有什么不對的地方呢?
#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;
}
答:沒有主循環(huán),
沒有等到中斷3
程序運(yùn)行一次就跑飛了!!!
在
void main(void)
{
//...你的程序
//在這里加 死循環(huán),等待中斷
while(1)
{
;
}
}
而且,中斷響應(yīng)函數(shù)里必須要清中斷標(biāo)志位(你的沒有)!
3、各位大俠幫我看一下我寫的51單片機(jī)C程序中斷有沒有問題,執(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++);[!--empirenews.page--]
d7=0;
for(c=0;c<25000;c++);
d7=1;
}
答:
IT0=0;//低電平觸發(fā),只要單片機(jī)監(jiān)測到是低電平,就觸發(fā)中斷
你P3.2一直接地,一直是低電平,那中斷就不斷的執(zhí)行,當(dāng)然回不到主程序中了。
改成IT0=1;//下降沿觸發(fā),單片機(jī)監(jiān)測到高電平到電平跳變,就觸發(fā)中斷
就算P3.2一直接地,也只觸發(fā)一次,中斷執(zhí)行完了,就回到主程序中了。
4、我的單片機(jī)這個程序?yàn)槭裁床荒芡耆珗?zhí)行整個程序誰能告訴我!就是沒法執(zhí)行3次亮暗的!
2010-10-20 21:40 提問者: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次 !可是就是不會跳到全亮全暗3次~~
答:
R0沒有賦初值!另外建議不要使用前2B個地址,因?yàn)?1中斷矢量就在這個空間里。建議從0030H開始。以下程序在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通過兩個外部中斷P3.2和P3.3,來控制P1.0和P1.1的數(shù)碼管亮和滅,一定keil C
說明:通過外部中斷0【P3.2】,P1.0的數(shù)碼管亮,中斷結(jié)束后,數(shù)碼管滅;再由外部中斷1【P3.3】,P1.1的數(shù)碼管亮,次中斷結(jié)束后,數(shù)碼管滅;簡言之就是一個中斷只控制一個數(shù)碼管,中斷之間在功能上沒有必然的聯(lián)系,編程環(huán)境keil C51。P1.0和P1.1口上接的都是普通LED小燈,數(shù)碼管=LED小燈。
以下是我編的程序,就是一個中斷控制一個數(shù)碼管,但是當(dāng)有兩個中斷時,我就抓瞎了
#include
sbit D1=P1^0;
void main()
{
D1=1;
EA=1;
EX0=1;
}
void exter() interrupt 0
{
D1=0;
}
求高手幫我改改程序,改成兩個中斷的那種,功能要求都寫在上面了~【希望能有程序注釋】3Q,我會去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松開)
delay(10);//延時去抖動
P0=0xff;//LED0熄滅
}
void INT0_ROUTING() interrupt 2
{
P0=0xfd;//LED1點(diǎn)亮
while((P3|0xf7)==0xff);//等待外部中斷1口(P3^3松開)
delay(10);//延時去抖動
P0=0xff;//LED1熄滅
}
void main()
{
EA=1;//中斷總開關(guān)
EX0=1;//外部中斷0開
EX1=1;//外部中斷1開
/*默認(rèn)低電平觸發(fā)*/
while(1);//死循環(huán) 防止跑飛
}
6、單片機(jī)中斷問題,下面這段程序不知道為什么只進(jìn)一次中斷,就沒有反應(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)延時程序
{
;
}
}
}
void init()
{
EA=1; //開總中斷
ES=1; //開串口中斷
TMOD= 0x21; //定時器1定時方式2,定時器1工作于8位自動重載模式, 用于產(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; //啟動定時器T1
TR0=1; //啟動定時器T0
ET0=1; //打開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; //定時器T0的高8位重新賦初值
TL0=(65536-50000)%256; //定時器T0的高8位重新賦初值[!--empirenews.page--]
if(key1==0)
keybreak();
}
這個程序上電后P0口顯示0x32;按下key2顯示0x3f;key1用于中斷,每20ms檢測是否有按下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;
這句是多余的 根本不會執(zhí)行 INT_0: PUSH ACC ;
由于p中1斷中1A被設(shè)為10所以5中7斷返回后對A移位沒有意義,o A一e直為10 ,并不d是只能中斷一1次 .
還有,不清楚key1是什么中斷,貌似是鍵盤掃描吧,
while(1)
{
key();
P0=0x32;
}
都進(jìn)入死循環(huán)了,所以跳不出來,就一次中斷了。
7、新手學(xué)習(xí)avr單片機(jī)ATmage 128 遇到問題,中斷程序被忽略問題,找不到原因。
avr studio 4 軟件仿真時,編譯通過了,單在編譯信息欄卻看到中斷程序被忽略。在軟件仿真時也發(fā)現(xiàn)中斷程序沒有執(zhí)行。不知道問題出在哪里,我用的是avr studio 4 ATmage 128 單片機(jī).
程序如下
#include
#include
void main() //用的是TC0 溢出中斷,來控制八位LED 一秒閃爍
{
PORTE = 0xFF; //LED 關(guān) 端口高電平位關(guān)
DDRE = 0xFF;
MCUCR |=(1<
sei(); //開啟全局中斷
TIMSK|=(1<
TCNT0 =155; //定時器賦初值
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
上面是寫的程序。還有編譯信息欄里的話。
答:
不是,你那句#pragma interrupt_handler timer0_ovf_isr:17是ICCAVR編譯軟件中寫中斷的方式,而看你的頭文件#include
SIGNAL(SIG_OVERFLOW0)
{
TCNT0 = 156; //設(shè)初值
j++;
if(j <= 5000) //中斷5000次后 執(zhí)行LED 電平翻轉(zhuǎn)
PORTE ^= 0xFF; //LED 電平翻轉(zhuǎn)
}
看看,記住,這是GCCAVR 編譯軟件的寫法
8新學(xué)的C51單片機(jī),編了個電平觸發(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;
}
答: 你這個程序中設(shè)置IT0=0,說明是低電平觸發(fā),所以只要P3^2口一直是低電平那么主程序停止,所以發(fā)光二極管點(diǎn)亮,如果P3^2口變?yōu)楦唠娖?,主程序繼續(xù),發(fā)光二極管熄滅。另一種情況是當(dāng)IT0=1的時候是負(fù)跳變觸發(fā),就是當(dāng)P3^2口檢測到一個又高電平到低電平的跳變后,觸發(fā)中斷,在中斷函數(shù)中點(diǎn)亮燈,立即出中斷,執(zhí)行到d1=1時熄燈??吹降默F(xiàn)象就是燈閃一下,直到又檢測到一個負(fù)跳變,燈又閃一下。兩種觸發(fā)方式的現(xiàn)象是不一樣的,如果你硬件沒問題的話。你可以把中斷函數(shù)寫成d1=!d1試試。
9、在C51單片機(jī)中,中斷服務(wù)程序怎么撤銷中斷引腳上的低電平?
我用的是,第一個單片機(jī)輸出低電平到第二個單片機(jī)的P3^2,第二個單片機(jī)是電平觸發(fā)方式中斷
低電平觸發(fā)方式:要求低電平保持到CPU實(shí)際響應(yīng)為止,為了避勉CPU再次響應(yīng)中斷,在中斷服務(wù)程序中應(yīng)該撤除中斷引腳上的低電平。請問,怎么撤銷?在中斷服務(wù)程序中怎么寫? 直接寫P3^2=1;行嗎?
答:
第一個單片機(jī)的程序,是誰來編寫? 如果也是樓主,那就好辦了。
第二個單片機(jī)完成了中斷的功能,在退出之前,可以向第一個單片機(jī)回送一個脈沖;
第一個單片機(jī)收到這個脈沖,就應(yīng)該撤消送到第二個單片機(jī)的中斷申請信號。
----
另外,如果能算出來完成中斷的時間,第一個單片機(jī)送來的申請信號,就不要超過這個時間,應(yīng)該及時、自動的撤消申請信號。[!--empirenews.page--]
第一個單片機(jī)送來的申請信號,也不可過短,應(yīng)該能讓對方檢測到。
10、程序如下,我想要得到的效果是1秒左邊的電動機(jī)轉(zhuǎn)動,同時黃燈亮,1秒右邊轉(zhuǎn)動,藍(lán)燈亮,以此循環(huán)下去,但是這個程序用上去后,左邊轉(zhuǎn)》右邊轉(zhuǎn)》左邊轉(zhuǎ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定時50ms,溢出20次,溢出40次,分別代表了具體的時間。 溢出40次之后,應(yīng)該從頭開始統(tǒng)計(jì)溢出次數(shù),所以,此處應(yīng)該有count=0;。 樓主原來的程序,缺少count=0;,那么它就會繼續(xù)增加,直到65536,才自動回到0。 這樣,時間,就難以控制了。
11、求助關(guān)于51單片機(jī)外部中斷的問題,小弟最近在學(xué)單片機(jī),剛做了一個鍵盤掃描程序。發(fā)現(xiàn)如果外部中斷為電平觸發(fā),程序能正常運(yùn)行。但如果改為邊沿觸發(fā),在將鍵值送給顯示重開中斷指令為EX0=1后,中斷竟然還會被觸發(fā)一次,這之后,再按鍵就不能觸發(fā)中斷了。如果將中斷程序中關(guān)中斷語句去掉,按鍵能被掃描,但引起中斷的次數(shù)不好說了。請大俠們看看哪出問題了。謝謝
uchar keynum,//定義全局變量按鍵時的鍵值
dpnum,//顯示值
time1,//延時計(jì)數(shù)值
topen,//延時計(jì)數(shù)控制
keyin;//外部中斷0向主程序傳遞有中斷標(biāo)識,有鍵按下
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)志,鍵放開標(biāo)志
IE=0x89;//開總中斷,外部中斷0,定時器中斷1
IT0=1;//中斷觸發(fā)方式
PT1=1;//中斷優(yōu)先級
TMOD=0x90;//定時器1工作方式1
TH1=(65536-5000)/256;//定時器初值高8位(定時5ms)
TL1=(65536-5000)%256;
TR1=1;//開始計(jì)時
P2=0xf0;//給鍵盤列高電平,行低電平
keydeal=0x00;//讓鍵處理初值為0,既未處理
while(1)
{if(keyin==1) //可能有鍵按下
{
if(time1>=2)//已延時10ms;計(jì)數(shù)2次,
{if(keysign==0&&keydeal==0)
{keynum=keyboard();
keybiao=1;
keydeal=1;
topen=0;//關(guān)延時計(jì)數(shù)
}//判斷是否真有鍵按下,調(diào)用鍵盤掃描程序
else if(keybiao==0&&time1>=2&&keybiao1==0)
{EX0=1;
keyin=0;
topen=0;
}//如果沒鍵按下,重開外部中斷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;//重開外部中斷0,中斷標(biāo)志清0
keydeal=0;//重開鍵未處理,讓程序可調(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)//通過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;//定時器初值高8位(定時5ms)
TL1=(65536-5000)%256;
time1++;
if(topen!=1) time1=0;//如果延時標(biāo)志不為1,不開始計(jì)時
display(dpnum,5);
}
void int0()interrupt 0
{EX0=1;
keyin=1;//向主程序傳遞鍵按下[!--empirenews.page--]
topen=1;//10ms延時計(jì)數(shù)開始
}
由于字?jǐn)?shù)有限,有部分程序給刪了,顯示等部分程序應(yīng)該沒問題,我在其它地方能正常運(yùn)行。
答:
不需要每次在進(jìn)入中斷程序后開一次中斷;EX0=1可以去掉。
實(shí)際上,外部中斷工作在邊沿觸發(fā)方式的時候,第一次電平跳變觸發(fā)后進(jìn)入中斷程序,然后硬件自動清除IE0中斷標(biāo)志位。但是在執(zhí)行中斷程序的過程中,如果中斷引腳再次檢測到電平跳變(負(fù)到高),那么IE0會被再次置1 。如果在退出中斷程序之前沒及時清0,那么就會再次引發(fā)一次中斷。
而按鍵的過程,不包括按下和松開時的電平抖動,至少會產(chǎn)生兩次電平跳轉(zhuǎn)。
因此,只需在你中斷程序里適當(dāng)加一點(diǎn)延遲,再將EX=1, 改成IE0=0 。
12、我用的單片機(jī)是8051F的單片機(jī),在程序中我用了兩個中斷。一個是定時計(jì)數(shù)器2產(chǎn)生的中斷100MS一次的數(shù)據(jù)采集。另一個是向上位機(jī)發(fā)送采集來的數(shù)據(jù),使用的串口來實(shí)現(xiàn)的,用的單片機(jī)的UART來實(shí)現(xiàn)。也是一個中斷。這兩個中斷在一起工作時需要注意些什么?我的中斷程序出了一些問題。
(就是默認(rèn)情況下,UART的中斷級別更高,但是有的時候UART的中斷不能及時響應(yīng),這是為甚?)
答:
之前和你做的一樣就兩個中斷 UART0加一個定時器 我用的是C8051F040
你向上位機(jī)發(fā)送數(shù)據(jù)使用UART0時 要確認(rèn)定時器工作完畢
T2定時中斷后 你加一個完成標(biāo)志如T2FLAG
if(T2FLAG==1) 將采集的數(shù)據(jù)放入 UART0的SBUF0 是UART0工作
你100ms的中斷時間 C8051這么快速的單片機(jī)怎么都該發(fā)送完成了吧。
13、MSP430單片機(jī)中斷嵌套,如何跳出中斷?
當(dāng)進(jìn)行A中斷時,來了一個B中斷,我想讓B中斷程序執(zhí)行完后不繼續(xù)
執(zhí)行A中斷而跳出整個中斷,去執(zhí)行主程序,請問這個怎么設(shè)置呢?
答:
中斷的時候會把SR狀態(tài)跟中斷下來要執(zhí)行語句的地址放進(jìn)堆棧中,實(shí)現(xiàn)處理完中斷以后cpu要執(zhí)行的語句,注意是地址先進(jìn),SR后進(jìn),出棧時SR先出,地址后出,當(dāng)然了在中斷里面可以嵌套中斷的,對可屏蔽中斷來說,主要是CPU響應(yīng)中斷以后,GIE會自動復(fù)位,所以不能對可屏蔽中斷進(jìn)行嵌套,如果在中斷中要嵌套可屏蔽中斷的話可以開GIE,但要注意的是如果此時正在響應(yīng)的中斷標(biāo)志還是置位的情況下會反復(fù)進(jìn)入此中斷,就像死循環(huán)一樣,這時會引起堆棧的溢出,而在響應(yīng)可屏蔽中斷時,不可屏蔽中斷不受此影響,因?yàn)樗皇蹽IE的影響,只受自己單獨(dú)的使能位影響。在堆棧中的操作原理類似。
14、MSP430單片機(jī)有幾個需要軟件清除的中斷標(biāo)志?如何清除?
(1)清除各個端口的外中斷用:PxIFG,相應(yīng)的位置0即可;
(2)清除Timer中斷用:TAIFG,TBIFG,相應(yīng)的位置0即可;
答:
MSP430的16個外中斷比如軟件清除Flag,在進(jìn)入外中斷后,首先要做的就是把相應(yīng)的PxIFG清0;
而定時器Timer中斷是自動清除Flag;
還有在中斷嵌套的時候會用到,在進(jìn)入中斷后,MCU會自動把全局中斷位GIE清零,這樣在進(jìn)入本中斷后就不會再相應(yīng)其他中斷,若要進(jìn)行中斷嵌套,必須在進(jìn)入中斷后把GIE再置1.
15、MCS-51系列單片機(jī)的有幾個中斷源?各中斷標(biāo)志是如何產(chǎn)生的?如何清除各中斷標(biāo)志?
答:
標(biāo)準(zhǔn)51有5個中斷向量(不算復(fù)位),分別是外部中斷0,定時器0,外部中斷1,定時器1,串行口;總共有6個中斷標(biāo)志,串行口的發(fā)送和接受共享一個中斷向量。
各個終端標(biāo)志產(chǎn)生情況如下:
外部中斷可以設(shè)置邊沿觸發(fā)或者電平觸發(fā),邊沿觸發(fā)進(jìn)入中斷程序后硬件自動清中斷標(biāo)志,電平觸發(fā)需要軟件清標(biāo)志位;
定時器T0,T1計(jì)數(shù)溢出產(chǎn)生中斷,進(jìn)入中斷程序硬件自動清標(biāo)志位;
串行口發(fā)送完成或者接收到數(shù)據(jù)就觸發(fā)中斷,由于是兩個中斷標(biāo)志共享一個中斷向量,所以需要在中斷程序里由軟件判斷是發(fā)送中斷還是接受中斷,并且只能由軟件清標(biāo)志位;
以上是標(biāo)準(zhǔn)51的中斷系統(tǒng),52由于多了一個T2定時器(T2定時器跟T0,T1功能相差很大,T2要強(qiáng)大很多),因此多了一個中斷向量2個中斷標(biāo)志(溢出中斷和T2外部中斷),T2中斷標(biāo)志必須由軟件清除標(biāo)志位
中斷使能位于IE寄存器
各中斷標(biāo)志位于相應(yīng)的模塊控制寄存器里面
模塊 位地位 位名稱 說明
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ī)的匯編語言的中斷服務(wù)程序最多有幾個?
答:一般而言有5個對:2個外中斷 ,2個定時器中斷, 1個串口中斷。
但是單片機(jī)的中斷服務(wù)資源是根據(jù)硬件的結(jié)構(gòu)設(shè)計(jì),會有不同的數(shù)量和類型的中斷服務(wù),,,因此中斷并不是對語言來講的,而是對于硬件資源來講的。比如52有6個中斷。
基于語言編譯器來講,我就舉例個人感覺最好的開發(fā)51大系列的開發(fā)環(huán)境Keil,其編譯器最多支持32個中斷服務(wù),,,,因此中斷對編譯來說,是一個“模擬”的概念。
17、單片機(jī)中斷改變頻率,為什么幾個輸出頻率無法改變? 程序如下?
#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;
}[!--empirenews.page--]
答:
T你只付了0值,怎么會變化頻率呢?你在主函數(shù)里加個T的賦值語句就行了,例如:while(T){T--;delay1s();}
18、單片機(jī)中斷程序的書寫步驟?
答:
標(biāo)準(zhǔn)形式:
void 函數(shù)名(void)interrupt n using m
{函數(shù)體語句}
n ----中斷編號
m-----要使用工作寄存器組號
19、我想知道單片機(jī)的蜂鳴器音樂程序中斷是如何響應(yīng)的?從main主程序中如何到中斷程序?具體步驟是啥?謝謝!
#include
sbit speaker = P1^5;
unsigned char timer0h, timer0l, time;
//--------------------------------------
//單片機(jī)晶振采用11.0592MHz
// 頻率-半周期數(shù)據(jù)表 高八位 本軟件共保存了四個八度的28個頻率數(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ù)表 要想演奏不同的樂曲, 只需要修改這個數(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; //下次的中斷時間, 這個時間, 控制音調(diào)高低
TL0 = timer0l;
TR0 = 1; //啟動T0
}
//--------------------------------------
void delay(unsigned char t) //延時程序,控制發(fā)音的時間長度
{
unsigned char t1;
unsigned long t2;
for(t1 = 0; t1 < t; t1++) //雙重循環(huán), 共延時t個半拍
for(t2 = 0; t2 < 8000; t2++); //延時期間, 可進(jìn)入T0中斷去發(fā)音
TR0 = 0; //關(guān)閉T0, 停止發(fā)音
}
//--------------------------------------
void song() //演奏一個音符
{
TH0 = timer0h; //控制音調(diào)
TL0 = timer0l;
TR0 = 1; //啟動T0, 由T0輸出方波去發(fā)音
delay(time); //控制時間長度
}
//--------------------------------------
void main(void)
{
unsigned char k, i;
TMOD = 1; //置T0定時工作方式1
ET0 = 1; //開T0中斷 IE=0x82;
EA = 1; //開CPU中斷
while(1) {
i = 0;
time = 1;
while(time) {
k = sszymmh[i] + 7 * sszymmh[i + 1] - 1;
//第i個是音符, 第i+1個是第幾個八度
timer0h = FREQH[k]; //從數(shù)據(jù)表中讀出頻率數(shù)值
timer0l = FREQL[k]; //實(shí)際上, 是定時的時間長度
time = ssz
ymmh[i + 2]; //讀出時間長度數(shù)值
i += 3;
song(); //發(fā)出一個音符
}
}
}
答:
你看main()函數(shù)就行了,首先進(jìn)行k、i的定義,然后是定義中斷的類型(程序中用的是定時器中斷),這個定時器有點(diǎn)特殊,它的作用是定義頻率的,頻率間隔小則聲調(diào)高,反之聲調(diào)低。這個頻率就是時間的倒數(shù)唄,所以TH的值越大,聲調(diào)越高;TL的值越小,聲調(diào)越低。接著往下走,while(1) 就是等待中斷的意思,這個程序中的定時器中斷沒有設(shè)置初值,所以中斷幾乎沒有等待,時時觸發(fā)(要是有等待時間,音樂不就連不上了么)。綜上:這個定時器中斷完成兩個任務(wù):1、使單片機(jī)時時觸發(fā)(等待時間幾乎為0);2、控制了音符的演奏頻率。
再往下 while(time) 的循環(huán)就是為演奏的音符賦值的操作了。
20、單片機(jī)中斷該什么時候進(jìn)如?
答:
中斷看是外部中斷、定時器還是串行口中斷了。
如果是外部中斷,就是p3.2、p3.3檢測到這兩個口電平變化時(假設(shè)這兩個口接上按鍵,那么當(dāng)按鍵按下時表明產(chǎn)生中斷),然后跳到中斷程序執(zhí)行。
如果是定時器中斷的話,有個中斷標(biāo)志位TFx(x表示0或者1),比如說你設(shè)置一個1S的定時器程序,你以50ms為基準(zhǔn),20次產(chǎn)生1s的時間,然后當(dāng)50ms一過,標(biāo)志位就產(chǎn)生變化,進(jìn)入定時器中斷程序執(zhí)行!
串行口中斷也是一樣有一個標(biāo)志位,接受或者發(fā)送數(shù)據(jù)滿了以后,標(biāo)志位就發(fā)生變化,然后進(jìn)入中斷執(zhí)行!
21、PIC單片機(jī)AD中斷什么時候開啟,對AD中斷應(yīng)該怎樣理解。
答:
AD模數(shù)轉(zhuǎn)換,是把模擬電壓數(shù)值采樣進(jìn)來,然后轉(zhuǎn)換成數(shù)字信號。這一采樣和轉(zhuǎn)換是需要時間的。并不是一開AD就能讀到數(shù)字信號數(shù)據(jù)。
一般來說其時間都只有幾微秒到幾百微秒(根據(jù)設(shè)置不同而定)。如果單片機(jī)沒有其他工作的時候,可以用循環(huán)等待的方式等AD轉(zhuǎn)換結(jié)束(轉(zhuǎn)換結(jié)束后DONE位會被置位)。但如果你的單片機(jī)還有其他工作,那就沒必要在等待它上面花費(fèi)時間??梢蚤_AD操作后,繼續(xù)執(zhí)行其他程序。而轉(zhuǎn)換結(jié)束后,AD中斷可以暫時斷開現(xiàn)有炒作,而把AD數(shù)據(jù)讀進(jìn)來。這就是AD中斷的作用。
2251單片機(jī)的五個中斷分別在什么時候(什么情況)執(zhí)行里面的程序!
答:
外部中斷0 :P3.2口有低電平(IT0=0)/ 下降沿(IT0=1)。
外部中斷1 :P3.3口有低電平(IT1=0)/ 下降沿(IT1=1)。
定時器0中斷:當(dāng)定時器0計(jì)數(shù)到FFFF溢出時[!--empirenews.page--]
定時器1中斷:當(dāng)定時器1計(jì)數(shù)到FFFF溢出時
串口中斷:串口接收到一幀?;虬l(fā)送完一幀數(shù)據(jù)都會產(chǎn)生中斷。
你網(wǎng)上找一下TCON和SCON。什么條件讓中斷標(biāo)志位的值改變。 那么就會進(jìn)入中斷服務(wù)程序去。
23、51單片機(jī),如果中斷函數(shù)比較長,執(zhí)行到一半又觸發(fā)了這個中斷,程序會停止從頭執(zhí)行,還是執(zhí)行結(jié)束后響應(yīng)中
答:
51單片機(jī)中,中斷分高低兩個優(yōu)先級,高優(yōu)先級的中斷能打斷低優(yōu)先級的中斷。
但同級中斷是不能打斷同級中斷的!無論該中斷函數(shù)有多長,在執(zhí)行到一半這個中斷又發(fā)生了,還是要等到該中斷函數(shù)執(zhí)行完畢,并再執(zhí)行了一條主程序指令后才會再次進(jìn)入該中斷。
不過,若樓主恰好在這個低優(yōu)先級中斷服務(wù)程序中修改了該中斷為高優(yōu)先級,那么如果該中斷函數(shù)比較長,執(zhí)行到一半又觸發(fā)了這個中斷,則該中斷函數(shù)就會被重新從頭開始執(zhí)行(中斷嵌套)。這是因?yàn)槌谥袛嘁酝獾钠渌袛?,?CPU 響應(yīng)該中斷,程序轉(zhuǎn)入該中斷函數(shù)前就已經(jīng)將該中斷的中斷標(biāo)志清零了。
另外,51的串口中斷比較特別,因?yàn)樾枰浖宄谥袛鄻?biāo)志,所以只要在未清串口中斷標(biāo)志前,是不會發(fā)生上述這樣的中斷嵌套的。
24、求51單片機(jī)程序,兩個計(jì)數(shù)器,主要是中斷函數(shù)的函數(shù)名以及初始化設(shè)置
答:
void into_into() interrupt 1 定時器0中斷入口函數(shù)
{
。。。。中斷服務(wù)程序。。。。
TH0=0;//
TL0=0;// 重新給T0賜值
}
void into_into() interrupt 3 定時器1中斷入口函數(shù)
{
。。。。中斷服務(wù)程序。。。。
TH1=0;//
TL1=0;// 重新給T1賜值
}
void to_to()
{
TMOD=0x11; //頂時器T0和T1工作方式1
TH0=0;//
TL0=0;// T0賜初值
TH1=0;//
TL1=0// T1賜初值
TR0=1;// 開始記數(shù)
ET0=1;// 允許T0中斷
TR1=1;// 開始記數(shù)
ET1=1;// 允許T1中斷
EA=1; // 打開總中斷
}
void main()
{
INIT_T0(); //定時器中斷初始化
while(1)
{
...........
}
25、請教一個單片機(jī)中斷的問題:比如來了一個脈沖,開始中斷,但中斷里的程序執(zhí)行到一半時,又來了一個脈沖,請問這時中斷里的程序是從頭開始呢還是繼續(xù)呢?
我的意思是程序就一個中斷A,來了一個脈沖,A執(zhí)行,A執(zhí)行到一半時,又來了一個脈沖,通知A執(zhí)行。這時A是從頭執(zhí)行還是先不理會呢?
答:
需要具體情況具體分析,因?yàn)椴煌膯纹瑱C(jī)在中斷機(jī)制上有細(xì)微的差別,需要查他的資料。
一般來說,一個中斷源請求中斷,對CPU來說,是一次性的做了一個“中斷掛號”。假如當(dāng)時因條件不滿足(例如CPU正在“關(guān)中斷”,即沒有打開“中斷允許”),而沒有響應(yīng)中斷,則掛號信息還在,這樣,將來一旦打開了中斷允許,仍然會響應(yīng),只是晚了一點(diǎn)而已。
而中斷響應(yīng)以后,必須有辦法把這個“中斷掛號”消除掉。有的CPU的功能是:只要響應(yīng)了這個中斷,掛號就自動消除了。也有的CPU不能自動清除掛號,必須在中斷服務(wù)程序中編入“清除中斷掛號”的操作,否則,一旦打開了中斷允許,它又會重復(fù)發(fā)生中斷。
現(xiàn)在的大多數(shù)單片機(jī)里,中斷控制器和CPU是在同一個芯片中,它可以做到自動消除中斷掛號。而過去許多種CPU,所配用的中斷控制器是另外一個芯片,自然就無法自動消除了。
也有的CPU中有另外一種“不掛號”的中斷請求。它必須由外界(發(fā)出中斷請求的那個設(shè)備)來保持一直不停申請,等到響應(yīng)中斷的時候,再設(shè)法(例如,在中斷服務(wù)程序中發(fā)出一個輸出信號)通知那個設(shè)備撤銷申請。
大多數(shù)的CPU中,一旦響應(yīng)中斷進(jìn)入了服務(wù)程序,就把“中斷允許”關(guān)掉了。故此時如果又有下一個中斷請求來了,不能立即響應(yīng),只能掛一個號,等以后“開中斷”時才能再響應(yīng)。如果程序員希望能夠“嵌套中斷”(即在一次中斷服務(wù)程序的執(zhí)行中途又進(jìn)入了另一個中斷服務(wù)程序),就需要在服務(wù)程序內(nèi)編入“開中斷”的操作。
“嵌套中斷”原則上允許“自己嵌套自己”,也就是說,一次中斷服務(wù)程序的執(zhí)行中途又被打斷并進(jìn)入了和自己一樣的中斷服務(wù)程序,并從頭到尾執(zhí)行一遍,結(jié)束后返回到先前打斷的那一點(diǎn),并繼續(xù)執(zhí)行后半截服務(wù)程序。這種情況會產(chǎn)生什么效果,是需要程序員自己考慮的。
也有的CPU具有“優(yōu)先次序”機(jī)制,可以在某一級的中斷服務(wù)程序里禁止優(yōu)先級不比自己高的其他中斷來打斷自己。同時,也提供給程序員有“放棄優(yōu)先權(quán)”以及“修改優(yōu)先級”的靈活性。
而被優(yōu)先機(jī)制暫時“屏蔽”的那些較低優(yōu)先級的中斷申請,同樣掛號仍在,以后高優(yōu)先級的中斷結(jié)束以后,還能響應(yīng)。
不過需要注意,大多數(shù)的CPU中,“中斷掛號”是只能掛一個的。也就是說,在前一次的中斷申請所掛的號還沒有被清除以前,又來了下一個中斷申請,那么,第二個掛號是掛不上的。
不過某些處理器中,中斷掛號可能分成幾個層次:CPU里面是一層,外圍針對各個具體的設(shè)備,還有另外一級“預(yù)備掛號”,那就比較復(fù)雜了。
另外多說幾句:上面已經(jīng)說,程序員可以自己決定你的中斷服務(wù)程序允許還是不允許“嵌套”。
如果不允許,您可以采用關(guān)中斷的辦法,或者利用優(yōu)先機(jī)制,來屏蔽同一中斷源的第二個中斷請求。
這樣,第二個中斷就不會被響應(yīng)。但它仍可以掛上一個號(只要它發(fā)生在上一個中斷掛號已經(jīng)被清除掉以后的時間)。然后,中斷服務(wù)程序結(jié)束時,一般都會開中斷并釋放優(yōu)先級屏蔽。然后,第二個中斷請求就會被響應(yīng),于是再一次執(zhí)行中斷服務(wù)程序。
如果允許“嵌套”,那就會如我上面所說:
一次中斷服務(wù)程序的執(zhí)行中途又被打斷并進(jìn)入了和自己一樣的中斷服務(wù)程序,并從頭到尾執(zhí)行一遍,結(jié)束后返回到先前打斷的那一點(diǎn),并繼續(xù)執(zhí)行后半截服務(wù)程序。[!--empirenews.page--]
26、我用51單片機(jī)定時/計(jì)數(shù)器1計(jì)數(shù)為什么不計(jì)數(shù)?想讓它記數(shù)產(chǎn)生中斷讓蜂鳴器響。
sbit fengming=P1^6;
void main()
{
TMOD=0x50;
EA=1;
ET1=1;
TH1=0xff;//來一次中斷記一次數(shù)
TL1=0xff;
TR1=1;
}
void time1(void) interrupt 3
{
fengming=0;
}
答:
不知道是你在網(wǎng)頁上打錯了,還是怎么回事。
void time1(void) interrupt 3-------》void timer1(void) interrupt 3
主程序最后,要加個死循環(huán):while(1){};
還有,你在這用了方式1,這個方式在你進(jìn)中斷后,TH1和TL1會變成0000H。你不對他重新賦值,你要等FFFFH次計(jì)數(shù),才會進(jìn)中斷。
27MCS-51 單片機(jī)定時器/計(jì)數(shù)器1的中斷入口地址是: 一共有四個A. 0003H B. 000BH C. 0013H D. 001BH,到底是是哪一個?
答:答案是D.1BH
因?yàn)椋?/p>
外中斷0——03h
定時器0——0bh
外中斷1——13h
定時器1——1bh
串口———23h
請背熟
28、我看很多程序都是主程序進(jìn)入while(1),就死在while(1)里了,然后等待外中斷。那么現(xiàn)在的問題是我想讓它進(jìn)入外中斷完事后,跳過while(1),執(zhí)行下邊的程序,該怎么辦?
while里邊用break嗎?不知道好使不好使,還有標(biāo)志位我看是硬件自動清零,查詢標(biāo)志應(yīng)該不能用吧,那該怎么辦呢?
答:
結(jié)束while(1)語句最好的方法就是使用break來跳出死循環(huán),關(guān)鍵就是選擇合適的flag(標(biāo)志位),如果說中斷標(biāo)志位是硬件自動清零的話,那么樓主不妨在中斷服務(wù)子程序中自己加入一個標(biāo)志位:如果用匯編語言的話,PSW中的F0位就可以很好的使用;如果用C的話,就可以隨便定義一個位變量,如bit a=0;。也就是說,樓主需要在程序中定義一個位變量a,在中斷服務(wù)子程序中將a置1,退出中斷后查詢a是否為1,例如:if(a) {a=0;break;}這樣就跳出了while語句了。
比方說,如果樓主想寫一個等待按鍵按下中斷的程序,就可以用while(!a);而不用while(1)語句了。
29、我用外部中斷1,中斷一次顯示下一個數(shù),數(shù)碼管顯示沒問題。但是我用P3-3口用導(dǎo)線連接,接觸一次地線,松開一次,這時候數(shù)碼管顯示會亂跳,有時候加兩次數(shù),有時候加好多次數(shù),反正就是不穩(wěn)定。假如p3-3口通過按鍵接地的話,按一次按鍵一般情況會加一次數(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;
}
答:
是抖動的問題。
應(yīng)該采取消抖措施,硬件、軟件方法皆可。
----
樓主在中斷函數(shù)中,延時,時間看來很是不短!
但是延時后,并沒有檢測按鍵是否還在按下,這就不能算是軟件消抖。
30、 (1) 為什么單片機(jī)有兩個外部中斷0允許位?有什么作用?
(2)在51內(nèi)核單片機(jī)中,當(dāng)允許響應(yīng)外部中斷0的中斷請求時,其特殊功能寄存器ie中的位必須為1 es exo ea et0?
答:
(1)兩個中斷是因?yàn)橐话愕?strong>單片機(jī)有兩個中斷源,可以實(shí)現(xiàn)兩級中斷嵌套,在實(shí)現(xiàn)復(fù)雜功能上兩級中斷嵌套很有用。
(2)
EA--總中斷允許位,必須為1
ES--串行中斷允許位,不必開,為0
EX0--外部中斷0允許位,應(yīng)為1
ET0--定時計(jì)數(shù)溢出中斷允許位,不必開,為0
擴(kuò)展閱讀: