打印
[技术问答]

串口通信+红外通信 通过串口发送红外遥控器的解码值到PC

[复制链接]
1820|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
Tennasi|  楼主 | 2016-2-28 22:41 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
/**
  *************************************************************************
  * [url=home.php?mod=space&uid=288409]@file[/url]       main.c
  * [url=home.php?mod=space&uid=187600]@author[/url]     xr
  * [url=home.php?mod=space&uid=212281]@date[/url]       2014年3月31日22:30:08
  * [url=home.php?mod=space&uid=895143]@version[/url]    V1.2.3
  * [url=home.php?mod=space&uid=247401]@brief[/url]      串口通信+红外通信 通过串口发送红外遥控器的解码值到PC
  * [url=home.php?mod=space&uid=536309]@NOTE[/url]       单片机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) //接收到红外数据
{
irflag = 0;
UartSend(ircode[0]); //发送用户码
delayms(100);//延时100ms
UartSend(ircode[2]); //发送键码
}
}
}

/**
  * @brief     延时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,八位自动重装模式
TH1 = 0xFD; //波特率 = 256-1/2^SMOD*T1溢出率  X=256-11059200/12/32/波特率
TL1 = TH1;//波特率9600bps
TR1 = 1;
ET1 = 0;//只用T1的计数
SCON |= 0x50;//串口方式1 SM0 SM1 SM2 REN TB8 RB8 TI RI 0101 0000
/*
SM0 = 0;
SM1 = 1;//方式1 SM2多机通信位
REN = 1;//允许接收数据
TI = 0;//发送完成中断标志
RI = 0;//接收完成中断标志
*/
ES = 1;//开串口中断
EA = 1;//开总中断
}


沙发
Tennasi|  楼主 | 2016-2-28 22:41 | 只看该作者
/**
  * @brief     串口发送一个字节数据到PC
  * @param     待发送数据
  * @retval    无
  */
void UartSend(unsigned char dat)
{
SBUF = dat;
//while (!TI);//等待发送完成,在中断模式下不需要等待,否则进不了中断
}

/**
  * @brief     串口中断
  * @param     无
  * @retval    无
  */
void Uart_ISP() interrupt 4 //串口中断标号是4
{
if (TI) //等待发送完成
{ //发送完成
TI = 0;//清零
}
}


/**
  **************************************************************
  * @file      infrared.c
  * @author    xr
  * @date      2014年3月31日20:51:23
  * @version   V1.2.3
  * @brief     红外通信--红外遥控器NEC协议解码
  * @note      单片机STC89C52RC MCU  晶振 11.0592MHZ
  **************************************************************
  */

#include <reg52.h>

sbit IRD = P3^3;//红外接收检测端口

bit irflag = 0;//接收到数据的标志
unsigned char ircode[4];//存放红外遥控器发送的用户码,用户码反码 键码 键码反码

/**
  * @brief     红外配置
  * @param     无
  * @retval    无
  */
void ConfigInfrared()
{
TH0 = 0;
TL0 = 0;//清零T0计数
TMOD &= 0xF0;
TMOD |= 0x01;//T0方式1
TR0 = 0;//在没有红外信号之前先关闭T0
ET0 = 0;//只用T0的计数

//外部中断1
IT1 = 1;//设置外部中断触发方式为下降沿触发
EX1 = 1;//开启外部中断1
}

/**
  * @brief     获得IRD红外检测引脚的高电平时间(空闲时间)
  * @param     无
  * @retval    高电平持续的计数值
  */
unsigned int getHeighTime()
{
//在检测外部信号前,必须先将IRDIO口拉高
IRD = 1;
TH0 = 0;
TL0 = 0;//清零T0计数
TR0 = 1;//开启T0计数

while (IRD) //持续高电平
{
//超时判断
if (TH0 > 0x40) //当IRD持续高电平时间17.7ms,远远大于引导码的9ms,是误码
{
break;//退出
}
}
TR0 = 0;//停止计数

return (TH0*256 + TL0);//返回高电平计数值
}

/**
  * @brief     获得IRD红外检测引脚的低电平时间(载波时间)
  * @param     无
  * @retval    低电平持续的计数值
  */
unsigned int getLowTime()
{
IRD = 1;//释放IRD,检测外部信号
TH0 = 0;
TL0 = 0;//清零T0计数
TR0 = 1;//开始计数

while (!IRD) //持续低电平
{
if (TH0 > 0x40) //超过18ms就是误码,错误信号
{
break;
}
}
TR0 = 0;//停止计数

return (TH0*256 + TL0);//返回低电平计数值
}

/**
  * @brief     外部中断1服务程序,检测红外信号
  * @param     无
  * @retval    无
  */
void EXINT_ISP() interrupt 2  //外部中断标号2
{
unsigned char byte;//接收数据
unsigned char i, j;
unsigned int time;//时间

time = getLowTime();//获得载波时间
if (time < 7833 || time > 8755) //引导码载波是9ms,这里规定在8.5ms-9.5ms之间是9ms的载波
{
//范围之外,误码
IE1 = 0;//清零外部中断1中断标志,为下一次再进入中断
return;//退出中断
}
//否则是9ms的载波
time = getHeighTime();//空闲时间
if (time < 3686 || time > 4608) //引导码的空闲时间4.5ms 这里规定4ms-5ms是4.5ms的空闲
{
IE1 = 0;//清零中断标志
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;

//退出中断时清零中断标志
IE1 = 0;
}

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

22

主题

169

帖子

1

粉丝