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