標題:
51單片機開發(fā)板定時器中斷和外部中斷沖突
[打印本頁]
作者:
Menida
時間:
2021-2-21 22:08
標題:
51單片機開發(fā)板定時器中斷和外部中斷沖突
想做一個四自由度的機械臂,如果不加上紅外的外部中斷的話舵機是可以好好轉(zhuǎn)動的,加上了外部中斷就有幾率轉(zhuǎn)的斷斷續(xù)續(xù)的
是定時器中斷和外部中斷沖突了嗎?(霧)還是我的代碼有問題?
至于定時器為什么設(shè)置為0.2ms,然后PWM給的數(shù)值也很奇怪,是因為我從某寶上面買的sg90不知道怎么的,給接近于高電平為0ms的PWM波到0度,接近于2ms的PWM波到180度(也可能是這里的問題?)
下面貼上單片機源代碼,還請各位大佬多多指教
/******************************************************************************
操控方式:紅外遙控和矩陣按鍵操控
舵機PWM接口接 P20\P21\P22\P23
******************************************************************************/
#include<reg52.h>
typedef unsigned int uint;
typedef unsigned char uchar;
#define GPIO_KEY P1//P1交給矩陣鍵盤
sbit dj1=P2^0;
sbit dj2=P2^1;
sbit dj3=P2^2;
sbit dj4=P2^3;
sbit key1=P3^1;
sbit key2=P3^0;
sbit IR=P3^2; //將紅外接收引腳和外部中斷0引腳定義在一起,這樣一旦接收到信號就進入中斷函數(shù)進行解碼
//紅外接收引腳和外部中斷0的引腳是一個
uchar irdata[4];//irdata[4]存的是一組用戶碼和數(shù)據(jù)碼、數(shù)據(jù)反碼
uchar KeyValue;//定義鍵值,確定按下按鍵
uint time; //定義紅外時間判斷
uchar count=0;
uchar PWM_count1=1; //此數(shù)據(jù)是多次試驗得到的結(jié)果
uchar PWM_count2=1;
uchar PWM_count3=1;
uchar PWM_count4=1;
/*延時函數(shù)*/
void delay(uint n) //延時一次約為0.01ms 用來判斷脈沖時間
/*注意:0到65535*/
{
while(n--);
}
/*獨立按鍵*/
void key()
{
if(key1==0)
{
delay(1000);
if(key1==0)
{
KeyValue=0;
PWM_count1=PWM_count2=PWM_count3=PWM_count4=1;
}
while(!key1);
}
if(key2==0)
{
delay(1000);
if(key2==0)
{
KeyValue=0; //待編寫固定動作
}
}
}
/*矩陣鍵盤*/
void KeyDown()
{
char a=0;
GPIO_KEY=0x0f;
if(GPIO_KEY!=0x0f) //讀取按鍵是否按下
{
delay(1000); //延時10ms進行消抖
if(GPIO_KEY!=0x0f) //再次檢測鍵盤是否按下
{
//測試列
GPIO_KEY=0X0F;
switch(GPIO_KEY)
{
case(0X07): KeyValue=1;break;
case(0X0b): KeyValue=2;break;
case(0X0d): KeyValue=3;break;
case(0X0e): KeyValue=4;break;
}
//測試行
GPIO_KEY=0XF0;
switch(GPIO_KEY)
{
case(0X70): KeyValue=KeyValue;break;
case(0Xb0): KeyValue=KeyValue+4;break;
case(0Xd0): KeyValue=KeyValue+8;break;
case(0Xe0): KeyValue=KeyValue+12;break;
}
}
}
while((a<50)&&(GPIO_KEY!=0xf0))
{
delay(100);
a++;
}
}
/*紅外遙控函數(shù)*/
void IR_init() //紅外遙控初始化
{
IT0=1; //外部中斷0觸發(fā)方式選擇位
EX0=1; //打開外部中斷0允許位
EA=1; //總中斷允許位
IR=1; //相當(dāng)于打開外部中斷0 此處意義為紅外接收器打開
}
void Read_IR() interrupt 0 //執(zhí)行中斷:進行讀取信號 最后產(chǎn)生鍵值
{
uint i,j,k;
delay(700);//能進入中斷函數(shù)就代表IR已經(jīng)為0,此處的延時是為了判斷延時的大體時間
if(IR==0)
{
k=1000;
while(IR==0&&(k>0))//檢測引導(dǎo)碼中9ms低電平
{
delay(1);
k--;
}
if(IR==1)//判斷高電平
{
k=500;
while(IR==1&&(k>0))//檢測引導(dǎo)碼中4.5ms高電平
{
delay(1);
k--;
}
for(i=0;i<4;i++) //開始讀取用戶碼和數(shù)據(jù)和數(shù)據(jù)反碼,因為用戶碼和數(shù)據(jù)碼、數(shù)據(jù)反碼共有4組,所以外層有四組循環(huán)
{
for(j=0;j<8;j++)//每組數(shù)據(jù)有八位,故內(nèi)層循環(huán)有八組,每次循環(huán)讀一位
{
if(IR==0)
{
k=70;
while(IR==0&&(k>0))//檢測0.56ms的低電平
{
k--;
delay(1);
}
}
if(IR==1)//進入高電平時間,這一塊比較核心,它判斷了高電平持續(xù)時間的長短
{
time=0;
k=500;
while(IR==1&&k>0)//開始檢測高電平
{
delay(10);
time++;//time是以0.1ms為單位,因為dy(10);
k--;
}
if(time>30)
return; //充當(dāng)break
irdata[i]>>=1; //移位運算,空出最高為為下一次采集做準備
if(time>=8)//如果高電平持續(xù)時間超過0.85ms代表位是“1”
irdata[i]|=0x80;//或運算,給最高為置1
time=0;//重置
}
}
}
}
if(irdata[2]!=~irdata[3])//irdata[2]與irdata[3]分別是數(shù)據(jù)碼和數(shù)據(jù)反碼 ,此操作是檢驗數(shù)據(jù)準確性(~取反)
return;
}
switch(irdata[2])//反饋鍵值所對應(yīng)的數(shù)值
{
case 0x44:KeyValue=1;break;
case 0x40:KeyValue=2;break;
case 0x43:KeyValue=3;break;
case 0x07:KeyValue=4;break;
case 0x15:KeyValue=5;break;
case 0x09:KeyValue=6;break;
case 0x16:KeyValue=7;break;
case 0x19:KeyValue=8;break;
case 0x0d:KeyValue=9;break;
case 0x0c:KeyValue=10;break;
case 0x18:KeyValue=11;break;
case 0x5e:KeyValue=12;break;
case 0x08:KeyValue=13;break;
case 0x1c:KeyValue=14;break;
case 0x5a:KeyValue=15;break;
case 0x42:KeyValue=16;break;
default:break;
}
}
/*定時器中斷初始化*/
void Timer_Init() //定時器中斷初始化
{
TMOD=0x01; //T0定時方式1
TH0=0xff; //設(shè)置定時器初值
TL0=0x48; //計數(shù)初值設(shè)置為0.2ms 每0.2ms進入一次中斷,晶振頻率:11.0592MHZ 200微秒
ET0=1; //打開定時器0的中斷
TR0=1; //打開定時器0
EA=1;
}
/*中斷發(fā)送PWM舵機控制函數(shù)*/
void Timer() interrupt 1 //定時器中斷發(fā)生,每0.2ms一次,count來記錄中斷次數(shù)
//100次中斷為20ms
//0--外部中斷0,1--定時器中斷0,2--外部中斷1,3--定時器中斷1,4--串行口中斷1
{
TR0=0; //關(guān)閉定時器
TH0=0xff;
TL0=0x48; //重新賦計數(shù)初值為0.1ms
if(count<=PWM_count1) //舵機1
{
dj1=1;
}
else
{
dj1=0;
}
if(count<=PWM_count2) //舵機2
{
dj2=1;
}
else
{
dj2=0;
}
if(count<=PWM_count3) //舵機3
{
dj3=1;
}
else
{
dj3=0;
}
if(count<=PWM_count4) //舵機4
{
dj4=1;
}
else
{
dj4=0;
}
count++;
if(count>=100)
{
count=0;
}
TR0=1; //打開定時器
}
/*main函數(shù)*/
void main()
{
IR_init(); //紅外遙控初始化 PS:紅外接收引腳P3^2
Timer_Init(); //定時器中斷初始化
while(1)
{
KeyDown();
key(); //舵機復(fù)位和自動動作
switch(KeyValue)
{
case 1:PWM_count1=1;break;//舵機1
case 2:PWM_count1=3;break;
case 3:PWM_count1=7;break;
case 4:PWM_count1=9;break;
case 5:PWM_count2=1;break;//舵機2
case 6:PWM_count2=3;break;
case 7:PWM_count2=7;break;
case 8:PWM_count2=9;break;
case 9:PWM_count3=1;break;//舵機3
case 10:PWM_count3=3;break;
case 11:PWM_count3=7;break;
case 12:PWM_count3=9;break;
case 13:PWM_count4=1;break;//舵機4
case 14:PWM_count4=3;break;
case 15:PWM_count4=7;break;
case 16:PWM_count4=9;break;
default:break;
}
}
}
復(fù)制代碼
作者:
wulin
時間:
2021-2-22 06:26
本帖最后由 wulin 于 2021-2-22 09:51 編輯
單片機玩的就是時間和邏輯。你T0中斷周期200us,EX0中斷任務(wù)完成需近百ms。外部中斷優(yōu)先于定時中斷,定時中斷當(dāng)然會頻繁丟失。所有不是必須在中斷中處理的事務(wù)都要放在主函數(shù)中處理。
作者:
黃youhui
時間:
2021-2-22 09:23
你的按鍵咋就這么奇葩呢
51hei截圖20210222092219.png
(67 KB, 下載次數(shù): 45)
下載附件
2021-2-22 09:22 上傳
作者:
npn
時間:
2021-11-29 23:11
請配置外部中斷、定時器中斷優(yōu)先級控制寄存器 :PX0、PT0
歡迎光臨 (http://www.torrancerestoration.com/bbs/)
Powered by Discuz! X3.1