51单片机红外解码C程序
发布网友
发布时间:2022-05-09 14:50
我来回答
共4个回答
热心网友
时间:2024-02-02 18:41
单片机采用外部中断P3.3管脚和红外接收头的信号线相连,中断方式为边沿触发方式。并用定时器0计算中断的间隔时间,来区分前导码、二进制的“1”、“0”码。并将8位操作码提取出来在数码管上显示。
// 解码值在Im[2]中,当IrOK=1时解码有效。
/* 51单片机红外遥控解码程序 */
//用遥控器对准红外接收头,按下遥控器按键,在数码管前两位上就会显示对应按键的编码
#include <reg52.h>
#define uchar unsigned char
sbit la=P2^6;
sbit wela=P2^7;
uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,
0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
uchar f;
#define Imax 14000 //此处为晶振为11.0592时的取值,
#define Imin 8000 //如用其它频率的晶振时,
#define Inum1 1450 //要改变相应的取值。
#define Inum2 700
#define Inum3 3000
unsigned char Im[4]={0x00,0x00,0x00,0x00};
uchar show[2]={0,0};
unsigned long m,Tc;
unsigned char IrOK;
void delay(uchar i)
{
uchar j,k;
for(j=i;j>0;j--)
for(k=125;k>0;k--);
}
void display()
{
la=0;
P0=table[show[0]];
la=1;
la=0;
wela=0;
P0=0xfe;
wela=1;
wela=0;
delay(5);
P0=table[show[1]];
la=1;
la=0;
P0=0xfd;
wela=1;
wela=0;
delay(5);
} //外部中断解码程序
void intersvr1(void) interrupt 2 using 1
{
Tc=TH0*256+TL0; //提取中断时间间隔时长
TH0=0;
TL0=0; //定时中断重新置零
if((Tc>Imin)&&(Tc<Imax))
{
m=0;
f=1;
return;
} //找到启始码
if(f==1)
{
if(Tc>Inum1&&Tc<Inum3)
{
Im[m/8]=Im[m/8]>>1|0x80; m++;
}
if(Tc>Inum2&&Tc<Inum1)
{
Im[m/8]=Im[m/8]>>1; m++; //取码
}
if(m==32)
{
m=0;
f=0;
if(Im[2]==~Im[3])
{
IrOK=1;
}
else IrOK=0; //取码完成后判断读码是否正确
}
//准备读下一码
}
}
/*演示主程序*/
void main(void)
{
unsigned int a;
m=0;
f=0;
EA=1;
IT1=1;EX1=1;
TMOD=0x11;
TH0=0;TL0=0;
TR0=1;//ET0=1;
while(1)
{
if(IrOK==1)
{
show[1]=Im[2] & 0x0F; //取键码的低四位
show[0]=Im[2] >> 4;
IrOK=0;
}
for(a=100;a>0;a--)
{
display();
}
}
}
解码程序这个就能实现
热心网友
时间:2024-02-02 18:42
关键程序如下:
//外部中断为边沿触发,接低电平进入
//1838将外部的高电平转为低电平
//NEC的码为1时,初次进入外部中断,启动定时器,下一次进入外部中断时通过定时器数值判断
//上一脉冲的周期,从而区分引导码或0码1码......
void intersvr1(void) interrupt 2 using 1 //外部中断
{
Tc=TH0*256+TL0;
TH0=0;
TL0=0; //定时中断重新置零
if((Tc>Imin)&&(Tc<Imax)) //8-14毫秒对应引导码13.5毫秒(9高4.5低)
{
m=0;
f=1;
return;
//在函数中,如果碰到return 语句,那么程序就会返回调用该函数的下一条语句执行,也就是说跳出函数的执行,回到原来的地方继续执行下去。
}
if(f==1)
{
if(Tc>Inum1&&Tc<Inum3) //1.45-3.0毫秒对应NEC码的1.125(0.565;0.565)毫秒的1
{
Im[m/8]=Im[m/8]>>1|0x80; m++; //取一位码,共32个位,放在数组Im[4]的4字节中
}
if(Tc>Inum2&&Tc<Inum1) //0.7-1.45毫秒对应NEC码的1.125(0.565;1.685)毫秒的0
{
Im[m/8]=Im[m/8]>>1; m++; //取一位码,共32个位,放在数组Im[4]的4字节中
}
if(m==32)
{
m=0;
f=0;
if(Im[2]==~Im[3]) //Im[2]为8位数据码,Im[3]为8位数据码的反码
{
IrOK=1;
}
else IrOK=0; //取码完成后判断读码是否正确
}
}
}
想要完整的demo留邮箱
热心网友
时间:2024-02-02 18:42
哈哈,这个我最近刚写出来,遥控器和你那个一样,1~8键控制8个IO口,按下0键关闭所有IO口,电源键可接继电器控制总开关,程序改写简单,家里的遥控器均可利用,多种工作方式,加qq:657054041
热心网友
时间:2024-02-02 18:43
给你个我做项目用的42位电视剧遥控器解码源代码 参考程序:
/**************************************************
*
* 51单片机精简遥控解码实验程序
*
*实验功能 :数码管显示遥控器键码
*
* 遥控器是42位电视遥控器
*
* 数码管上电默认显示【 E--000 】
***************************************************/
#include "REG52.H"
sbit delu = P2^6; //数码管段选sbit wela = P2^7; //数码管位选
sbit IR_dat = P3^2; //遥控数据口sbit Bee_tp = P2^3;
unsigned int IR_boke;
unsigned char IR_temp;
unsigned char IR_vnum;
unsigned char IR_data[4];
unsigned char code value_tab[] =
{
0x3F,
0x06,
0x5B,
0x4F,
0x66,
0x6D,
0x7D,
0x07,
0x7F,
0x6F
}; //0-9
#define IR_200 (200 * 110592 / 120000)
#define IR_800 (800 * 110592 / 120000)
#define IR_1120 (1120* 110592 / 120000)
#define IR_2000 (2000* 110592 / 120000)
#define IR_8500 (8500* 110592 / 120000)
#define IR_9500 (9500* 110592 / 120000)
#define IR_4000 (4000* 110592 / 120000)
#define IR_4500 (4500* 110592 / 120000)
/*
** 外部中断初始化子函数
**/
void INTO_Init(void)
{
TMOD = 0x01;
EA = 1;
EX0 = 1;
IT0 = 1;
}
/*
** 红外下升沿低电平延时时间计算子函数
**/
unsigned int IR_Interrupt_LSB(void)
{
TL0 = 0;
TH0 = 0;
TR0 = 1;
while(!IR_dat && (TH0 & 0x80) == 0);
TR0 = 0;
return(TH0 * 256 + TL0);
}
/*
** 红外上升沿高电平延时时间计算子函数
**/
unsigned int IR_Interrupt_MSB(void)
{
TL0 = 0;
TH0 = 0;
TR0 = 1;
while(IR_dat && (TH0 & 0x80) == 0);
TR0 = 0;
return(TH0 * 256 + TL0);
}
/*
** 软件延时1ms子函数
**/
void Delay_1ms(unsigned int time)
{
unsigned int x, y;
for(x = time; x > 0; x--)
for(y = 120; y > 0; y--);
}
void Buf_beepCmd(void)
{
unsigned char i;
for(i = 0; i < 100; i++)
{
Bee_tp = 0;
}
Delay_1ms(20);
Bee_tp = 1;
}
/*
** 数码管显示遥控器按键值子函数
**/
void Shumg_Display_dataCmd(unsigned char value_)
{
delu = 1; /*************** E ***************/
P0 = 0x79;
delu = 0;
P0 = 0xFF;
wela = 1;
P0 = 0xFE;
wela = 0;
Delay_1ms(2);
delu = 1; /*************** - ***************/
P0 = 0x40;
delu = 0;
P0 = 0xFF;
wela = 1;
P0 = 0xFD;
wela = 0;
Delay_1ms(2);
delu = 1; /*************** - ***************/
P0 = 0x40;
delu = 0;
P0 = 0xFF;
wela = 1;
P0 = 0xFB;
wela = 0;
Delay_1ms(2);
delu = 1;
P0 = value_tab[value_ / 100]; /************** 百位 *************/
delu = 0;
P0 = 0xFF;
wela = 1;
P0 = 0xF7;
wela = 0;
Delay_1ms(2);
delu = 1;
P0 = value_tab[value_ % 100 / 10]; /************** 十位 *************/
delu = 0;
P0 = 0xFF;
wela = 1;
P0 = 0xEF;
wela = 0;
Delay_1ms(2);
delu = 1;
P0 = value_tab[value_ % 10]; /************** 个位 *************/
delu = 0;
P0 = 0xFF;
wela = 1;
P0 = 0xDF;
wela = 0;
Delay_1ms(2);
}
/*
** 函数主体
**/
int main(void)
{
INTO_Init();
while(1)
{
Shumg_Display_dataCmd(IR_data[2]);
}
}
/*
** 外部中断服务程序
**/
void INTO_timero()interrupt 0
{
unsigned char i;
unsigned char temp;
IR_dat = 1;
IR_boke = IR_Interrupt_LSB();
if((IR_boke < IR_8500) || (IR_boke > IR_9500)) /*******判断低电平引导码9ms********/
{
return;
}
IR_boke = IR_Interrupt_MSB();
if((IR_boke < IR_4000) || (IR_boke > IR_4500)) /******判断高电平引导码4.5ms******/
{
return;
}
IR_vnum = 3;
for(i = 1; i < 43; i++)
{ /******电视遥控器是42位编码*******/
IR_temp >>= 1;
IR_boke = IR_Interrupt_LSB();
if((IR_boke < IR_200) || (IR_boke > IR_800)) /********判断低电平0.56ms*********/
{
return;
}
IR_boke = IR_Interrupt_MSB();
if((IR_boke < IR_200) || (IR_boke > IR_2000)) /********判断高电平1.68ms********/
{
return;
}
if(IR_boke > IR_1120) /*********判断键码1还是0**********/
{
IR_temp |= 0x80;
}
if(i == 13 || i == 26 || i == 34 || i == 42)
{
IR_vnum++;
if(IR_vnum == 4)
{
IR_vnum = 0;
}
IR_data[IR_vnum] = IR_temp;
IR_temp = 0;
}
}
if((IR_data[0]) != (~ IR_data[1]) || (IR_data[2]) != (~ IR_data[3])) //判断用户吗和按键码
{
return;
}
temp = IR_data[2] / 16;
IR_data[2] = IR_data[2] % 16;
IR_data[2] = IR_data[2] + temp * 10; //得到的十六进制键码头转换成十进制数
Buf_beepCmd();
}