STC89C52单片机红外遥控器解码
扫描二维码
随时随地手机看文章
实现功能: 按实验板所佩带的红外遥控器上面的数字键,把所按的数字显示在实
验板上的数码管上,一定注意要跟红外探测头的距离不要太远,而且
程序里只编写了遥控器上的数字键的部分
实验板型号:KBL-XYD-C52
实验名称: 红外控制数码管的显示
#include
#define uchar unsigned char
#define uint unsigned int
sbit IR = P3^3; //红外接收器数据线
sbit Duan=P2^6; //定义数码管的段选使能端
sbit Wei =P2^7; //定义数码管的位选使能端
#define Digital_tube_Wei_Enable Wei=1; //开启控制数码管的位选使能端
#define Digital_tube_Wei_Disable Wei=0; //关闭控制数码管的位选使能端
#define Digital_tube_Duan_Enable Duan=1; //开启控制数码管的段选使能端
#define Digital_tube_Duan_Disable Duan=0; //关闭控制数码管的段选使能端
#define Digital_tube_Duan P0 //定义数码管数据端口
uchar cIRReceiveData[7];
uchar code Dis_table[]= //将BCD码转换成数码管扫描码的数组
{0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x40,0x00};
函数名称:毫秒延时函数
函数功能:实现毫秒级的延时
参数介绍:Delay_MS: 定义需要延时的毫秒的数值
iNumber: 记录Delay_MS的数值,以for语句实现所要求的延时
iValue: 要延时毫秒所要进行的循环数值,本数值为实际测得
返回值: 无
注意事项:本实验是在所用晶振为12M的前提下实现的毫秒延时,本函数是通过循环的形
式完成,所以如果改变了晶振的频率,请做相应的改变
void DelayMs(uint Delay_MS)
{
uint iNumber,iValue;
for(iNumber=0;iNumber
{
iValue=107; //107这个数值是通过测定而得
while(iValue--);
}
}
函数名称:Delay
函数功能:延时0.14毫秒,主要是用于红外解码
参数介绍:cDelay:延时0.14ms的次数
返回值: 无
注意事项:无
void Delay(unsigned char cDelay) //x*0.14MS
{
unsigned char cNumber;
while(cDelay--)
{
for (cNumber=0;cNumber<13;cNumber++) {}
}
}
函数名称:One_DigitalTube_display
函数功能:把数字显示在数码管上,因为实验板上用了锁存器573控制数码管
参数介绍:无
返回值: 无
注意事项:无
void One_DigitalTube_display(unsigned char uData)
{
Digital_tube_Duan_Enable; //使能数码管的段选
Digital_tube_Duan=Dis_table[uData];//输入所要显示的数值
Digital_tube_Duan_Disable; //关闭数码管的段选
DelayMs(1); //调整时序,以实现稳定显示
}
函数名称:Init_INT1
函数功能:配置外部中断1,让其为下降沿触发,同时打开全局中断
参数介绍:无
返回值: 无
注意事项:无
void Init_INT1()
{
IT1=1; //外部中断1,为下降沿触发
EX1=1; //允许外部中断1中断
EA=1; //CPU开放中断
}
函数名称:main
函数功能:初始化外部中断1,让实验板上所用数码管的公共端接为低电平,然后进入
while(1)的循环,等待中断的发生
参数介绍:无
返回值: 无
注意事项:实验板上所用的数码管为共阴极数码管
void main()
{
Init_INT1(); //初始化外部中断1
IR=1; //I/O口初始化
Digital_tube_Wei_Enable; //打开控制数码管锁存器的使能端
P0=0x00; //给所有数码管的公共端低电平
Digital_tube_Wei_Disable;//关闭控制数码管锁存器的使能端
while(1);
}
函数名称:IR_Routine
函数功能:对红外接收头接收到的红外信号进行解码,解码后,把遥控器上的数字显示
在数码管上
参数介绍:无
返回值: 无
注意事项:具体的协议,请看光盘里所带的名为“红外控制”的数据手册
void IR_Routine() interrupt 2
{
unsigned char cNumber1,cNumber2,cCount=0;
EX1 = 0; //关闭中断
Delay(15);
if (IR==1) //然后再检测红线接收脚是有数据招收,有继续,没有则退出
{
EX1 =1; //打开中断
return; //跳出去
}
while (!IR) //确认IR信号出现
{ //等IR变为高电平,跳过9ms的前导低电平信号。
Delay(1);
}
for (cNumber1=0;cNumber1<4;cNumber1++) //收集四组数据,前两组为地址码,仅
{ //仅接着是两个命令码,这是NEC公司所定义的协议里规定的
for (cNumber2=0;cNumber2<8;cNumber2++)//每组数据有8位
{
while (IR) //等 IR 变为低电平,跳过4.5ms的前导高电平信号。
{
Delay(1);
}
while (!IR) //等 IR 变为高电平
{
Delay(1);
}
while (IR) //计算IR高电平时长
{
Delay(1);
cCount++;
if (cCount>=30)
{
EX1=1;
return;
} //太长了就自动推出中断服务程序
} //高电平计数完毕
cIRReceiveData[cNumber1]=cIRReceiveData[cNumber1] >> 1;//数据最高位补“0”
if(cCount>=8) //协议里定义‘1’的电平为2.25ms,因为Delay(1)延时为0.14ms
{ //加上其他指令执行时的延时,所以大于等于8时,为高电平
cIRReceiveData[cNumber1] = cIRReceiveData[cNumber1] | 0x80;
} //数据最高位补“1”
cCount=0;
}//end for k
}//end for j
if(cIRReceiveData[2]!=~cIRReceiveData[3])//判断接收到指令是不是正确,协议里规定
{ //第一次发指令和第二次发的正好的按位取反的,以此保证接收数据的可靠性
EX1=1;
return;
}
switch(cIRReceiveData[2]) //把解码得到的数据转换成实验板上能够显示的数字
{
case 0x16:
One_DigitalTube_display(0); break;
case 0x0c:
One_DigitalTube_display(1); break;
case 0x18:
One_DigitalTube_display(2); break;
case 0x5e:
One_DigitalTube_display(3); break;
case 0x08:
One_DigitalTube_display(4); break;
case 0x1c:
One_DigitalTube_display(5); break;
case 0x5a:
One_DigitalTube_display(6); break;
case 0x42:
One_DigitalTube_display(7); break;
case 0x52:
One_DigitalTube_display(8); break;
case 0x4a:
One_DigitalTube_display(9); break;
}
EX1 = 1; //打开中断,解码完成,以进行下次解码
}