|
對我們的51單片機(jī)而言,遙控多是通過紅外實(shí)現(xiàn),可是你想過幾十年前單片機(jī)沒普及時(shí)的情形嗎?
當(dāng)年我在林場工作,全場只有一部電話可以打外線長途,在場部。其余的分機(jī)打不了,我當(dāng)時(shí)為了方便,設(shè)計(jì)制作了電話遙控器。在家里用分機(jī)撥我預(yù)先設(shè)定好的空位內(nèi)線電話號,我的分機(jī)就自動(dòng)接上外線可以打長途了。原理也很簡單,就是做個(gè)全橋整流電路,經(jīng)濾波后直接帶動(dòng)有多路觸點(diǎn)向一繼電器,把我的分機(jī)接在外線上,同時(shí)斷開主機(jī)。只要通話,繼電器自鎖;電話掛機(jī)后繼電裝自動(dòng)釋放。這個(gè)方法我一直用到我家自己安裝了長途電話為止。(當(dāng)然也是我占了管理程控電話交換機(jī)的光,只是為了方便,少跑一趟不近的路。)
那年孩子上中學(xué),為了方便我在學(xué)校附近租了間小房。天很冷,晚上看電視都趴在炕上。當(dāng)時(shí)電視器基本沒有遙控的,電視節(jié)目也只有一個(gè)地方臺(tái)。怕冷,全家誰都不愿意出被窩關(guān)閉電視機(jī)。
我用阻容元件制作了一個(gè)定時(shí)器,假定1小時(shí)。上炕前啟動(dòng),1小時(shí)后關(guān)機(jī)。開始挺好,可有一天電視節(jié)目沒看完時(shí)間到關(guān)機(jī)了,惹愛人一頓嘮叨。我重新設(shè)計(jì),改成電視信號控制的。有電視信號就不關(guān)機(jī),電視機(jī)沒有信號延時(shí)一段時(shí)間關(guān)閉電視機(jī)。
可沒多久問題又來了。一天,電視劇看完了,開始播放晚間新聞,電視機(jī)還哇哇響,又惹來愛人埋怨。
再改,這次我制作了光控的。沒有遙控器,就直接用手電筒。按一下開機(jī),再按一下關(guān)機(jī)。用了一段時(shí)間。
后來電視臺(tái)增多了,不止一個(gè)臺(tái)了。我又改成短按換臺(tái),長按關(guān)機(jī)的方式。
時(shí)我把我的做法寫成文章投稿給《無線電》雜志。由于我前兩次發(fā)表文章都特別簡潔,稿費(fèi)很少,這次有意寫詳細(xì)點(diǎn)。可稿子投出去很長時(shí)間不見發(fā)表。大約幾個(gè)月后我在雜志上看到了類似文章發(fā)表了。
后來雜志又有了成品電視機(jī)紅外遙控器套件出售,但價(jià)格不菲,當(dāng)時(shí)安裝下來要200多元,還得懂各種型號電視機(jī)線路原理,風(fēng)險(xiǎn)也高。
我的許多朋友要我給他們改裝電視機(jī)遙控器,我先后為幾十人安裝。現(xiàn)在的人很難理解電視機(jī)沒有遙控器的時(shí)代是怎樣過來的。
幾年前,我準(zhǔn)備為老父90大壽制一臺(tái)51單片機(jī)控制的簡易小車機(jī)器人,用流行的尋跡小車改制。選用雙驅(qū)動(dòng)輪加導(dǎo)向的方式,因?yàn)榭梢栽?60度轉(zhuǎn)向。我的設(shè)想是,小車出發(fā),語音播報(bào)活動(dòng)開始。小車前進(jìn)放下一只裝有書寫筆的桿,寫出九十兩個(gè)漢字。之后播放生日快樂,我的好父親等歌曲,最后吹滅蠟燭。
我當(dāng)時(shí)用的是紅外遙控配合51單片機(jī)完成各項(xiàng)任務(wù)。當(dāng)時(shí)除寫字部分外其它功能都可用程序或遙控器完成。寫字功能我沒有用步進(jìn)電機(jī),只在輪子上安裝了碼盤計(jì)數(shù),判斷行走距離和轉(zhuǎn)彎角度。實(shí)際試驗(yàn)時(shí)誤差較大,每次都難一致。后來女兒看我天天在電腦上修改再試驗(yàn),就跟我說:別弄了,那天是個(gè)隆重場合,萬一你的設(shè)備出點(diǎn)故障就不好了。我聽老父講子個(gè)故事,說一次乾隆給位老者送了幅字,寫了九十大壽,這位老者九十后就死了。
所以我從止罷休半途而廢,我的眼睛就是當(dāng)年盯電腦屏幕辛壞的。
照片是小車主板和能片斷錄放mp3的設(shè)備。主板的數(shù)碼管可顯示解碼后的紅外遙控各鍵碼。
兩張家人照是老父九十大壽全體及老父我的子女和孫輩。后我大病一場,5年大父也走了,今年是他兩歲年。老父若在97了。
附51機(jī)紅外線資料
//#################################################################################################
//文件:51單片機(jī)的紅外遙控解碼程序
//屬性:使用外部中斷0連接遙控頭,接收紅外遙控鍵值送P2口顯示,12MHz外部晶振
//作者:新思科電子 2011-06
//資源:P3.2=接收頭輸入,P2=8LED
//#################################################################################################
#include"reg52.h"
#define uint unsigned int
#define uchar unsigned char
uchar led=0x00;
void io_init(void);
void int_init(void);
void main(void)
{
io_init();
int_init();
while(1);
}
void io_init(void)
{
P0=0xff;
P1=0xff;
P2=0xff;
P3=0xff;
}
void int_init(void)
{
EX0=1;
EA=1;
}
void interrupt0()interrupt 0
{
uchar i=0,j=0,k=0,us=0;
uchar addr[4]={0};
EX0=0;
for(i=0;i<255;i++) //9ms內(nèi)有高電平認(rèn)為是干擾
{
if(P3&0x04) //255的值實(shí)際時(shí)間為800us
{
EX0=1;
return;
}
}
while(!(P3&0x04)); //等待9ms低電平過去
for(i=0;i<4;i++)
{
for(j=0;j<8;j++)
{
while(P3&0x04); //等待4.5ms高電平過去
while(!(P3&0x04)); //等待0.56ms低電平后面的高電平
while(P3&0x04) //計(jì)算這個(gè)高電平的時(shí)間
{
for(us=0;us<=32;us++); //100us的延時(shí)語句
if((k++)>=30) //高電平時(shí)間過長退出程序
{
EX0=1;
return;
}
}
addr[ i]=addr[ i]>>1; //接收一位數(shù)據(jù)
if(k>=8)
addr[ i]=addr[ i]|0x80; //高電平大于0.56ms,則為1
k=0;
}
}
P2=~(addr[2]); //P2的LED顯示二進(jìn)制鍵值
EX0=1;
}
紅外解碼教程
紅外遙控系統(tǒng)一般分發(fā)射和接收兩個(gè)部分
發(fā)射部分的主要元件為紅外發(fā)光二極管。目前大量使用的紅外發(fā)光二極管發(fā)出的紅外線波長為940mm左右,外形與普通φ5發(fā)光二極管相同。
接收部分的紅外接收管是一種光敏二極管。紅外發(fā)光二極管一般有圓形和方形兩種。由于紅外發(fā)光二極管的發(fā)射功率一般都較小(100mW左右),所以紅外接收二極管接收到的信號比較微弱,因此就要增加高增益放大電路。最近幾年大多都采用成品紅外接收頭。
成品紅外接收頭的封裝大致有兩種:一種采用鐵皮屏蔽;一種是塑料封裝。均有三只引腳,即電源正(VDD)、電源負(fù)(GND)和數(shù)據(jù)輸出(VO或OUT)。紅外接收頭的引腳排列因型號不同而不盡相同,可參考廠家的使用說明。成品紅外接收頭的優(yōu)點(diǎn)是不需要復(fù)雜的調(diào)試和外殼屏蔽,使用起來如同一只三極管,非常方便。但在使用時(shí)注意成品紅外接收頭的載波頻率。紅外遙控常用的載波頻率為38kHz,這是由發(fā)射端所使用455kHz晶振來決定的。在發(fā)射端要對晶振進(jìn)行整數(shù)分頻,分頻系數(shù)一般取12,所以455kHz÷12≈37.9kHz≈38kHz。也有一些遙控系統(tǒng)采用36 kHz、40 kHz、56 kHz等,由發(fā)射端晶振的振蕩頻率來決定。
紅外遙控的特點(diǎn)是不影響周邊環(huán)境的、不干擾其他電器設(shè)備。室內(nèi)近距離(小于10米)遙控中得到了廣泛的應(yīng)用。
紅外遙控在生產(chǎn)和生活中應(yīng)用越來越廣泛,不同的紅外遙控芯片有不同的發(fā)碼協(xié)議,但一般都是由引導(dǎo)碼,系統(tǒng)碼,鍵碼三部分組成.
引導(dǎo)碼是告訴接收機(jī)準(zhǔn)備接收紅外遙控碼.系統(tǒng)碼是識(shí)別碼,不同的遙控芯片有不同的識(shí)別碼,以免搞錯(cuò).
遙控器上不同的按鍵有不同的鍵碼,系統(tǒng)碼和鍵碼都是16位碼,8位正碼,8位反碼.如SC6122的系統(tǒng)碼是FF00,FF和00互為反碼,鍵碼1為EF10也是互為反碼.
SC6122的引導(dǎo)碼為低電平為9000微秒,高電平為4500微秒.當(dāng)然高電平不可能精確為9000微秒,在8000微秒到10000微秒都看作是正常范圍,低電平在4000-5000之間都看作是正常范圍.引導(dǎo)碼后的32位編碼(16位系統(tǒng)碼和16位鍵碼)不管高低電平,載波時(shí)間都是560微秒,但低電平持續(xù)時(shí)間是1125微秒,高電平持續(xù)時(shí)間是2250微秒,所以低電平除去載波時(shí)間大約是560微秒,高電平除去載波時(shí)間大約是1680微秒.低電平也有一個(gè)波動(dòng)范圍,在400-700之間都看作是正常的,具體多少可以通過示波器測量出來.高電平也有一個(gè)波動(dòng)范圍,在400-2000之間都看作是正常的,具體多少也是根據(jù)經(jīng)驗(yàn).當(dāng)然范圍越寬,捕捉紅外線的范圍也越寬,越精確.在捕捉到有高低電平之間,在560-1680之間取一個(gè)中間值1120微秒,認(rèn)為小于1120微秒是低電平,大于1120微秒是高電平.
以下程序能在LCD上顯示系統(tǒng)碼和鍵碼,按不同的按鍵,系統(tǒng)碼不變,變的是鍵碼.
#include <reg52.h>
#define c(x) (x*110592/120000)
sbit Ir_Pin=P3^3;
unsigned char code Led_Tab[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,
0xf8,0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E}; //共陽極數(shù)碼顯示碼0-F.
unsigned char code Led_Sel[]={0xe,0xd,0xb,0x7};
unsigned char Led_Buf[4]; //顯示緩沖區(qū)
char Led_Index; //位選
unsigned char Ir_Buf[4]; //用于保存解碼結(jié)果
//==============================================================
timer0() interrupt 1 using 1 //數(shù)碼管掃描
{
TL0=65536-1000;
TH0=(65536-1000)/256; //定時(shí)器0設(shè)定約1000us中斷一次,用于數(shù)碼管掃描
P0=0xff;
P2=Led_Sel[Led_Index]; //位選
P0=Led_Tab[Led_Buf[Led_Index]]; //段選
if(++Led_Index>3) Led_Index=0; //四個(gè)掃描完了,到第一個(gè)數(shù)碼管
}
//==============================================================
unsigned int Ir_Get_Low()
{
TL1=0;
TH1=0;
TR1=1;
while(!Ir_Pin && (TH1&0x80)==0);
TR1=0;
return TH1*256+TL1;
}
//=============================================================
unsigned int Ir_Get_High()
{
TL1=0;
TH1=0;
TR1=1;
while(Ir_Pin && (TH1&0x80)==0);
TR1=0;
return TH1*256+TL1;
}
//==============================================================
main()
{
unsigned int temp;
char i,j;
Led_Index=1;
TMOD=0x11;
TL0=65536-1000;
TH0=(65536-1000)/256; //定時(shí)器0設(shè)定約1000us中斷一次,用于數(shù)碼管掃描
EA=1;
ET0=1;
TR0=1;
Led_Buf[0]=0;
Led_Buf[1]=0;
Led_Buf[2]=0;
Led_Buf[3]=0; //顯示區(qū)設(shè)成0
do
{
restart:
while(Ir_Pin);
temp=Ir_Get_Low();
if(temp<c(8500) || temp>c(9500)) continue;//引導(dǎo)脈沖低電平9000
temp=Ir_Get_High();
if(temp<c(4000) || temp>c(5000)) continue;//引導(dǎo)脈沖高電平4500
for(i=0;i<4;i++) //4個(gè)字節(jié)
for(j=0;j<8;j++) //每個(gè)字節(jié)8位
{
temp=Ir_Get_Low();
if(temp<c(200) || temp>c(800)) goto restart;
temp=Ir_Get_High();
if(temp<c(200) || temp>c(2000)) goto restart;
Ir_Buf[ i]>>=1;
if(temp>c(1120)) Ir_Buf[ i]|=0x80;
}
Led_Buf[0]=Ir_Buf[2]&0xf;
Led_Buf[1]=(Ir_Buf[2]/16)&0xf;
Led_Buf[2]=Ir_Buf[3]&0xf;
Led_Buf[3]=(Ir_Buf[3]/16)&0xf; //顯示結(jié)果
}
while(1);
}
另一份紅外線解碼教程:
紅外遙控系統(tǒng)一般分發(fā)射和接收兩個(gè)部分
發(fā)射部分的主要元件為紅外發(fā)光二極管。目前大量使用的紅外發(fā)光二極管發(fā)出的紅外線波長為940mm左右,外形與普通φ5發(fā)光二極管相同。
接收部分的紅外接收管是一種光敏二極管。紅外發(fā)光二極管一般有圓形和方形兩種。由于紅外發(fā)光二極管的發(fā)射功率一般都較小(100mW左右),所以紅外接收二極管接收到的信號比較微弱,因此就要增加高增益放大電路。最近幾年大多都采用成品紅外接收頭。
成品紅外接收頭的封裝大致有兩種:一種采用鐵皮屏蔽;一種是塑料封裝。均有三只引腳,即電源正(VDD)、電源負(fù)(GND)和數(shù)據(jù)輸出(VO或OUT)。紅外接收頭的引腳排列因型號不同而不盡相同,可參考廠家的使用說明。成品紅外接收頭的優(yōu)點(diǎn)是不需要復(fù)雜的調(diào)試和外殼屏蔽,使用起來如同一只三極管,非常方便。但在使用時(shí)注意成品紅外接收頭的載波頻率。紅外遙控常用的載波頻率為38kHz,這是由發(fā)射端所使用455kHz晶振來決定的。在發(fā)射端要對晶振進(jìn)行整數(shù)分頻,分頻系數(shù)一般取12,所以455kHz÷12≈37.9kHz≈38kHz。也有一些遙控系統(tǒng)采用36 kHz、40 kHz、56 kHz等,由發(fā)射端晶振的振蕩頻率來決定。
紅外遙控的特點(diǎn)是不影響周邊環(huán)境的、不干擾其他電器設(shè)備。室內(nèi)近距離(小于10米)遙控中得到了廣泛的應(yīng)用。
紅外遙控在生產(chǎn)和生活中應(yīng)用越來越廣泛,不同的紅外遙控芯片有不同的發(fā)碼協(xié)議,但一般都是由引導(dǎo)碼,系統(tǒng)碼,鍵碼三部分組成.
引導(dǎo)碼是告訴接收機(jī)準(zhǔn)備接收紅外遙控碼.系統(tǒng)碼是識(shí)別碼,不同的遙控芯片有不同的識(shí)別碼,以免搞錯(cuò).
遙控器上不同的按鍵有不同的鍵碼,系統(tǒng)碼和鍵碼都是16位碼,8位正碼,8位反碼.如SC6122的系統(tǒng)碼是FF00,FF和00互為反碼,鍵碼1為EF10也是互為反碼.
SC6122的引導(dǎo)碼為低電平為9000微秒,高電平為4500微秒.當(dāng)然高電平不可能精確為9000微秒,在8000微秒到10000微秒都看作是正常范圍,低電平在4000-5000之間都看作是正常范圍.引導(dǎo)碼后的32位編碼(16位系統(tǒng)碼和16位鍵碼)不管高低電平,載波時(shí)間都是560微秒,但低電平持續(xù)時(shí)間是1125微秒,高電平持續(xù)時(shí)間是2250微秒,所以低電平除去載波時(shí)間大約是560微秒,高電平除去載波時(shí)間大約是1680微秒.低電平也有一個(gè)波動(dòng)范圍,在400-700之間都看作是正常的,具體多少可以通過示波器測量出來.高電平也有一個(gè)波動(dòng)范圍,在400-2000之間都看作是正常的,具體多少也是根據(jù)經(jīng)驗(yàn).當(dāng)然范圍越寬,捕捉紅外線的范圍也越寬,越精確.在捕捉到有高低電平之間,在560-1680之間取一個(gè)中間值1120微秒,認(rèn)為小于1120微秒是低電平,大于1120微秒是高電平.
以下程序能在LCD上顯示系統(tǒng)碼和鍵碼,按不同的按鍵,系統(tǒng)碼不變,變的是鍵碼.
#include <reg52.h>
#define c(x) (x*110592/120000)
sbit Ir_Pin=P3^3;
unsigned char code Led_Tab[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,
0xf8,0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E}; //共陽極數(shù)碼顯示碼0-F.
unsigned char code Led_Sel[]={0xe,0xd,0xb,0x7};
unsigned char Led_Buf[4]; //顯示緩沖區(qū)
char Led_Index; //位選
unsigned char Ir_Buf[4]; //用于保存解碼結(jié)果
//==============================================================
timer0() interrupt 1 using 1 //數(shù)碼管掃描
{
TL0=65536-1000;
TH0=(65536-1000)/256; //定時(shí)器0設(shè)定約1000us中斷一次,用于數(shù)碼管掃描
P0=0xff;
P2=Led_Sel[Led_Index]; //位選
P0=Led_Tab[Led_Buf[Led_Index]]; //段選
if(++Led_Index>3) Led_Index=0; //四個(gè)掃描完了,到第一個(gè)數(shù)碼管
}
//==============================================================
unsigned int Ir_Get_Low()
{
TL1=0;
TH1=0;
TR1=1;
while(!Ir_Pin && (TH1&0x80)==0);
TR1=0;
return TH1*256+TL1;
}
//=============================================================
unsigned int Ir_Get_High()
{
TL1=0;
TH1=0;
TR1=1;
while(Ir_Pin && (TH1&0x80)==0);
TR1=0;
return TH1*256+TL1;
}
//==============================================================
main()
{
unsigned int temp;
char i,j;
Led_Index=1;
TMOD=0x11;
TL0=65536-1000;
TH0=(65536-1000)/256; //定時(shí)器0設(shè)定約1000us中斷一次,用于數(shù)碼管掃描
EA=1;
ET0=1;
TR0=1;
Led_Buf[0]=0;
Led_Buf[1]=0;
Led_Buf[2]=0;
Led_Buf[3]=0; //顯示區(qū)設(shè)成0
do
{
restart:
while(Ir_Pin);
temp=Ir_Get_Low();
if(temp<c(8500) || temp>c(9500)) continue;//引導(dǎo)脈沖低電平9000
temp=Ir_Get_High();
if(temp<c(4000) || temp>c(5000)) continue;//引導(dǎo)脈沖高電平4500
for(i=0;i<4;i++) //4個(gè)字節(jié)
for(j=0;j<8;j++) //每個(gè)字節(jié)8位
{
temp=Ir_Get_Low();
if(temp<c(200) || temp>c(800)) goto restart;
temp=Ir_Get_High();
if(temp<c(200) || temp>c(2000)) goto restart;
Ir_Buf[ i]>>=1;
if(temp>c(1120)) Ir_Buf[ i]|=0x80;
}
Led_Buf[0]=Ir_Buf[2]&0xf;
Led_Buf[1]=(Ir_Buf[2]/16)&0xf;
Led_Buf[2]=Ir_Buf[3]&0xf;
Led_Buf[3]=(Ir_Buf[3]/16)&0xf; //顯示結(jié)果
}
while(1);
} |
評分
-
查看全部評分
|