📄 红外接收程序.c
字号:
/*********************************************
12Mhz 晶振
**本程序适合32位码遥控器,即16位系统码,16位
数据码,如:57L5,55K2,54B4,KD-29,55K8,5Z26A,
等型号的遥控器,转贴请保持代码的完整性
当有按键时就会产一个9.12ms低电平和4.5ms高电平的起始码,紧接着是16位系统码,
此系统码能区别不同的电器设备,防止不同机种遥控码互相干扰,接下来是8位数据码
和8位数据反码,间隔23ms的高电平后,再发一个与启始码完全一样的结束码 。
以脉宽为0.565ms、间隔0.56ms、周期为1.125ms的组合表示二进制的“0”;
以脉宽为0.565ms、间隔1.685ms、周期为2.25ms的组合表示二进制的“1”
定时器约定采用方式2自动重载形式。最小定时周期50us,为一个计数单位。
因此:
引导信号:13.5ms相当于270个单位
0: 为22.6个
1: 为45.2个
为了增强抗干扰能力,可以用一个范围来确定某个信号
有效信号一定超过半个脉冲周期即11.3个单位
所以
合法信号范围 【10,280】
引导信号范围 【200,280】
0 信号范围 【10,30】
1 信号范围 【30,60】
利用HS0038B解码。1脚out接20K上拉电阻,2脚接地,3脚串联100欧姆电阻接VCC,3脚对地接4.7us电容。
*********************************************/
#include "reg51.h"
#define uint unsigned int
#define uchar unsigned char
sbit IR=P3^3;//红外端口
sbit lock=P3^2;
unsigned char code zxm[]={0x03,0xf3,0x26,0x62,0xd2,0x4a,0x0a,0xe3,0x02,0x42};
uchar num,n;
uchar key_code=0;//遥控键值
uchar new_code=0;//有无新按键
uchar buf[4];//暂存地址码、 地址反码 、用户码 、用户反码
uchar key_bit_count=0;//键编码脉冲计数
uint count=0;//定时中断次数计数
uint buf_count=0;//定时中断计数暂存
uchar common_code_count=0;//前导码脉冲计数
bit IR_status=0;//脉冲接收器所处的状态,0:无信号,1:系统码接收区
char cnt;
void delay_10us(unsigned char y)///延时子程序10us
{
unsigned char x;
for(x=y;x>0;x--);
}
void init(void)/////初始化
{
IR=1; //红外端口写1
EA=1; //开总中断
TMOD=0x02; //定时器0,模式2,8位自动装载模式
TH0=0Xce; //定时50us
TL0=0Xce;
IT1=1; //INT1下降沿触发
ET0=1; //允许定时器中断
EX1=1; //允许外部中断
}
/***********************************************
定时器中断
***********************************************/
void time0() interrupt 1///定时器中断
{
count++;//定时器中断次数累加
}
/**********************************************
外部中断,红外解码程序
**********************************************/
void int1() interrupt 2///外部中断
{
TR0=1;//开定时器中断
if(count>12&&count<280)//信息持续时间超过最小脉宽0.565ms且不大于引导信号9+4.5=13.5ms 如果信号合法,则放入buf_count,count清0,对下一个脉冲信号计时
{
buf_count=count;
count=0;
}
delay_10us(10);//延时100us以消除下降沿跳变抖动
if(IR==0)//INT1引脚稳定为低电平,则表法确实是信号,count重新计时,因上面延时了50us,故要补偿1次TO中断
{
count=2;
}
if(buf_count>=0&&buf_count<280)//若收到的信号合法,则再进行信号分析
{
if(IR_status==0)//如果之前未收到引导码
{
if(buf_count>100&&buf_count<280)//判断是否引导码13.5ms
{
IR_status=1;//系统标记
buf_count=0;//
n=0;//buf的角标从0开始
}
}
else if(IR_status==1)///收到引导码
{
if(key_bit_count<32)//收到数据少于32位,则将收到的数据写入buf[]
{
if(buf_count>30&&buf_count<60)
{
buf_count=0;
buf[n]>>=1;
buf[n]|=0x80;//收到1
key_bit_count++;//数据脉冲累加
}
else if(buf_count>10&&buf_count<30)//收到0
{
buf_count=0;
buf[n]>>=1;//收到0
key_bit_count++;
}
if(key_bit_count==32)//若收完8位数据则做以下处理
{
IR_status=0;//接收状态返回到空闲
key_bit_count=0;
buf_count=0;
TR0=0;
EX1=0; //停止外中断
new_code=1;
}
n=key_bit_count/8;
}
}
}
}
void disp(unsigned long n)
{
unsigned char i=0,t[6]={0};
while(n)
{
t[i++]=n%10;
n/=10;
if(i>5)
break;
}
for(i=0;i<6;i++)
{
SBUF=zxm[t[i]];
while(!TI);
TI=0;
}
lock=0;
lock=1;
}
/*************************************
主程序
*************************************/
void main()
{
init(); ///初始化
disp(0);
while(1)
{
if(new_code)//判断是否有新按键,如果有则执行下面程序,没有则一直循环
{
new_code=0;
//buf[0] 地址码 buf[1] 地址反码 buf[2] 用户码 buf[3] 用户反码
if(buf[0]==~buf[1] && buf[2]==~buf[3])
{
if(buf[0]==56)
{
disp(buf[2]);
}
}
EX1=1; //重新开启外中断
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -