|
// 本程序主要是遙控器解碼和1602驅動程序
//-------------------------------------------------------
// LCD1602 IR-DECODE
// 連線表: CPU=89S52
// SysClock=12MHz
// LCD: 1602
// 功能:解碼紅外遙控器
// 遙控器芯片:tc9012-011
#include <at89x52.h>
#define uchar unsigned char
#define uint unsigned int
/*----------------------------控制I/O口設置,根據實際而定---------------*/
#define RS P0_7 //RS數據命令選擇端,高電平數據,低電平命令
#define RW P0_6 //RW讀寫選擇端,高電平讀操作,低電平寫操作
#define E P0_5 //E使能控制端,E高電平跳變為低電平時LCD執行命令
#define DATA P2 //數據端口定義
#define D0 P2_0
#define D1 P2_1
#define D2 P2_2
#define D3 P2_3
#define D4 P2_4
#define D5 P2_5
#define D6 P2_6
#define D7 P2_7
#define KEY1 P1_0
#define KEY2 P1_1
#define IR_RE P3_2
/*------------------------------------------------------------------------------*/
bit k=0; //紅外解碼判斷標志位,為0則為有效信號,為1則為無效
uchar n=0; //用來控制外部中斷
uchar code str0[16]=" REMOTE CONTROL"; //開機畫面顯示
uchar code str1[16]=" IR-CODE: ";
uchar code str2[16]="ERROR";
uchar *p0=str0;
uchar *p1=str1;
uchar *p2=str2;
delay1ms(uint k);
void disp(void); //紅外鍵值顯示程序
uchar data date[4]; //date數組為存放地址原碼,反碼,數據原碼,反碼
/*------------------------LCD忙判斷子程序--------------------------------------*/
void busy()
{
RS=0;RW=1;
E=0;E=1;DATA=0xff;
while(D7);
}
/*----------------------- 寫命令子程序-----------------------------------------*/
void wcom(uchar com)
{
busy();
RS=0;RW=0;
E=1;
DATA=com;
E=0;
}
/*-------------------------寫數據子程序--------------------------------------*/
void wdata(uchar dat)
{
busy();
RS=1;RW=0;
E=1;
DATA=dat;
E=0;
}
/*--------------------------讀命令子程序-----------------------------------*/
uchar rcom(void)
{
uchar com;
busy();
RS=0;RW=1;
DATA=0xff;
E=1;
com=DATA;
E=0;
return(com);
}
/*----------------------------讀數據子程序-----------------------------*/
uchar rdat(void)
{
uchar dat;
busy();
RS=1;RW=1;
DATA=0xff;
E=1;
dat=DATA;
E=0;
return(dat);
}
/*--------------------------延時1ms程子程序-----------------------*/
delay1000()
{
uint i,j;
for(i=0;i<1;i++)
for(j=0;j<124;j++)
;
}
/*---------------------------延時882us子程序-----------------------*/
delay882()
{
uint i,j;
for(i=0;i<1;i++)
for(j=0;j<109;j++)
;
}
/*--------------------------延時2400ms程子程序-----------------------*/
delay2400()
{
uint i,j;
for(i=0;i<3;i++)
for(j=0;j<99;j++)
;
}
/*--------------------------以下為初始化程序,由上面子程序組成,根據個人愛好-----------*/
/******************************清屏程序***********************************/
void clear()
{ wcom (0x01);}
/******************************歸位程序********************************/
void rehome()
{ wcom(0x02); }
/*******************8*****888**88888顯示模式設定8888888888888888888888*/
void mode(bit x)
{
if(x==1)wcom(0x38); //兩行5*8 mode
else wcom(0x34); //一行5*10 mode
}
/*------------------------顯示開關控制命令----------------------------*/
void on_off(bit x)
{
if(x==1)wcom(0x0f); //顯示開,光標開,光標閃爍
else wcom(0x0c); //顯示開,光標關
}
/*------------------------init初始化組合-------------------------*/
void init()
{
clear(); //清屏
mode(1); //模式設置
on_off(1); //顯示設置
wcom(0x06); //移動方式
}
/*---------------------------對字符串的處理------------------------*/
void strchar(uchar *p)
{
while(*p!='\0')
{
wdata(*p);
p++;
}
}
/*----------------------------------------------------------*/
/*-----------------------紅外解碼程序(核心)-----------------*/
/*----------------------------------------------------------*/
void IR_decode()
{
uchar i,j;
while(IR_RE==0);
delay2400();
if(IR_RE==1) //延時2.4ms后如果是高電平則是新碼
{
delay2400(); //延時4.8ms避開4.5ms的高電平
for(i=0;i<4;i++)
{
for(j=0;j<8;j++)
{
while(IR_RE==0); //等待地址碼第1位高電平到來
delay882(); //延時882ms判斷此時引腳電平
///CY=IR_RE;
if(IR_RE==0)
{
date[i]>>=1;
date[i]=date[i]&0x7f;
}
else if(IR_RE==1)
{
delay1000();
date[i]>>=1;
date[i]=date[i]|0x80;
}
} //1位數據接收結束
} //32位二進制碼接收結束
}
}
/*------------------二進制碼轉換為壓縮型BCD碼,并顯示---------------*/
void two_2_bcd(uchar date)
{
uchar temp;
temp=date;
date&=0xf0;
date>>=4; //右移四位得到高四位碼
date&=0x0f; //與0x0f想與確保高四位為0
if(date<=0x09)
{
// wcom(0xcb);
wdata(0x30+date); //lcd顯示鍵值高四位
}
else
{
date=date-0x09;
//wcom(0xcb);
wdata(0x40+date);
}
date=temp;
date&=0x0f;
if(date<=0x09)
{
wdata(0x30+date); //lcd顯示低四位值
}
else
{
date=date-0x09;
wdata(0x40+date);
}
wdata(0x48); //顯示字符'H'
}
//////////////////////////////轉換程序結束///////////////////////////
/*----------------------解碼成功后,1602顯示鍵值子程序---------------*/
void disp()
{
uchar date1;
date1=date[3]^0xff; //如果得到的數據原碼和數據反碼相反
if(date[2]==date1) //顯示鍵值
{
wcom(0xc0);
two_2_bcd(date[0]);
wdata(0x20);
two_2_bcd(date[1]);
wdata(0x20);
two_2_bcd(date[2]);
wdata(0x20);
two_2_bcd(date[3]);
}
}
/*------------------------外部中斷0程序-------------------------*/
/*------------------主要用于處理紅外遙控鍵值--------------------*/
void int0() interrupt 0
{
uint i;
for(i=0;i<4;i++)
{
delay1000();
if(IR_RE==1){k=~k;} //剛開始為4.5ms的引導碼,如果4ms內出現高電平則退出解碼程序
}
if(k==0)
{
EX0=0; //檢測到有效信號關中斷,防止干擾
IR_decode(); //如果接收到的是有效信號,則調用解碼程序
disp(); //解碼成功,調用顯示程序,顯示該鍵值
}
EX0=1; //開外部中斷,允許新的遙控按鍵
}
/*---------------------------------------------------------------*/
/* 以下為主程序,主要對LCD初始化,開始界面設置 */
/*---------------------------------------------------------------*/
void main(void)
{
SP=0x60; //堆棧指針
TMOD=0x11; //定時器模式設置所選為 模式1
TH0=0xd8; //定時器初值理論為 10ms;
TL0=0xf7; //實際取d8f7
ET0=1; //允許定時器0中斷
EX0=1; //允許外部中斷0,用于檢測紅外遙控器按鍵
EA=1; //總中斷開
init(); //初始化LCD
wcom(0x80); //寫入字符的地址為第1行第1列
strchar(p0); //調用顯示字符串函數
wcom(0xc0);
//strchar(p1);
while(1);
}
|
|