功能:显示遥控按键对应用户码毫无作用
红外遥控是类似于之前的串口通信但没有波特率的说法,主要就是按照红外遥控器发出信号的时序进行分析。
如我实验使用的DT9122D遥控器可从说明书中查得其信号时序(如下图)
图中的引导码前9ms为高电平后4.5ms为低电平表示红外信号的开始,是用于过滤噪声的。后面的用户码和键位码组成的32位信号才是表征键位的,键数据反码主要起到验证信号真伪的作用。
而用户编码的组成方式很有意思,图上读入的低(高)八位的用户编码的1、2、3、4…位 是真正的低(高)用户编码的8、7、6、5…位,键位码也一样。
其次,信号读入的关键在0、1的判别。0、1在红外遥控信号中用一组高低电平表示,其区别在于“接收解码”中高电平的持续时间(即宽度),在DT9122D遥控器上0持续0.56ms,1持续1.69ms,思路是每次接收完位信号前半段的低电平,并接收的高点平后延时tms(0.56ms 下面是具体代码实现。 数码管显示模块 为了信号读入的精确,将51芯片内置的T1定时/计数器作为参照。(推荐使用单片机小精灵) 在信号读入中需要三个延时:引导码判别9ms、引导码结束4.5ms、位布尔判别(取0信号和1信号宽度的中值为佳)0.84ms 关键是时序、时序和时序 *注意对中断开关的操作。准备工作
我抄我自己#define date P0//用于数码管显示
#define place P2//用于数码管显示
typedef unsigned int u16;
typedef unsigned char u8;
sbit IRIN=P3^2;//红外信号i/o,利用了外部中断
u8 code number[]={0x28,0x7e,0xa2,0x62,0x74,0x61,0x21,0x7a,0x20,0x60,0x30,0x25,0xa9,0x26,0xa1,0xb1};
//数码管显示字库
u8 code where[]={0xff,0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};
//数码管显示位库
u8 k1,k2;//记录用户码
void delay(u16 num){
u16 i,j;
for(i=1;i<=num;++i)
for(j=110;j>0;--j)
;
}
void display(u16 x,u16 y){//第x个数码管显示数字y(1、2...a、b...f)
place=where[x];
delay(2);
date=number[y];
delay(2);
date=0xff;
}
void initalize(void){//初始化函数
IRIN=1;//因为引导码一开始是0,所以置1
TCON=0x01;//设置外部中断方式
TMOD=0x10;//设置T1定时
EA=1;//总中断开启
EX0=1;//外部中断开启
}
延时代码
*不使用T1的中断void time_9000us(void)
{
TH1 = 0x0DC;//(0xff-9000)
TL1 = 0x0D8;
TR1 = 1;//开始计时
while(!TF1);//溢出标识
TF1=0;//手动重置
TR1=0;
}
void time_4500us(void)
{
TH1 = 0x0EE;
TL1 = 0x6C;
TR1 = 1;
while(!TF1);
TF1=0;
TR1=0;
}
void time_840us(void)
{
TH1 = 0x0FC;
TL1 = 0x0B8;
TR1 = 1;
while(!TF1);
TF1=0;
TR1=0;
}
八位数据读入
u8 get_code(void){
u8 n;
static temp=0;
for(n=0;n<8;n++){
while(!IRIN);//等到低电平的宽度结束
time_840us();
if(IRIN){
temp=(0x80|(temp>>1));// 将temp的其余位右移,第一位置1
while(IRIN);//准备读入下一位起始的低电平
}
else
temp=(0x00|(temp>>1));//同理
}
return temp;
}
外部中断
void interr(void) interrupt 0{
u8 a1,a2,n1,n2;//32位数据
EA=0;//关闭中断,防止干扰
time_9000us();
if(!IRIN){//若引导码错误则说明是干扰信号
EA=1;
return;
}
while(!IRIN);//以防万一的小设计
time_4500us();
if(IRIN){
EA=1;
return;
}
a1=get_code();//低八位用户码
a2=get_code();//高八位用户码
n1=get_code();//机器码
n2=get_code();//机器反码
if(n1!=~n2){//利用反码判断真伪
k1=14;
EA=1;
return;
}
k1=n2;//用于显示
k2=a2;//同上
EA=1;
}
无聊的土味main
void main(){
initalize();//初始化
while(1){
display(1,((k1&0xf0)>>4)&0x0f);//我随意找了一些位显示
display(2,(k1&0x0f));
}
}