紅外遙控有發(fā)送和接收兩個組成部分。發(fā)送端采用單片機將待發(fā)送的二進制信號編碼調(diào)制為一系列的脈沖串信號,通過紅外發(fā)射管發(fā)射紅外信號。紅外接收完成對紅外信號的接收、放大、檢波、整形,并解調(diào)出遙控編碼脈沖。為了減少干擾, 采用的是價格便宜性能可靠的一體化紅外接收頭(HS0038, 它接收紅外信號頻率為38kHz,周期約26μ s) 接收紅外信號,它同時對信號進行放大、檢波、整形得到 TTL 電平的編碼信號,再送給單片機,經(jīng)單片機解碼并執(zhí)行去控制相關(guān)對象。具體實現(xiàn)過程如下:
(在這里特別強調(diào):編碼與解碼是一對逆過程,不僅在原理上是一對逆過程,在碼的發(fā)收過程也是互反的,即以前發(fā)射端原始信號是高電平,那接收頭輸出的就是低電平,反之亦然。因此為了保證解碼過程簡單方便,在編碼時應該直接換算成其反碼。)
1.紅外發(fā)射部分:
下圖為紅外發(fā)射部分的電路擬圖:
編碼過程:
(1) 二進制信號的調(diào)制
二進制信號的調(diào)制由單片機來完成,它把編碼后的二進制信號調(diào)制成頻率為38kHz的間斷脈沖串(用定時器來完成),相當于用二進制信號的編碼乘以頻率為38kHz的脈沖信號得到的間斷脈沖串,即是調(diào)制后用于紅外發(fā)射二極管發(fā)送的信號。
(2)PPM編碼
這種遙控編碼具有以下特征:
1遙控編碼脈沖由前導碼、16 位地址碼(8位地址碼、8 位地址碼的反碼)和 16 位操作碼(8 位操作碼、8 位操作碼的反碼)組成。前導碼:是一個遙控碼的起始部分,由一個9ms的高電平 ( 起始碼 ) 和一個4. 5ms的低電平 ( 結(jié)果碼 )組成,作為接受數(shù)據(jù)的準備脈沖。
16位地址碼:能區(qū)別不同的紅外遙控設備,防止不同機種遙控碼互相干擾。
16 位操作碼:用來執(zhí)行不同的操作。
2采用脈寬調(diào)制的串行碼,以脈寬為0.56ms、間隔0.56ms、周期為1.12ms的組合表示二進制的“0”;以脈寬為1.68ms、間隔0.56ms、周期為2.24ms的組合表示二進制的“1”。
(3)發(fā)送程序
#include 《AT89X51.h》
static bit OP; //紅外發(fā)射管的亮滅控制位
static unsigned int count; //延時計數(shù)器
static unsigned int endcount; //終止延時計數(shù)
static unsigned char flag; //紅外發(fā)送標志
sbit P3_4=P3^4;
char iraddr1; //十六位地址的第一個字節(jié)
char iraddr2; //十六位地址的第二個字節(jié)
void SendIRdata(char p_irdata);//發(fā)送子函數(shù)
void delay();
void main(void)
{
count = 0;
flag = 0; //無載波
OP = 0; //不亮
P3_4 = 0; //在后面會發(fā)現(xiàn)用OP賦值的
EA = 1; //允許CPU中斷
TMOD = 0x11; //設定時器0和1為16位模式1
ET0 = 1; //定時器0中斷允許
TH0 = 0xFF;
TL0 = 0xE6; //設定時值0為38K 也就是每隔26us中斷一次
TR0 = 1;//開始計數(shù)
iraddr1=3;//自定義的一個地址
iraddr2=252;//地址反碼
do{
delay();
SendIRdata(12);
}while(1);
}
//定時器0中斷處理
void timeint(void) interrupt 1
{
TH0=0xFF;
TL0=0xE6; //設定時值為38K 也就是每隔26us中斷一次
count++;
if (flag==1)
{OP=~OP; }//如果是待發(fā)送的有效數(shù)據(jù)flag=1,就在此產(chǎn)生載波(亮滅交變)
else
{OP = 0; }
P3_4 = OP;
}
void SendIRdata(char p_irdata) //發(fā)送數(shù)據(jù)子函數(shù)
{
int i;
char irdata=p_irdata;
//發(fā)送9ms的起始碼,并是載波模式有效
endcount=223;
flag=1;
count=0;
while(count《endcount);//等待中斷,控制亮滅交變的總時間為9ms
//發(fā)送4.5ms的結(jié)果碼,并是載波模式無效
endcount=117
flag=0;
count=0;
do{}while(count《endcount);
//發(fā)送十六位地址的前八位
irdata=iraddr1;
for(i=0;i《8;i++)
{//一個周期里規(guī)定先以高電平開始,在以低電平結(jié)束。先發(fā)送0.56ms的38KHZ“1”的紅外波(即編碼中0.56ms的高電平)
endcount=10;
flag=1;
count=0;
do{}while(count《endcount);
//停止發(fā)送紅外信號(即編碼中的低電平)
if(irdata-(irdata/2)*2) //判斷二進制數(shù)個位為1還是0
{endcount=41; } //1為寬的高電平1.68ms
else
{endcount=15; } //0為窄的高電平0.56ms
flag=0;
count=0;
while(count《endcount);
irdata=irdata》》1;//依次取位
}
//發(fā)送十六位地址的后八位
irdata=iraddr2; //此處已經(jīng)是地址的反碼
for(i=0;i《8;i++)
{
endcount=10;
flag=1;
count=0;
while(count《endcount);
if(irdata-(irdata/2)*2)
{endcount=41;}
else
{endcount=15;}
flag=0;
count=0;
do{}while(count《endcount);
irdata=irdata》》1;
}
//發(fā)送八位數(shù)據(jù)
irdata=p_irdata;
for(i=0;i《8;i++)
{
endcount=10;
flag=1;
count=0;
while(count《endcount);
if(irdata-(irdata/2)*2)
{ endcount=41; }
else
{endcount=15; }
flag=0;
count=0;
do{}while(count《endcount);
irdata=irdata》》1;
}
//發(fā)送八位數(shù)據(jù)的反碼
irdata=~p_irdata; //要將數(shù)據(jù)位取反
for(i=0;i《8;i++)
{
endcount=10;
flag=1;
count=0;
while(count《endcount);
if(irdata-(irdata/2)*2)
{endcount=41; }
else
{endcount=15; }
flag=0;
count=0;
while(count《endcount);
irdata=irdata》》1;
}
endcount=10;
flag=1;
count=0;
do{}while(count《endcount);
flag=0;
}
void delay()
{
int i,j;
for(i=0;i《400;i++)
{
for(j=0;j《100;j++)
{
}
}
}
一串完整的編碼如下圖所示
2.紅外接收部分:
紅外接收完成對紅外信號的接收、放大、檢波、整形,并解調(diào)出遙控編碼脈沖。為了減少干擾,采用的是價格便宜性能可靠的一體化紅外接收頭(HS0038,它接收紅外信號頻率為38kHz,周期約26us) 接收紅外信號,它同時對信號進行放大、檢波、整形得到 TTL電平的編碼信號,再送給單片機,經(jīng)單片機解碼并執(zhí)行去控制相關(guān)對象。
接收部分的電路擬圖為:
其應用程序為:
#include“reg52.h”
#define uchar unsigned char
#define uint unsigned int
#include“reg52.h”
#define uchar unsigned char
#define uint unsigned int
uchar ram[4]={0,0,0,0};//存放接受到的4個數(shù)據(jù) 地址碼16位+按鍵碼8位+按鍵碼取反的8位
void delaytime(uint time) //延遲90uS
{ uchar a,b;
for(a=time;a》0;a--)
{ for(b=40;b》0;b--); }
}
void rem()interrupt 0 //中斷函數(shù)
{
uchar ramc=0; //定義接收了4個字節(jié)的變量
uchar count=0; //定義現(xiàn)在接收第幾位變量
uint i=0; //此處變量用來在下面配合連續(xù)監(jiān)測9MS 內(nèi)是否有高電平
prem=1;
for(i=0;i《1100;i++) //以下FOR語句執(zhí)行時間為8MS左右
{
if(prem) //進入遙控接收程序首先進入引導碼的前半部判斷,即:是否有9MS左右的低電平
return; //引導碼錯誤則退出 ,注意與break語句的區(qū)別
}
while(prem!=1); //等待引導碼的后半部 4.5 MS 高電平開始的到來。
delaytime(50); //延時大于4.5MS時間,跨過引導碼的后半部分,來到真正遙控數(shù)據(jù)32位中
//第一位數(shù)據(jù)的0.56MS開始脈沖
for(ramc=0;ramc《4;ramc++)//循環(huán)4次接收4個字節(jié)
{ for(count=0;count《8;count++) //循環(huán)8次接收8位(一個字節(jié))
{
while(prem!=1); //開始判斷現(xiàn)在接收到的數(shù)據(jù)是0或者1 ,首先在這行本句話時,
//保已經(jīng)進入數(shù)據(jù)的0.56MS 低電平階段
//等待本次接受數(shù)據(jù)的高電平的到來。
delaytime(9);//高電平到來后,數(shù)據(jù)0 高電平最多延續(xù)0.56MS,而數(shù)據(jù)1,高電平可延續(xù)1.66MS大于0.8MS 后我們可以再判斷遙控接收腳的電平。
if(prem) //如果這時高電平仍然在繼續(xù)那么接收到的數(shù)據(jù)是1的編碼
{ram[ramc]=(ram[ramc]《《1)+1;//將目前接收到的數(shù)據(jù)位1放到對應的字節(jié)中
delaytime(11); //如果本次接受到的數(shù)據(jù)是1,那么要繼續(xù)延遲1MS,這樣才能跨
//下個位編碼的低電平中(即是開始的0.56MS中)
}
else //否則目前接收到的是數(shù)據(jù)0的編碼
ram[ramc]=ram[ramc]《《1; //將目前接收到的數(shù)據(jù)位0放到對應的字節(jié)中
} //本次接收結(jié)束,進行下次位接收,此接收動作進行32次,正好完成4個字節(jié)的接收
}
if(ram[2]!=(~(ram[3]&0x7f))) //本次接收碼的判斷
{ for(i=0;i《4;i++) //沒有此對應關(guān)系則表明接收失敗,清除接受到的數(shù)據(jù)
ram[i]=0;
returned;}
main()
{
IT0=1; //設定INT0為邊沿觸發(fā)
EX0=1; //打開外部中斷0
EA=1; //全局中斷開關(guān)打開
while(1)
{
switch(dis_num)
{
case 0x81: num=0; break;
case 0xcf: num=1; break;
case 0x92: num=2; break;
case 0x86: num=3; break;
case 0xcc: num=4; break;
case 0xa4: num=5; break;
case 0xa0: num=6; break;
case 0x8f: num=7; break;
case 0x80: num=8; break;
case 0x84: num=9; break;
case 0x88: num=10;break;
case 0xe0: num=11;break;
case 0xb1: num=12;break;
case 0xc2: num=13;break;
case 0xb0: num=14;break;
case 0xb8: num=15;break;
}
P2=table[num];
P1=0x01;
delaytime(5);
}
-
調(diào)制
+關(guān)注
關(guān)注
0文章
157瀏覽量
29664 -
紅外遙控
+關(guān)注
關(guān)注
22文章
347瀏覽量
45588 -
HS0038
+關(guān)注
關(guān)注
1文章
5瀏覽量
13377
發(fā)布評論請先 登錄
相關(guān)推薦
評論