专家
公告
财富商城
电子网
旗下网站
首页
问题库
专栏
标签库
话题
专家
NEW
门户
发布
提问题
发文章
51单片机
红外波形分析怎么分析呀?
2020-02-04 09:04
发布
×
打开微信“扫一扫”,打开网页后点击屏幕右上角分享按钮
站内问答
/
51单片机
2018
8
8
家里的电视机遥控器、音响遥控器等好多的遥控经常不知放到哪里去了,想做一个公用的遥控发射器,买了USBee AX来显示每个遥控器的波形,保存了几十个按键的波形,但是发现一个一个分析还是很困难的,有什么好的分析方法吗?希望各位多加指教。
下面是一个按键的波形:
红外图片.jpg
(174.94 KB, 下载次数: 1)
下载附件
2012-4-26 21:40 上传
友情提示:
此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
8条回答
mcu_mouse
2020-02-05 03:33
本帖最后由 mcu_mouse 于 2012-4-26 23:37 编辑
/************************* 说 明 *********************************/
/* 以一个9ms的低电平和4.5ms的高电平为引导码,后跟32位二进制代码 */
/* 前16位为8位用户码及其反码,后16位为8位的操作码及其反码 */
/* 以脉宽为0.565ms、间隔0.56ms、周期为1.125ms的组合表示"0"; */
/* 以脉宽为0.565ms、间隔1.685ms、周期为2.25ms的组合表示"1"。 */
/* 注意:接收码的脉宽与间隔是对发射码取反的,即间隔是0.565ms */
/******************************************************************/
#include <REGX52.h>
#define uchar unsigned char
uchar data IRcode[4];//定义一个4字节的数组用来存储代码
uchar CodeTemp; //编码字节缓存变量
uchar i,j,k;//延时用的循环变量
sbit IRsignal=P3^2; //HS0038接收头OUT端直接连P3.2(INT0)
sbit LED = P3^5;
/**************************延时0.9ms子程序**********************/
void Delay0_9ms(void)
{
uchar j,k;
for(j=18;j>0;j--)
{
for(k=20;k>0;k--)
;
}
}
/***************************延时1ms子程序**********************/
void Delay1ms(void)
{
uchar i,j;
for(i=2;i>0;i--)
for(j=230;j>0;j--)
;
}
/***************************延时4.5ms子程序**********************/
void Delay4_5ms(void)
{
uchar i,j;
for(i=10;i>0;i--)
for(j=225;j>0;j--)
;
}
/**************************** 延时子程序 ************************/
void Delay(void)
{
uchar i,j,k;
for(i=200;i>0;i--)
for(j=200;j>0;j--)
for(k=3;k>0;k--)
;
}
/************************中断0解码服务子程序**********************/
void int0(void) interrupt 0 using 2
{
EA=0;
LED = 0;
for(k=0;k<10;k++)
{
Delay0_9ms();
if (IRsignal==1)//如果0.9ms后IRsignal=1,说明不是引导码
{
k=10;break;
}
else
if(k==9) //如果持续了10×0.9ms=9ms的低电平,说明是引导码
{
while(IRsignal==0);
Delay4_5ms(); //跳过持续4.5ms的高电平
for(i=0;i<4;i++) //分别读取4个字节
{
for(j=1;j<=8;j++) //每个字节8个bit的判断
{
while(IRsignal==0); //等待上升沿
Delay0_9ms(); //从上升沿那一时刻开始延时0.9ms,再判断IRsignal
if(IRsignal==1) //如果IRsignal是"1",则向右移入一位"1"
{
Delay1ms();
CodeTemp=CodeTemp|0x80;
if(j<8)
CodeTemp=CodeTemp>>1;
}
else
if(j<8)CodeTemp=CodeTemp>>1; //如果IRsignal是"0",则向右移一位,自动补"0"
}
IRcode
=CodeTemp;
CodeTemp=0;
}
for(i=0;i<4;i++) //通过串口将代码发出
{
SBUF=IRcode
;
while(!TI); //等待一个字节发送完毕
TI=0;
}
Delay();
}
}
EA=1;
LED = 1;
}
/***********************串口初始化程序*********************/
void initUart(void)
{
TMOD|=0x20;
SCON=0x50;
PCON|=0x80;
TH1=0xff; //57600bps @ 11.0592MHz
TL1=0xff;
TR1=1;
}
/**************************主程序*************************/
void main()
{
initUart();
IT0=1; //INT0为负边沿触发, (1:负边沿触发,0:低电平触发)
EX0=1; //外部中断INT0开, (1:开,????? 0:关??? )
EA=1; //开所有中断
CodeTemp=0; //初始化红外编码字节缓存变量
Delay();
while(1);
}
直接用这个程序解码红外遥控了再用串口输出就好了。或者再改成红外学习的,红外学习的话就得再加上38K的载波,
上面的是解NEC码的。再发一个解RC-5码的。自己再稍微修改下就好了。红外接收处理方面肯定是能用的。另外,这2个程序都是用的11.0592的晶振,再声明下,这2个程序都是网上的。
我稍微修改了下来用的。
#include "../Src/INC/STC_NEW_8051.H"
#include <stdio.h>
#include "../Src/INC/CONFIG.H"
#include "../Src/LED/LED.H"
#include "../Src/Uart/UART.H"
//==============================================================================
// 定义红外接收的接口(根据实际的硬件接线进行修改)
//==============================================================================
sbit Ir_RECV = P3^3; // INT1
//==============================================================================
//
// 状态机的含义:
//
// 状态S0: 初始状态
// 状态S1: 1,1 状态,在两个bit中间触发中断
// 状态S2: 0 状态
//
// S1->S1: 1个周期
// S1->S2: 1.5个周期
// S2->S2: 1个周期或2个周期
// S2->S1: 1.5个周期
//
//==============================================================================
//==============================================================================
// 时间常数(使用晶震频率为11.0592MHz)
//==============================================================================*/
#define CYCLE_1_0 0x65B // 1776us
#define CYCLE_1_5 0x989 // 2664us
#define CYCLE_2_0 0x0CB7 // 3552us
#define TH_CYCLE_1_0 (CYCLE_1_0>>8) //提取定时器高8位值
#define TH_CYCLE_1_5 (CYCLE_1_5>>8)
#define TH_CYCLE_2_0 (CYCLE_2_0>>8)
// 用于解码的变量
u16 nIrRecvCode=0xFFFF; // 保存解码数值(1个开始位 1个控制位 5个地址位 6个命令位)
u8 nIrBitCount=0; // 记录已经解码的位数
u8 nIrState=0; // 初始状态
u8 nBuffer;
bit g_bIrOK = 0;
// 初始化中断及定时器
void IrInit()
{
// 定时器0
TMOD |= 0x01; // T0工作于方式1,即16位定时器
ET0 = 0; // 关定时器0中断允许
TR0 = 0; // 关闭定时器0
TH0 = 0;
TL0 = 0;
AUXR = 0x00;
// 外部中断源INT0
EX1 = 1; // 允许外部中断源INT1
PX1 = 1; // 外部中断源为高优先级
IT1 = 1; // 边缘触发
// 允许中断
EA=1;
}
// 处理红外命令
void IrProcessCommand(int remotecode)
{
nBuffer=(u8)(remotecode&0xFF);
// speaData(nBuffer,2); //我的自定义拆字子程序,提供给LCD1602显示
}
// 外部中断0的处理函数 SAA_3010T 解码程序
void IrInt1(void) interrupt 2
{
// 保存计数器的高位,作为判断周期长短的依据
u8 HighTick = TH0;
// 重置计数器
TH0 = 0;TL0 = 0;TR0 = 1;ET0 = 1;
// 状态转移图
switch( nIrState )
{
case 0: // 第一个起始位
nIrBitCount = 1;
nIrRecvCode = 0;
nIrState = 2;
break;
case 1: // 状态1
if(HighTick == TH_CYCLE_1_0) // S1->S1 (持续位1状态)
{
nIrState = 1;
nIrBitCount++;
nIrRecvCode = nIrRecvCode<<1;
nIrRecvCode = nIrRecvCode+1;
}
else if(HighTick == TH_CYCLE_1_5) // S1->S2 ( 1,1,0 ) 转到位0状态
{
nIrState = 2;
nIrBitCount = nIrBitCount+2;
nIrRecvCode = nIrRecvCode<<1;
nIrRecvCode = nIrRecvCode+1;
nIrRecvCode = nIrRecvCode<<1;
}
else // 错误状态
{
nIrBitCount = 0;
nIrState = 0;
}
break;
case 2: // 状态2
if(HighTick == TH_CYCLE_1_0) // S2->S2(持续位0状态)
{
nIrState = 2;
nIrBitCount++;
nIrRecvCode = nIrRecvCode<<1;
}
else if(HighTick == TH_CYCLE_1_5) // S2->S1(转到位1状态)
{
nIrState = 1;
nIrBitCount++;
nIrRecvCode = nIrRecvCode<<1;
nIrRecvCode = nIrRecvCode+1;
}
else if(HighTick == TH_CYCLE_2_0) // S2->S2
{
// 0->1->0
nIrState = 2;
nIrBitCount = nIrBitCount+2;
nIrRecvCode = nIrRecvCode<<1;
nIrRecvCode = nIrRecvCode+1;
nIrRecvCode = nIrRecvCode<<1;
}
else // 错误状态
{
nIrBitCount = 0;
nIrState = 0;
}
break;
default:break;
}
}
// 定时器T0的中断处理函数
void IrTimer0(void) interrupt 1
{
ET0 = 0; // 关定时器0中断允许
TR0 = 0; // 关闭定时器0
// 出现了超时
if( nIrBitCount == 13 )
{
if((nIrState == 1)||(nIrState == 2)) // 0,1
{
nIrBitCount ++;
nIrRecvCode = nIrRecvCode<<1;
nIrRecvCode = nIrRecvCode+1;
}
}
// 检查是否有合理数据
if( nIrBitCount == 14 )
{
// 停止中断0
EX0 = 0;
// 处理遥控命令
IrProcessCommand(~nIrRecvCode);//&0x0FFF);
// 重新初始化初始化
nIrBitCount = 0;
nIrState = 0;
g_bIrOK = 1;
// Display(28,0);
}
// 启用中断
EX0 = 1;
}
void KeyProcess()
{
static u8 ncomp ;
if(g_bIrOK == 1)
{
u8 bdata temp[3];
temp[2] = ( (~nIrRecvCode)) & 0x3F;
temp[1] = ( (~nIrRecvCode)>>6) & 0x1F;
temp[0] = ( (~nIrRecvCode)>>11) & 0x07;
if(ncomp != temp[0])
{
switch(temp[2])
{
case 0x17: //夜间 0x17
// Display(temp[2]);
// WByte(temp[2]);
break;
case 0x11: //演习 0x11
break;
case 0x14: //保护 0x14
break;
case 0x15: //校枪 0x15
break;
case 0x12: //时间 0x12
break;
case 0x10: //弹夹数 0x10
break;
case 0x13: //编号 0x13
break;
case 0x16: //设置 0x16
break;
case 0x3A: //命值 0x3A
break;
case 0x32: //1 0x32
break;
case 0x2A: //2 0x2A
break;
case 0x22: //3 0x22
break;
case 0x39: //频点 0x39
break;
case 0x31: //4 0x31
break;
case 0x29: //5 0x29
break;
case 0x21: //6 0x21
break;
case 0x38: //VIP 0x38
break;
case 0x30: //7 0x30
break;
case 0x28: //8 0x28
break;
case 0x20: //9 0x20
break;
case 0x35: //0 0x35
break;
case 0x3F: //分组 0x3F
break;
case 0x3D: //清除 0x3D
break;
case 0x27: //确认 0x27
break;
case 0x37: //A 0x37
break;
case 0x3C: //B 0x3C
break;
case 0x34: //C 0x34
break;
case 0x26: //D 0x26
break;
default: break;
}
ncomp = temp[0];
}
g_bIrOK = 0;
}
}
加载中...
查看其它8个回答
一周热门
更多
>
相关问题
【东软载波ESF0654 PDS开发板活动】开箱
1 个回答
东软载波ESF0654 PDS开发板外部中断
1 个回答
东软载波ESF0654 PDS开发板高级控制定时器AD16C4T
1 个回答
用串口调试助手为什么只能在hex模式接收发送而在文本模式不行
9 个回答
触摸芯片SC02B/SC04B在地砖灯的设计方案
1 个回答
相关文章
51单片机与蓝牙模块连接
0个评论
51单片机的硬件结构
0个评论
基于51单片机的无线遥控器制作
0个评论
51单片机 AD转换
0个评论
51单片机数码管递增显示
0个评论
如何实现对单片机寄存器的访问
0个评论
基于51单片机的指纹密码锁
0个评论
×
关闭
采纳回答
向帮助了您的知道网友说句感谢的话吧!
非常感谢!
确 认
×
关闭
编辑标签
最多设置5个标签!
51单片机
保存
关闭
×
关闭
举报内容
检举类型
检举内容
检举用户
检举原因
广告推广
恶意灌水
回答内容与提问无关
抄袭答案
其他
检举说明(必填)
提交
关闭
×
打开微信“扫一扫”,打开网页后点击屏幕右上角分享按钮
×
付费偷看金额在0.1-10元之间
确定
×
关闭
您已邀请
0
人回答
查看邀请
擅长该话题的人
回答过该话题的人
我关注的人
/************************* 说 明 *********************************/
/* 以一个9ms的低电平和4.5ms的高电平为引导码,后跟32位二进制代码 */
/* 前16位为8位用户码及其反码,后16位为8位的操作码及其反码 */
/* 以脉宽为0.565ms、间隔0.56ms、周期为1.125ms的组合表示"0"; */
/* 以脉宽为0.565ms、间隔1.685ms、周期为2.25ms的组合表示"1"。 */
/* 注意:接收码的脉宽与间隔是对发射码取反的,即间隔是0.565ms */
/******************************************************************/
#include <REGX52.h>
#define uchar unsigned char
uchar data IRcode[4];//定义一个4字节的数组用来存储代码
uchar CodeTemp; //编码字节缓存变量
uchar i,j,k;//延时用的循环变量
sbit IRsignal=P3^2; //HS0038接收头OUT端直接连P3.2(INT0)
sbit LED = P3^5;
/**************************延时0.9ms子程序**********************/
void Delay0_9ms(void)
{
uchar j,k;
for(j=18;j>0;j--)
{
for(k=20;k>0;k--)
;
}
}
/***************************延时1ms子程序**********************/
void Delay1ms(void)
{
uchar i,j;
for(i=2;i>0;i--)
for(j=230;j>0;j--)
;
}
/***************************延时4.5ms子程序**********************/
void Delay4_5ms(void)
{
uchar i,j;
for(i=10;i>0;i--)
for(j=225;j>0;j--)
;
}
/**************************** 延时子程序 ************************/
void Delay(void)
{
uchar i,j,k;
for(i=200;i>0;i--)
for(j=200;j>0;j--)
for(k=3;k>0;k--)
;
}
/************************中断0解码服务子程序**********************/
void int0(void) interrupt 0 using 2
{
EA=0;
LED = 0;
for(k=0;k<10;k++)
{
Delay0_9ms();
if (IRsignal==1)//如果0.9ms后IRsignal=1,说明不是引导码
{
k=10;break;
}
else
if(k==9) //如果持续了10×0.9ms=9ms的低电平,说明是引导码
{
while(IRsignal==0);
Delay4_5ms(); //跳过持续4.5ms的高电平
for(i=0;i<4;i++) //分别读取4个字节
{
for(j=1;j<=8;j++) //每个字节8个bit的判断
{
while(IRsignal==0); //等待上升沿
Delay0_9ms(); //从上升沿那一时刻开始延时0.9ms,再判断IRsignal
if(IRsignal==1) //如果IRsignal是"1",则向右移入一位"1"
{
Delay1ms();
CodeTemp=CodeTemp|0x80;
if(j<8)
CodeTemp=CodeTemp>>1;
}
else
if(j<8)CodeTemp=CodeTemp>>1; //如果IRsignal是"0",则向右移一位,自动补"0"
}
IRcode=CodeTemp;
CodeTemp=0;
}
for(i=0;i<4;i++) //通过串口将代码发出
{
SBUF=IRcode;
while(!TI); //等待一个字节发送完毕
TI=0;
}
Delay();
}
}
EA=1;
LED = 1;
}
/***********************串口初始化程序*********************/
void initUart(void)
{
TMOD|=0x20;
SCON=0x50;
PCON|=0x80;
TH1=0xff; //57600bps @ 11.0592MHz
TL1=0xff;
TR1=1;
}
/**************************主程序*************************/
void main()
{
initUart();
IT0=1; //INT0为负边沿触发, (1:负边沿触发,0:低电平触发)
EX0=1; //外部中断INT0开, (1:开,????? 0:关??? )
EA=1; //开所有中断
CodeTemp=0; //初始化红外编码字节缓存变量
Delay();
while(1);
}
直接用这个程序解码红外遥控了再用串口输出就好了。或者再改成红外学习的,红外学习的话就得再加上38K的载波,
上面的是解NEC码的。再发一个解RC-5码的。自己再稍微修改下就好了。红外接收处理方面肯定是能用的。另外,这2个程序都是用的11.0592的晶振,再声明下,这2个程序都是网上的。
我稍微修改了下来用的。
#include "../Src/INC/STC_NEW_8051.H"
#include <stdio.h>
#include "../Src/INC/CONFIG.H"
#include "../Src/LED/LED.H"
#include "../Src/Uart/UART.H"
//==============================================================================
// 定义红外接收的接口(根据实际的硬件接线进行修改)
//==============================================================================
sbit Ir_RECV = P3^3; // INT1
//==============================================================================
//
// 状态机的含义:
//
// 状态S0: 初始状态
// 状态S1: 1,1 状态,在两个bit中间触发中断
// 状态S2: 0 状态
//
// S1->S1: 1个周期
// S1->S2: 1.5个周期
// S2->S2: 1个周期或2个周期
// S2->S1: 1.5个周期
//
//==============================================================================
//==============================================================================
// 时间常数(使用晶震频率为11.0592MHz)
//==============================================================================*/
#define CYCLE_1_0 0x65B // 1776us
#define CYCLE_1_5 0x989 // 2664us
#define CYCLE_2_0 0x0CB7 // 3552us
#define TH_CYCLE_1_0 (CYCLE_1_0>>8) //提取定时器高8位值
#define TH_CYCLE_1_5 (CYCLE_1_5>>8)
#define TH_CYCLE_2_0 (CYCLE_2_0>>8)
// 用于解码的变量
u16 nIrRecvCode=0xFFFF; // 保存解码数值(1个开始位 1个控制位 5个地址位 6个命令位)
u8 nIrBitCount=0; // 记录已经解码的位数
u8 nIrState=0; // 初始状态
u8 nBuffer;
bit g_bIrOK = 0;
// 初始化中断及定时器
void IrInit()
{
// 定时器0
TMOD |= 0x01; // T0工作于方式1,即16位定时器
ET0 = 0; // 关定时器0中断允许
TR0 = 0; // 关闭定时器0
TH0 = 0;
TL0 = 0;
AUXR = 0x00;
// 外部中断源INT0
EX1 = 1; // 允许外部中断源INT1
PX1 = 1; // 外部中断源为高优先级
IT1 = 1; // 边缘触发
// 允许中断
EA=1;
}
// 处理红外命令
void IrProcessCommand(int remotecode)
{
nBuffer=(u8)(remotecode&0xFF);
// speaData(nBuffer,2); //我的自定义拆字子程序,提供给LCD1602显示
}
// 外部中断0的处理函数 SAA_3010T 解码程序
void IrInt1(void) interrupt 2
{
// 保存计数器的高位,作为判断周期长短的依据
u8 HighTick = TH0;
// 重置计数器
TH0 = 0;TL0 = 0;TR0 = 1;ET0 = 1;
// 状态转移图
switch( nIrState )
{
case 0: // 第一个起始位
nIrBitCount = 1;
nIrRecvCode = 0;
nIrState = 2;
break;
case 1: // 状态1
if(HighTick == TH_CYCLE_1_0) // S1->S1 (持续位1状态)
{
nIrState = 1;
nIrBitCount++;
nIrRecvCode = nIrRecvCode<<1;
nIrRecvCode = nIrRecvCode+1;
}
else if(HighTick == TH_CYCLE_1_5) // S1->S2 ( 1,1,0 ) 转到位0状态
{
nIrState = 2;
nIrBitCount = nIrBitCount+2;
nIrRecvCode = nIrRecvCode<<1;
nIrRecvCode = nIrRecvCode+1;
nIrRecvCode = nIrRecvCode<<1;
}
else // 错误状态
{
nIrBitCount = 0;
nIrState = 0;
}
break;
case 2: // 状态2
if(HighTick == TH_CYCLE_1_0) // S2->S2(持续位0状态)
{
nIrState = 2;
nIrBitCount++;
nIrRecvCode = nIrRecvCode<<1;
}
else if(HighTick == TH_CYCLE_1_5) // S2->S1(转到位1状态)
{
nIrState = 1;
nIrBitCount++;
nIrRecvCode = nIrRecvCode<<1;
nIrRecvCode = nIrRecvCode+1;
}
else if(HighTick == TH_CYCLE_2_0) // S2->S2
{
// 0->1->0
nIrState = 2;
nIrBitCount = nIrBitCount+2;
nIrRecvCode = nIrRecvCode<<1;
nIrRecvCode = nIrRecvCode+1;
nIrRecvCode = nIrRecvCode<<1;
}
else // 错误状态
{
nIrBitCount = 0;
nIrState = 0;
}
break;
default:break;
}
}
// 定时器T0的中断处理函数
void IrTimer0(void) interrupt 1
{
ET0 = 0; // 关定时器0中断允许
TR0 = 0; // 关闭定时器0
// 出现了超时
if( nIrBitCount == 13 )
{
if((nIrState == 1)||(nIrState == 2)) // 0,1
{
nIrBitCount ++;
nIrRecvCode = nIrRecvCode<<1;
nIrRecvCode = nIrRecvCode+1;
}
}
// 检查是否有合理数据
if( nIrBitCount == 14 )
{
// 停止中断0
EX0 = 0;
// 处理遥控命令
IrProcessCommand(~nIrRecvCode);//&0x0FFF);
// 重新初始化初始化
nIrBitCount = 0;
nIrState = 0;
g_bIrOK = 1;
// Display(28,0);
}
// 启用中断
EX0 = 1;
}
void KeyProcess()
{
static u8 ncomp ;
if(g_bIrOK == 1)
{
u8 bdata temp[3];
temp[2] = ( (~nIrRecvCode)) & 0x3F;
temp[1] = ( (~nIrRecvCode)>>6) & 0x1F;
temp[0] = ( (~nIrRecvCode)>>11) & 0x07;
if(ncomp != temp[0])
{
switch(temp[2])
{
case 0x17: //夜间 0x17
// Display(temp[2]);
// WByte(temp[2]);
break;
case 0x11: //演习 0x11
break;
case 0x14: //保护 0x14
break;
case 0x15: //校枪 0x15
break;
case 0x12: //时间 0x12
break;
case 0x10: //弹夹数 0x10
break;
case 0x13: //编号 0x13
break;
case 0x16: //设置 0x16
break;
case 0x3A: //命值 0x3A
break;
case 0x32: //1 0x32
break;
case 0x2A: //2 0x2A
break;
case 0x22: //3 0x22
break;
case 0x39: //频点 0x39
break;
case 0x31: //4 0x31
break;
case 0x29: //5 0x29
break;
case 0x21: //6 0x21
break;
case 0x38: //VIP 0x38
break;
case 0x30: //7 0x30
break;
case 0x28: //8 0x28
break;
case 0x20: //9 0x20
break;
case 0x35: //0 0x35
break;
case 0x3F: //分组 0x3F
break;
case 0x3D: //清除 0x3D
break;
case 0x27: //确认 0x27
break;
case 0x37: //A 0x37
break;
case 0x3C: //B 0x3C
break;
case 0x34: //C 0x34
break;
case 0x26: //D 0x26
break;
default: break;
}
ncomp = temp[0];
}
g_bIrOK = 0;
}
}
一周热门 更多>