概述
中斷系統(tǒng)的設(shè)置,是為了讓CPU能對外界緊急事件進(jìn)行實時處理
中斷的過程是,當(dāng)中斷請求源發(fā)出中斷請求時,CPU響應(yīng)中斷后,CPU先暫停當(dāng)時正在執(zhí)行的主程序,轉(zhuǎn)而去處理中斷服務(wù)程序,處理完后繼續(xù)原來的工作
微型機(jī)一般允許多個中斷源,當(dāng)幾個中斷源同時發(fā)出中斷時,CPU先響應(yīng)最高優(yōu)先級的中斷
中斷嵌套:CPU在處理中斷時,外界產(chǎn)生了更高優(yōu)先級的中斷,CPU暫停當(dāng)前中斷,處理了更高優(yōu)先級的中斷后,在回來處理之前的中斷,具有中斷嵌套功能的系統(tǒng)叫多級中斷系統(tǒng),不具有的叫單級中斷系統(tǒng)
如何使用中斷
此52單片機(jī)一般有8個中斷請求源,分別對應(yīng)8個中斷查詢次序號(中斷號),這些中斷被硬件所調(diào)用,通過編寫中斷查詢次序號的中斷服務(wù)程序,就可以讓CPU在響應(yīng)中斷時,執(zhí)行具體的功能代碼;4個外部中斷INT0,INT1,INT2,INT3,3個定時器中斷,定時器0中斷,定時器1中斷,定時器3中斷,1個串口中斷。
每一個中斷源都可用軟件獨立地控制為允許中斷或關(guān)閉中斷,每一個中斷源的中斷優(yōu)先級均可用軟件設(shè)置
中斷相關(guān)寄存器
中斷相關(guān)的寄存器有:中斷請求標(biāo)志寄存器TCON和SCON,中斷允許寄存器IE,中斷優(yōu)先級寄存器IP
TCON寄存器中IE0和IE1位是外部中斷請求0和1的中斷請求標(biāo)志位,IT0和IT1位用于選擇外部中斷請求是負(fù)跳變觸發(fā),還是電平觸發(fā),IT置0為電平觸發(fā),即當(dāng)加到INT上的外部中斷請求輸入信號為低電平時,將IE位置1,發(fā)出中斷,CPU介入后,硬件將IE置0
IE寄存器對中斷的允許和禁止實現(xiàn)兩級控制,可位尋址,總的中斷開關(guān)位EA(IE^7),EA置0,所有中斷都無效,EA置1,中斷源是否運行還要由低位的中斷請求允許控制位的狀態(tài)決定,置1對應(yīng)中斷源中斷允許,置0中斷無效,其他位ET0到ET2控制定時器0到2的溢出中斷,ES控制串口,EX0到EX1控制外部中斷0到1
中斷開關(guān)如圖
IP寄存器用于配置中斷請求源的優(yōu)先級,不同位配置不同中斷請求源
優(yōu)先級相同的多個中斷,CPU的響應(yīng)次序按照中斷查詢次序號來響應(yīng),0為最先,7為最低
中斷請求源順序如圖
案例一:定時器中斷控制閃燈
#include "reg52.h"
sbit ledblue =P3^7;
sbit ledyellow =P3^6;
void delay1000(){
int cnt=0;
TR0=1;
while(1){
if(TF0==1){
cnt++;
TF0=0; //定時器0爆表不中斷,那么手動將TF0位置0
TL0=0x00;
TH0=0xDC;
}
if(cnt==100)break;
}
TR0=0;
}
void ClockInit(){
TMOD&=0x00;
TMOD|=0x11;
TL0=0x00;
TH0=0xDC;
TL1=0x00;
TH1=0xDC;
}
void main(){
ledblue=1;
ledyellow=0;
ClockInit();
EA=1;
ET1=1;
TR1=1;
while(1){
ledblue=!ledblue;
delay1000();
}
}
void Lightyellow() interrupt 3 //定時器1每10ms爆表一次,爆表時TF1位置1,進(jìn)入中斷,TF1位自動置0,然后將cnt++,加到50次,即0.5s后,黃燈電平翻轉(zhuǎn)
{ static int cnt=0;
cnt++;
TL1=0x00;
TH1=0xDC;
if(cnt==50){
ledyellow=!ledyellow;
cnt=0;
}
}
案例二:定時器中斷控制SG90舵機(jī)切換角度轉(zhuǎn)動
SG90舵機(jī)
SG90舵機(jī)需要的控制信號與一般的電平信號不同,他需要的控制信號是PWM信號,即占空比不同的方波信號
舵機(jī)接線為紅線VCC,黑線GND,黃線PWM信號接收
SG90舵機(jī)有兩個規(guī)格,180°類型的360°類型,對應(yīng)PWM波的控制情況如圖
180°版本 占空比越高,轉(zhuǎn)動的角度越大,但是轉(zhuǎn)動角度有些誤差,需要微調(diào),高電平時間大概90°要1570us,180°要2570us,2720us為最大角度(略微大于180°),220us為最小角度(略微小于0°);超過2730us,先轉(zhuǎn)動到最大角度,然后按超出量多少,轉(zhuǎn)動速度就是多少的轉(zhuǎn)動速度轉(zhuǎn)動一小會,然后再快速轉(zhuǎn)動回最大角度,如此循環(huán),小于220us同理,
360°版本
0到2.5%占空比,維持最快順時針轉(zhuǎn)速不變;2.5%到7.5%占空比,占空比越高,順時針轉(zhuǎn)速越慢;7.5%完全暫停;7.5%到12.5%占空比,占空比越高,逆時針轉(zhuǎn)速越快;12.5%占空比往上,維持最快逆時針轉(zhuǎn)速不變
SG90舵機(jī)還分為數(shù)字電機(jī)和模擬電機(jī),數(shù)字電機(jī),給一次PWM信號就能轉(zhuǎn)動,模擬電機(jī)需要在一段時間內(nèi)持續(xù)給PWM信號才能轉(zhuǎn)動
我們采用的是180類型的模擬信號SG90舵機(jī)
注意:一般信號周期是固定的,對于控制不同儀器,可能信號周期會有所變化;而對于相應(yīng)信號周期占空比可以變化,用來控制程度
什么是PWM
PWM是脈沖寬度調(diào)制,通過對一系列脈沖的寬度進(jìn)行調(diào)制,通過調(diào)節(jié)占空比,等效出需要的模擬信號波形,相當(dāng)于用調(diào)節(jié)高低電平的時間長度來等效模擬信號,PWM給出的信號仍然是數(shù)字的,簡而言之,PWM是一種對模擬信號電平進(jìn)行數(shù)字編碼的方法,比如1s內(nèi)給持續(xù)5v的電壓信號,占空比60%,相當(dāng)于是1s內(nèi)給持續(xù)3v的電壓信號,占空比20%,相當(dāng)于1s內(nèi)給持續(xù)1v的電壓信號
PWM波有兩個決定條件,一個是信號周期,另一個是占空比
信號周期:PWM波是由周期的占空比信號組成,信號周期就是一個占空比信號所占的時間長度
占空比:一個信號周期內(nèi),信號處于高電平狀態(tài)的時間占整個周期的時間,比如方波的占空比就是50%
占空比不同,表示的模擬信號不同,輸出的電壓就不同,對應(yīng)的舵機(jī)旋轉(zhuǎn)角度就不同
PWM信號可以通過C52自帶的硬件產(chǎn)生,也可以通過IO口軟件模擬產(chǎn)生,精準(zhǔn)度略差
如何控制舵機(jī)
PWM波的頻率不能太高,一般50hz,即信號周期0.02s,信號周期用定時器來控制
頻率高的話,周期就小,固定時間內(nèi)接收到的信號數(shù)量就越多,頻率低的話,周期就大,固定時間內(nèi)接收到的信號數(shù)量就越少,但是固定時間內(nèi)二者高低電平所占時間的比例是相同的,為占空比
占空比每提升2.5%,舵機(jī)就增加45°
在大于周期的一段時間內(nèi)持續(xù)輸出對應(yīng)占空比的PWM波,電機(jī)就會轉(zhuǎn)動相應(yīng)角度
如何設(shè)定定時器定時的初值
因為定時器的初值由TH位和TL位設(shè)置,所以TH位可以等于(65536-定時時長/機(jī)器周期)/256得出,
TL位可以等于(65536-定時時長/機(jī)器周期)%256得出
注意:取模運算不可以用浮點數(shù)
PWM方波如何輸出
方案1
用定時器0來輸出周期占空比的高電平,定時器1來輸出剩下周期時間的低電平。在電平跳變點(當(dāng)前即定時器爆表)進(jìn)入中斷程序,來配置下一個定時器
將PWM波分為一段時間的高電平,一段時間的低電平,不斷重復(fù),起初打開定時器1,爆表后,進(jìn)入中斷程序,在中斷程序中,設(shè)定輸出高電平和定時器0的定時初值后,打開定時器0,結(jié)束中斷程序,這樣就輸出了對應(yīng)時間的高電平,等定時器0爆表后,進(jìn)入中斷程序,在中斷程序中又設(shè)置輸出低電平和定時器1的定時初值,然后結(jié)束中斷程序
進(jìn)入中斷后要及時關(guān)閉當(dāng)前定時器,再打開下一個定時器,這樣保持定時器0運行一段時間,定時器1運行一段時間
代碼
#include "reg52.h"
#include<intrins.h>
sbit ledb=P3^7;
sbit ledy=P3^6;
sbit sg90 =P1^6;
int flag=0;
void Delay2000() //@11.0592MHz
{
unsigned char i, j, k;
_nop_();
i = 15;
j = 2;
k = 235;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void ClockInit(){
TMOD&=0x00;
TMOD|=0x11;
TL0=0x66;
TH0=0xbd;
TH1=0xfa;
TL1=0x9a;
EA=1;
ET0=1;
ET1=1;
}
void do1() interrupt 1
{
TR0=0;
sg90=0;
ledy=0;
ledb=1;
if(flag==0){
//TL1=0xcd;
//TH1=0xb9;
TH1=(65536-19500/1.085)/256;
TL1=(int)(65536-19500/1.085)%256;
}
if(flag==1){
//TL1=0x66;
//TH1=0xbd;
TH1=(65536-18500/1.085)/256;
TL1=(int)(65536-18500/1.085)%256; //取模不能用浮點數(shù),需要強轉(zhuǎn)
}
TR1=1;
}
void do2() interrupt 3
{
TR1=0;
sg90=1;
ledy=1;
ledb=0;
if(flag==0){//360°sg90舵機(jī) 2.5%占空比順時針全速轉(zhuǎn)動
// TL0=0x33;
// TH0=0xfe;
TH0=(65536-500/1.085)/256;
TL0=(int)(65536-500/1.085)%256;
}
if(flag==1){ //360°sg90舵機(jī) 7.5%占空比停止轉(zhuǎn)動
// TL0=0x9a;
// TH0=0xfa;
TH0=(65536-1500/1.085)/256;
TL0=(int)(65536-1500/1.085)%256;
}
TR0=1;
}
void main(){
ledy=1;
ledb=0;
ClockInit();
TR1=1;
while(1){
flag=!flag; //切換占空比
Delay2000();
}
}
方案2
由于占空比每提升2.5%,舵機(jī)就增加45°,如果以45度為轉(zhuǎn)動單位,那么可以將一個周期20ms秒分成40等分,每等分占0.5ms,每等分輸出高電平或低電平
用一個變量cnt記錄次數(shù),爆表一次cnt++,將定時器爆表前可計時的時長定為0.5ms,每次爆表前持續(xù)輸出高電平或者低電平,總共輸出40次,代表一個周期;cnt自加到40后,cnt置0,代表循環(huán)
每增加2.5%的占空比,40次中,輸出高電平的次數(shù)就多一次
代碼
#include "reg52.h"
#include<intrins.h>
sbit sg90 =P1^6;
sbit ledb =P3^7;
sbit ledy =P3^6;
int cnt=0;
int jd;
void Delay2000() //@11.0592MHz
{
unsigned char i, j, k;
_nop_();
i = 15;
j = 2;
k = 235;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void ClockInit(){
TMOD&=0x00;
TMOD|=0x11;
// TL0=0xff;
// TH0=0xb7;
TL1=0x33;
TH1=0xfe;
EA=1;
// ET0=1;
ET1=1;
}
void main(){
Delay2000();
ClockInit();
TR1=1;
while(1){
jd=3;
cnt=0;
TL1=0x33;
TH1=0xfe;
ledb=0;
ledy=1;
Delay2000();
jd=4;
cnt=0;
TL1=0x33;
TH1=0xfe;
ledb=1;
ledy=0;
Delay2000();
}
}
void do2() interrupt 3
{
cnt++;
if(cnt<=jd)sg90=1;
else sg90=0;
TL1=0x33;
TH1=0xfe;
if(cnt==40){
cnt=0;
}
}
案例三:超聲波模塊測距控制亮燈
超聲波模塊HC-SR04
通過發(fā)送和接收超聲波,利用時間和聲音傳播速度計算出障礙物與模塊的距離,測距范圍2cm到400cm,精度為3mm
TRIG引腳,給予至少10us的高電平,產(chǎn)生發(fā)波指令,經(jīng)過一小段時間產(chǎn)生8個40khz的超聲波方波并發(fā)送出去,發(fā)送時,ECHO引腳由低電平跳轉(zhuǎn)到高電平,當(dāng)超聲波反彈回來被接收時,ECHO引腳又高電平跳轉(zhuǎn)到低電平
計算時間,ECHO引腳進(jìn)入高電平時,打開定時器,ECHO引腳跳轉(zhuǎn)會低電平時,關(guān)閉定時器,通過定時器的差值計算出超聲波傳播的時間,距離等于時間*340/2,定時器一次可計時71106us,最大測距為1208cm,所以滿足400cm的測距范圍
代碼
#include "reg52.h"
sbit ledblue =P3^7;
sbit ledyellow =P3^6;
sbit Trig=P2^5;
sbit Echo=P2^6;
void Delay10us() //@11.0592MHz
{
unsigned char i;
i = 2;
while (--i);
}
void ClockInit(){
TMOD&=0xf0;
TMOD|=0x01;
TH0=0x00;
TH0=0x00;
}
void startHC(){
Trig=1;
Delay10us();
Trig=0;
}
void main(){
double dis=0;
double time=0;
ClockInit();
while(1){
startHC();
while(Echo==0);
TR0=1;
while(Echo==1);
TR0=0;
time=(TH0*256+TL0)*1.085;
dis=time*0.017;
if(dis<10)ledblue=0;
else ledblue=1;
TH0=0x00;
TL0=0x00;
}
}
終項目:感應(yīng)開關(guān)蓋垃圾桶
目標(biāo)實現(xiàn)
1、測距控制垃圾桶開關(guān)蓋
2、按鍵控制垃圾桶開關(guān)蓋
3、振動控制垃圾桶開關(guān)蓋
4、開關(guān)蓋時蜂鳴器響應(yīng)
需要的技術(shù)
1、垃圾桶開關(guān)蓋需要舵機(jī)轉(zhuǎn)動角度來支撐,舵機(jī)轉(zhuǎn)動不同的角度需要不同占空比的PWM波,實現(xiàn)PWM波,則需要定時器0和定時器1分別產(chǎn)生相應(yīng)時間的高低電平循環(huán),需要用到定時器中斷
2、振動控制開關(guān)蓋,如果只是把振動產(chǎn)生的信號或到測距控制開關(guān)蓋中,則有可能發(fā)生振動已經(jīng)產(chǎn)生,信號也產(chǎn)生了,但是代碼沒有捕獲到這個信號,當(dāng)運行到判斷部分時,振動信號已經(jīng)消失了,所以需要用到外部中斷,信號產(chǎn)生時同時發(fā)起外部中斷,用一個變量記錄下這個信號,下次運行到判斷部分時,能檢測到這個變量,則會控制開關(guān)蓋文章來源:http://www.zghlxwxcb.cn/news/detail-413751.html
外部中斷IT0如果置0表示低電平觸發(fā),對于模塊發(fā)出信號為低電平時會發(fā)出中斷;置1表示下降沿觸發(fā),對于模塊發(fā)出信號與高電平脈沖有效,因為發(fā)出脈沖后會跳變回低電平,跳回時發(fā)出中斷文章來源地址http://www.zghlxwxcb.cn/news/detail-413751.html
代碼
#include "reg52.h"
#include<intrins.h>
sbit ledblue =P3^7;
sbit ledyellow =P3^6;
sbit Trig =P2^5;
sbit Echo =P2^6;
sbit sg90 =P1^6;
sbit key1 =P2^1;
sbit zd =P3^2; //振動
sbit beep =P2^4; //繼電器開關(guān),用于控制喇叭
int jd=0;
int jdbake=0;
int flag=1;
int soundflag=0;
int zd_mark=0;
void Delay2000ms() //@11.0592MHz
{
unsigned char i, j, k;
_nop_();
i = 15;
j = 2;
k = 235;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void Delay100ms() //@11.0592MHz
{
unsigned char i, j;
i = 180;
j = 73;
do
{
while (--j);
} while (--i);
}
void Delay10us() //@11.0592MHz
{
unsigned char i;
i = 2;
while (--i);
}
void startHC(){
Trig=1;
Delay10us();
Trig=0;
}
double getDis(){
double time=0;
TH2=0x00;
TL2=0x00;
startHC();
while(Echo==0);
TR2=1;
while(Echo==1);
TR2=0;
time=(TH2*256+TL2)*1.085;
return (time*0.017);
}
void ClockInit(){
TMOD&=0x00;
TMOD|=0x11;
EA=1;
ET0=1;
ET1=1;
TR1=1;
}
void Sound(){
int i=0;
beep=0;
for(i;i<3;i++){
Delay100ms();
}
beep=1;
i=0;
for(i;i<3;i++){
Delay100ms();
}
}
void Clock2Init(){
TH2=0x00;
TL2=0x00;
}
void EX0Init(){
EX0=1;//開啟外部中斷
IT0=0;//中斷觸發(fā)為低電平
}
void main(){
double dis=0;
Clock2Init();
ClockInit();
EX0Init();
while(1){
dis=getDis();
if(key1==0){
Delay100ms();
flag=!flag;
if(soundflag==0){
soundflag=0;
}else {
soundflag=!soundflag;
}
}
if(flag==1){
EX0=1;
ledyellow=1;
if(dis<10||zd_mark==1){
EX0=0;
jd=180;
ledblue=0;
if(jdbake!=jd){
Sound();
}
jdbake=jd;
Delay2000ms();
zd_mark=0;
EX0=1;
}
else {
jd=0;
jdbake=jd;
ledblue=1;
Delay100ms();
}
}else{
EX0=0;
jd=180;
if(soundflag==0){
Sound(); //按鍵后只響一聲
}
soundflag=1;
Delay100ms();
ledyellow=0;
}
}
}
void Low() interrupt 1
{
TR0=0;
sg90=0;
if(jd==0){
// TL1=0xcd;
// TH1=0xb9;
TH1=(65536-(20000-500)/1.085)/256;
TL1=(int)(65536-(20000-500)/1.085)%256;
}
if(jd==180){
//TL1=0x66;
//TH1=0xbd;
TH1=(65536-(20000-2570)/1.085)/256;
TL1=(int)(65536-(20000-2570)/1.085)%256; //??×?è??£2??éò?ó???μ?êy
}
TR1=1;
}
void High() interrupt 3
{
TR1=0;
sg90=1;
if(jd==0){//×a?ˉ
// TL0=0x33;
// TH0=0xfe;
TH0=(65536-500/1.085)/256; //1570 90° 210最小度數(shù)
TL0=(int)(65536-500/1.085)%256;
}
if(jd==180){ //?Yí£
// TL0=0x9a;
// TH0=0xfa;
TH0=(65536-2570/1.085)/256; //2570 180° 2720最大度數(shù)
TL0=(int)(65536-2570/1.085)%256;
}
TR0=1;
}
void get_zdsignal() interrupt 0
{
zd_mark=1;
}
到了這里,關(guān)于51單片機(jī)——中斷的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!