單片機(jī)練習(xí)-RC-5紅外遙控器程序及簡(jiǎn)單制造DIY PC遙控器
本程序采用的芯片為SAA3010, 參考資料有:
1.常用紅外遙控接收頭引腳圖解
2.紅外遙控編碼資料
3.RC-5紅外遙控程序
4.GIRDER中文教程與電腦遙控器制作資料
5.Girder網(wǎng)站(一個(gè)需要錢(qián)買的遙控)
6.再度出擊,20元打造經(jīng)典PC遙控器!
7.SAA3010 DataSheet
這次主要是完成單片機(jī)接收紅外搖控器發(fā)出的數(shù)據(jù). 在此基礎(chǔ)上, 我們可DIY出自己的PC搖控器, 也可自行發(fā)揮一些, 做出類似于很多Club里的點(diǎn)歌系統(tǒng)的硬件外紅信號(hào)轉(zhuǎn)換裝置....
本次實(shí)驗(yàn)依舊采用TX-1B實(shí)驗(yàn)板, 只需增加一個(gè)一體化紅外接收頭, 如下圖:
本程序中, DataOut引腳接到P3.2口. 在接收頭的電源和地端接上濾波電容會(huì)使誤碼率更加低....
SAA3010芯片:
(圖中位時(shí)間1.688ms, 而根據(jù)DataSheet里描述的位時(shí)間為1.788ms, 但實(shí)際中我使用的時(shí)間為1.651ms)
我使用的鍵盤(pán)編碼如下:
鍵盤(pán)外觀:
編碼:
一體化紅外接收頭的數(shù)據(jù)輸出的判斷思路: (手畫(huà), 太難看也別見(jiàn)怪:) )
Tb = 1.778ms = 1.780ms (實(shí)際中測(cè)試為1.651ms)
T1/4b = 445us (實(shí)際中413ms)
T3/4b = 1.335ms (實(shí)際1.239ms)
在等待第一次低電平到來(lái)后, 定時(shí)器開(kāi)始第一次定時(shí)T1/4b時(shí)間, 然后到達(dá)第一次數(shù)據(jù)的T3/4b時(shí)刻, 讀取該位電平狀態(tài);
以后定時(shí)器每次定時(shí)Tb時(shí)間, 這樣到達(dá)對(duì)應(yīng)每位的T3/4時(shí)刻, 并可讀取該位電平狀態(tài).
具體邏輯請(qǐng)看代碼中的詳細(xì)注釋:
采用程序查詢方式:
SAA3010_RC5
//接收紅外遙控器(Infraredremotecontroltransmitter)發(fā)出的數(shù)據(jù)
//芯片型號(hào):SAA3010,它采用RC-5協(xié)議
//芯片資料:http://www.alldatasheet.com/datasheet-pdf/pdf/18953/PHILIPS/SAA3010.html
//利用與P1口相連的發(fā)光二極管輸出接收到的按鍵對(duì)應(yīng)碼,并將它輸出到串口,用于遙控
//PC使用了Girder來(lái)觸發(fā)自定義的功能
#include"reg51.h"
#include"intrins.h"
#defineucharunsignedchar
/*********************IRCRC-5****************************************/
ucharYKDatas[3];//遙控碼(一幀14位),YKDatas[0]:0,1為startbits,2為controlbit,YKtype=0
//YKDatas[1]:3~7為systembits,YKtype=1
//YKDatas[2]:8~13為commandbits,YKtype=2
sbitYKIn=P3^2;//數(shù)據(jù)輸入位
ucharYKcount,YKtype;//遙控已接收位數(shù),一幀的各段標(biāo)志
bitYKend;//接收結(jié)束標(biāo)志
//延時(shí)a*1ms
voiddelayMs(unsignedinta)
{
unsignedinti,j;
for(i=a;i>0;i--)
for(j=100;j>0;j--);
}
voidYKInit()//遙控接收初始化
{
YKDatas[0]=YKDatas[1]=YKDatas[2]=0;
YKcount=0;
YKtype=0;
YKend=0;
}
voidtime0()interrupt1
{
//第一次進(jìn)入中斷前,定時(shí)1/4位的時(shí)間:445us,以后則定時(shí)一位時(shí)間1.778ms
//即在3/4位時(shí)間時(shí),判斷該位是1還是0
//實(shí)際測(cè)試中,位時(shí)間只在1.651ms(+-1ms),定時(shí)1/4位的時(shí)間:413us
bitin=~YKIn;//一體化解碼后,有載頻部分變?yōu)榈碗娖?即低電平實(shí)際為1,高電平實(shí)際為0
//設(shè)置定時(shí)器初值
//模式1:TH0=(2^16-(1651/1.085))/2^8=(65536-1651/1.085)/256=250;
//TL0=(65536-1651/1.085)%256=14
TH0=250;
TL0=14;
YKDatas[YKtype]=YKDatas[YKtype]"in;//將數(shù)據(jù)放入最低位
YKcount++;
if(YKcount==3)//獲取完Startbits和controlbit,共3位
{
YKtype=1;
}
elseif(YKcount==8)//獲取完systembits,共5位
{
YKtype=2;
}
elseif(YKcount==14)//獲取完commondbits,共6位
{
YKtype=3;
}
elseif(YKtype==3)//等待最后1/4位時(shí)間結(jié)束,實(shí)際延時(shí)1位時(shí)間
{
YKend=1;
YKcount=0;
YKtype=0;
TR0=0;//接收結(jié)束,停止定時(shí)器0
return;
}
else//將數(shù)據(jù)左移一位,以便將一下位數(shù)據(jù)并于最低位
{
YKDatas[YKtype]=YKDatas[YKtype]<<1;
}
}
/*********************IRCRC-5****************************************/
/*********************RS232****************************************/
//初始化串口
voidRSInit()
{
TMOD|=0x20;//T1工作方式2
TH1=TL1=0xfd;//裝入初值,以后是自動(dòng)重載的8位計(jì)數(shù)器
TR1=1;//啟動(dòng)T1
SM0=0;
SM1=1;//方式1
REN=1;//允許接收
EA=1;//開(kāi)中斷
ES=1;//允許串口中斷
PCON=0x00;//串口波特率不加倍.即設(shè)置SMOD=0;
}
//寫(xiě)一字節(jié)數(shù)據(jù)到串口,使用程序查詢方式檢測(cè)發(fā)送情況
voidRsWriteByte(unsignedcharbyte)
{
ES=0;//關(guān)中斷
SBUF=byte;
while(!TI);//檢測(cè)是否發(fā)送完
TI=0;//清0發(fā)送中斷標(biāo)志
ES=1;//開(kāi)中斷,以允許接收數(shù)據(jù)時(shí)使用中斷方式
}
voidserial()interrupt4//串口中斷是4
{
P1=SBUF;
RI=0;//清0接收中斷標(biāo)志
}
/*********************RS232****************************************/
voiddisplay()//顯示接收的數(shù)據(jù)
{
P1=~YKDatas[2];
/*switch(YKDatas[2])
{
case0x3f:
case0x0c:RsWriteByte(YKDatas[0]);break;
default:break;
}*/
//RsWriteByte(YKDatas[1]);
RsWriteByte(YKDatas[2]);
}
voidmain(void)
{
TMOD=0x01;//T0選用方式1(16位定時(shí))
IE=0x82;//開(kāi)總中斷,開(kāi)定時(shí)器0中斷
YKIn=1;
RSInit();
while(1)
{
YKInit();
//模式1:TH0=(2^16-(413/1.085))/2^8=(65536-381)/256=255;
//TL0=(65536-381)%256=131
TH0=255;
TL0=131;
while(YKIn);//等待低電平,一幀開(kāi)始
TR0=1;//啟動(dòng)定時(shí)器0,接收紅外遙控器發(fā)來(lái)的數(shù)據(jù)
while(!YKend);//等待接收結(jié)束
display();
delayMs(200);
}
}
改進(jìn)代碼: 由原來(lái)的程序查詢方式, 換成