/**
*************************************************************************
* @file main.c
* @author xr
* @date 2014年3月31日22:30:08
* @version V1.2.3
* @brief 串口通信+紅外通信 通過串口發(fā)送紅外遙控器的解碼值到PC
* @note 單片機(jī)STC89C52RC MCU 晶振 11.0592MHZ
*************************************************************************
*/
#include <reg52.h>
void ConfigUart();
void UartSend(unsigned char dat);
void delayms(unsigned int xms);
extern bit irflag;
extern unsigned char ircode[4];
extern void ConfigInfrared();
void main()
{
ConfigUart();
ConfigInfrared();
while (1)
{
if (irflag) //接收到紅外數(shù)據(jù)
{
irflag = 0;
UartSend(ircode[0]); //發(fā)送用戶碼
delayms(100);//延時(shí)100ms
UartSend(ircode[2]); //發(fā)送鍵碼
}
}
}
/**
* @brief 延時(shí)xms
* @param xms
* @retval 無
*/
void delayms(unsigned int xms)
{
unsigned int x, y;
for (x = 0; x < xms; x++)
for (y = 0; y < 110; y++);
}
/**
* @brief 配置串口通信
* @param 無
* @retval 無
*/
void ConfigUart()
{
TMOD &= 0x0F;//清零T1控制位
TMOD |= 0x20;//T1方式2,八位自動(dòng)重裝模式
TH1 = 0xFD; //波特率 = 256-1/2^SMOD*T1溢出率 X=256-11059200/12/32/波特率
TL1 = TH1;//波特率9600bps
TR1 = 1;
ET1 = 0;//只用T1的計(jì)數(shù)
SCON |= 0x50;//串口方式1 SM0 SM1 SM2 REN TB8 RB8 TI RI 0101 0000
/*
SM0 = 0;
SM1 = 1;//方式1 SM2多機(jī)通信位
REN = 1;//允許接收數(shù)據(jù)
TI = 0;//發(fā)送完成中斷標(biāo)志
RI = 0;//接收完成中斷標(biāo)志
*/
ES = 1;//開串口中斷
EA = 1;//開總中斷
}
/**
* @brief 串口發(fā)送一個(gè)字節(jié)數(shù)據(jù)到PC
* @param 待發(fā)送數(shù)據(jù)
* @retval 無
*/
void UartSend(unsigned char dat)
{
SBUF = dat;
//while (!TI);//等待發(fā)送完成,在中斷模式下不需要等待,否則進(jìn)不了中斷
}
/**
* @brief 串口中斷
* @param 無
* @retval 無
*/
void Uart_ISP() interrupt 4 //串口中斷標(biāo)號(hào)是4
{
if (TI) //等待發(fā)送完成
{ //發(fā)送完成
TI = 0;//清零
}
}
/**
**************************************************************
* @file infrared.c
* @author xr
* @date 2014年3月31日20:51:23
* @version V1.2.3
* @brief 紅外通信--紅外遙控器NEC協(xié)議解碼
* @note 單片機(jī)STC89C52RC MCU 晶振 11.0592MHZ
**************************************************************
*/
#include <reg52.h>
sbit IRD = P3^3;//紅外接收檢測(cè)端口
bit irflag = 0;//接收到數(shù)據(jù)的標(biāo)志
unsigned char ircode[4];//存放紅外遙控器發(fā)送的用戶碼,用戶碼反碼 鍵碼 鍵碼反碼
/**
* @brief 紅外配置
* @param 無
* @retval 無
*/
void ConfigInfrared()
{
TH0 = 0;
TL0 = 0;//清零T0計(jì)數(shù)
TMOD &= 0xF0;
TMOD |= 0x01;//T0方式1
TR0 = 0;//在沒有紅外信號(hào)之前先關(guān)閉T0
ET0 = 0;//只用T0的計(jì)數(shù)
//外部中斷1
IT1 = 1;//設(shè)置外部中斷觸發(fā)方式為下降沿觸發(fā)
EX1 = 1;//開啟外部中斷1
}
/**
* @brief 獲得IRD紅外檢測(cè)引腳的高電平時(shí)間(空閑時(shí)間)
* @param 無
* @retval 高電平持續(xù)的計(jì)數(shù)值
*/
unsigned int getHeighTime()
{
//在檢測(cè)外部信號(hào)前,必須先將IRDIO口拉高
IRD = 1;
TH0 = 0;
TL0 = 0;//清零T0計(jì)數(shù)
TR0 = 1;//開啟T0計(jì)數(shù)
while (IRD) //持續(xù)高電平
{
//超時(shí)判斷
if (TH0 > 0x40) //當(dāng)IRD持續(xù)高電平時(shí)間17.7ms,遠(yuǎn)遠(yuǎn)大于引導(dǎo)碼的9ms,是誤碼
{
break;//退出
}
}
TR0 = 0;//停止計(jì)數(shù)
return (TH0*256 + TL0);//返回高電平計(jì)數(shù)值
}
/**
* @brief 獲得IRD紅外檢測(cè)引腳的低電平時(shí)間(載波時(shí)間)
* @param 無
* @retval 低電平持續(xù)的計(jì)數(shù)值
*/
unsigned int getLowTime()
{
IRD = 1;//釋放IRD,檢測(cè)外部信號(hào)
TH0 = 0;
TL0 = 0;//清零T0計(jì)數(shù)
TR0 = 1;//開始計(jì)數(shù)
while (!IRD) //持續(xù)低電平
{
if (TH0 > 0x40) //超過18ms就是誤碼,錯(cuò)誤信號(hào)
{
break;
}
}
TR0 = 0;//停止計(jì)數(shù)
return (TH0*256 + TL0);//返回低電平計(jì)數(shù)值
}
/**
* @brief 外部中斷1服務(wù)程序,檢測(cè)紅外信號(hào)
* @param 無
* @retval 無
*/
void EXINT_ISP() interrupt 2 //外部中斷標(biāo)號(hào)2
{
unsigned char byte;//接收數(shù)據(jù)
unsigned char i, j;
unsigned int time;//時(shí)間
time = getLowTime();//獲得載波時(shí)間
if (time < 7833 || time > 8755) //引導(dǎo)碼載波是9ms,這里規(guī)定在8.5ms-9.5ms之間是9ms的載波
{
//范圍之外,誤碼
IE1 = 0;//清零外部中斷1中斷標(biāo)志,為下一次再進(jìn)入中斷
return;//退出中斷
}
//否則是9ms的載波
time = getHeighTime();//空閑時(shí)間
if (time < 3686 || time > 4608) //引導(dǎo)碼的空閑時(shí)間4.5ms 這里規(guī)定4ms-5ms是4.5ms的空閑
{
IE1 = 0;//清零中斷標(biāo)志
return;//退出中斷
}
//否則是4.5ms的空閑
//開始接收用戶碼和鍵碼等
for (i = 0; i < 4; i++)
{
for (j = 0; j < 8; j++)
{
time = getLowTime();//載波
if (time < 423 || time > 608) //560us的載波和560us的空閑是0 范圍460us-660us
{
IE1 = 0;
return;
}
//560us載波
time = getHeighTime();
if (time > 423 && time < 608) //560us空閑
{
//bit '0'
byte >>= 1;//低位在前,移入一位0
}
else if (time > 1198 && time < 1658) //1.68ms的空閑是1 范圍 1300us-1800us
{
//bit '1'
byte >>= 1;//移入一位
byte |= 0x80;//移入的一位置1
}
else
{
//誤碼
IE1 = 0;
return;//退出中斷
}
}
ircode = byte;
}
//接收完成
irflag = 1;
//退出中斷時(shí)清零中斷標(biāo)志
IE1 = 0;
}