本帖最后由 benbens 于 2015-7-15 00:19 編輯
前不久迷上了紅外遙控解碼,雖然自己在學校時曾經(jīng)研究過,但一直沒有搞清楚。溫故而知新,加上得到一大神指點,讓我茅塞頓開。
當一個紅外遙控器的按鍵按下去時,共有四組數(shù)據(jù)發(fā)送出去了,第一組是低8位用戶碼, 第二組是高8位用戶碼,第三組是數(shù)據(jù)碼, 第四組是數(shù)據(jù)反碼。 用戶碼也叫引導碼,用來區(qū)別不同的遙控器,數(shù)據(jù)碼也叫按鍵碼,用來區(qū)別不同的按鍵。數(shù)據(jù)反碼就是數(shù)據(jù)碼取反之后,用來進行數(shù)據(jù)校驗的。
自己手頭的有一塊0802的液晶顯示模塊,剛好利用起來,做一個紅外遙控碼值測試的工具。 主控芯片用的是STC89C52RC單片機, 用它主要是因為這片單片機一直閑置在這里,大家也可以把程序移植到其它型號的單片機上(移植時注意延時函數(shù))。想到只用來測試紅外遙控碼值太可惜這片單片機和0802液晶顯示屏了,何不加上其它功能?手上有DS1302時鐘芯片,用來做一個萬年歷在合適不過了,再用一個撥動開關來切換碼值測試功能和時鐘功能(撥動開關后要重啟一下)。STC89C52RC有好多IO口,索性再加蜂鳴器和LED。
碼值測試功能:當解碼出四組數(shù)據(jù)后蜂鳴器滴一聲,LED閃爍一下。
時鐘功能:1.當按鍵按下蜂鳴器滴一聲 2.每當?shù)秸c的時候,蜂鳴器滴一聲(整點報時)。
以下是實物效果圖:
依次是 年 月 日 星期 時 分

照片名稱:紅外解碼-1
所屬相冊:電子DIY
首次開機,沒有接收到紅外信號時顯示

照片名稱:紅外解碼-3
所屬相冊:電子DIY
接收到紅外信號并成功解碼時
引導碼:0x00ff 按鍵碼:0x01 按鍵反碼:0xfe

照片名稱:紅外解碼-2
所屬相冊:電子DIY
整體效果圖

照片名稱:紅外解碼-4
所屬相冊:電子DIY
供電電源采取USB供電,直接插電腦或者手機充電器就行了。。。。
我是直接現(xiàn)場發(fā)揮,沒有畫電路圖,大家也可以從我的程序里看出電路的連接,鑒于我菜鳥般的編程能力,我就不全部把程序公布出來,只給出關鍵程序。需要的童鞋也可以留下郵箱,我可以發(fā)給你。
1. IO接口定義
unsigned char IR_code[4] = {0,0,0,0};//存放四組數(shù)據(jù)
sbit fmq=P1^0;//蜂鳴器接口
sbit RS=P1^1;
sbit RW=P1^2;
sbit EN=P1^3;
sbit mode=P1^4;//模式選擇接口
sbit IR_Out = P3^2; // 此口為紅外信號輸入MCU口
sbit led=P3^7;
sbit mos_key=P1^6;
sbit up_key=P1^5;
sbit down_key=P3^6;
sbit CE=P2^5; //DS1302片選口
sbit IO=P2^6; //DS1302數(shù)據(jù)口
sbit SCLK=P2^7; //DS1302時鐘口
2. 0802液晶驅動程序
void write_com(unsigned char com) //寫指令
{
RW=0;
RS=0;
EN=0;
P0=com;
EN=1;
delayms(5);
EN=0;
}
void write_dat(unsigned char dat)//寫數(shù)據(jù)
{
RW=0;
RS=1;
EN=0;
P0=dat;
EN=1;
delayms(5);
EN=0;
}
void lcdIR_init()
{
EA = 1; // CPU準許中斷
delayms(400);
write_com(0x3c); //8位數(shù)據(jù)總線,兩行顯示模式,5*10點陣
write_com(0x01); //清顯示
write_com(0x0c); // 開顯示,關閉光標,關閉閃爍
write_com(0x80);
write_dat('B');
write_dat('C');
write_dat(':');
write_com(0x80+5);
write_dat('-');
write_com(0xc0);
write_dat('K');
write_dat('C');
write_dat(':');
write_com(0xc0+5);
write_dat('-');
}
void lcdtime_init()
{
EA = 0; // CPU不準許中斷
delayms(400);
write_com(0x3c); //8位數(shù)據(jù)總線,兩行顯示模式,5*10點陣
write_com(0x01); //清顯示
write_com(0x0c); // 開顯示,關閉光標,關閉閃爍
write_com(0x80);
write_dat(' ');
write_dat(' ');
write_dat('-');
write_dat(' ');
write_dat(' ');
write_dat('-');
write_dat(' ');
write_dat(' ');
}
3. 紅外解碼程序
/*------------------------------------------------------------*-
函數(shù)名稱:Int0()
函數(shù)輸入:無(容許中斷時,外部觸發(fā))
函數(shù)輸出:無
函數(shù)說明:外部中斷0中斷處理
-*------------------------------------------------------------*/
void Int0() interrupt 0
{
unsigned char i,j;
EX0 = 0; // 關閉外部中斷0
i = 10; // 0.793ms延時,運行10次
while( --i )
{
// 定時0.793ms,延時0.793ms*10=7.93ms
Delay793us();
// 這7.93ms期間只要IR_Out變高電平,就非合法的紅外信號,跳出
if( IR_Out )
{
EX0 = 1; // 準許中斷
return ;
}
}
// 程序進行到這里,表明是合法的紅外信號(利用9ms判斷)
while( !IR_Out ); // 等待9ms低電平過去
// 程序進行到這里,表明經(jīng)過9ms低電平
Delay2305us(); // 延時2.305ms
// IR_Out 為低表明是連發(fā)碼,不予理睬,跳出
if( !IR_Out )
{
EX0=1;
return;
}
// 程序進行到這里,表明是引導碼,等待4.5ms高電平的過去
while( IR_Out );
// 開始接收四組數(shù)據(jù)
for(i=0; i<4; i++)
{
for(j=0; j<8; j++)
{
while( !IR_Out ); // 等待低電平過去
IR_code[ i] >>= 1; // 把上次的數(shù)據(jù)位右移一位
Delay793us(); //延時0.793ms
// 若為數(shù)據(jù)"1",則延時后IR_Out為高電平
if( IR_Out )
{
IR_code[ i] |= 0x80; // 所有數(shù)據(jù)位1放最高位
while( IR_Out ); // 等待高電平過去
}
}
}
//IR_code[0]低8位用戶碼,IR_code[1]高8位用戶碼,IR_code[2]為數(shù)據(jù)碼,IR_code[3]為數(shù)據(jù)反碼----dat為二進制
if (IR_code[2]!=~IR_code[3]) //數(shù)據(jù)碼校驗
{
EX0=1;
return;
}
fmq=led=0;
diaplay_IRcode(0,0x80+3);
diaplay_IRcode(1,0x80+6);
diaplay_IRcode(2,0xc0+3);
diaplay_IRcode(3,0xc0+6);
EX0=1; // 開中斷
return;
}
4. 主函數(shù)
void main()
{
IR_Out = 1; // 此口為MCU輸入口,故需要置1
IT0 = 1; // 外部中斷0,下降沿觸發(fā)
EX0 = 1; // 準許外部中斷
while(1)
{
while(mode==1)
{
lcdIR_init();
while(1)
fmq=led=1;
}
while(mode==0)
{
lcdtime_init();
while(1)
display_settime();
}
}
}
|