实验目的:利用计数器0和外部中断0进行红外解码,将20键红外遥控器键码显示在两位数码管上
遇到问题:将hex文件下载到单片机按下按键数码管显示键码与遥控器键码不一致。例如按下按键“+”,数码管显示41,但是正确键码为40;又如按下遥控器播放按钮,数码管显示1C,标准键码为15.
请论坛各位前辈大佬帮我看看是哪里出错误了,谢谢
单片机程序代码如下:
- #include <REGX52.H>
- sbit IR_INPUT=P3^2; //红外接收引脚
- unsigned char ircode[4]; //红外代码接收缓冲区
- unsigned char NixeTable[]= //共阴数码管键码
- {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
- 0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
- /*软件生成的延时函数,延时xms*/
- void Delay(unsigned int xms) //@12.000MHz
- {
- unsigned char i, j;
- while(xms--)
- {
- i = 12;
- j = 169;
- do
- {
- while (--j);
- } while (--i);
- }
-
- }
- /*数码管显示函数,用两位数码管显示红外控制码*/
- void Nixie(unsigned char Location,Number)
- {
- switch(Location) //位选
- {
- case 1:
- P2_4=1;P2_3=1;P2_2=1;break;
- case 2:
- P2_4=1;P2_3=1;P2_2=0;break;
- }
- P0=NixeTable[Number]; //段选
- Delay(1); //这里没有延时数码管会很暗
- P0=0x00; //消隐
- }
- /*计数器0初始化函数*/
- void Timer0_Init(void)
- {
- TMOD &= 0xF0; //设置定时器模式
- TMOD |= 0x01; //设置定时器模式
- TL0 = 0; //设置定时初值
- TH0 = 0; //设置定时初值
- TF0 = 0; //清除TF0标志
- TR0 = 0; //定时器0不计时
- }
- /*外部中断0初始化函数*/
- void Int0_Init(void)
- {
- IT0=1; //设置INT0下降沿触发
- IE0=0; //清空外部中断0中断请求标志位
- EX0=1; //打开外部中断0
- EA=1; //打开总中断开关
- PX0=1; //设置外部中断优先级
- }
- /*获取高电平时间*/
- unsigned int GetHighTime()
- {
- TH0=0; //清零T0计数器初值
- TL0=0;
- TR0=1; //启动T0计数
- while(IR_INPUT) //红外输入引脚为1时循环检测等待,遇到下降沿时结束循环
- {
- if(TH0>=0x40) {break;} //当T0计数值大于18ms强制退出,避免程序死在这里
- }
- TR0=0; //停止计数
- return(TH0*256+TL0); //计数值合成16位整形数
- }
- /*获取低电平时间*/
- unsigned int GetLowTime()
- {
- TH0=0;
- TL0=0;
- TR0=1;
- while(!IR_INPUT)
- {
- if(TH0>=0x40) {break;}
- }
- TR0=0;
- return(TH0*256+TL0);
- }
- /*主函数*/
- void main()
- {
- Timer0_Init();
- Int0_Init();
- while(1)
- {
- Nixie(1,ircode[2]>>4);
- Nixie(2,ircode[2]&0x0F);
- }
- }
- /*外部中断服务子函数,执行红外接收和解码*/
- void Int0_Routine() interrupt 0
- {
- unsigned char i,j;
- unsigned char byt;
- unsigned int time;
-
- //接收并判定引导码的9ms低电平
- time=GetLowTime();
- if((time<7833)||(time>8755)) //时间判定范围为8.5ms~9.5ms,超出范围则为误码
- {
- IE0=0; //退出前清零INT0中断标志
- return;
- }
- //接收并判定引导码的4.5ms低电平
- time=GetHighTime();
- if((time<3686)||(time>4608)) //时间判定范围为4.0ms~5.0ms,超出范围则为误码
- {
- IE0=0; //退出前清零INT0中断标志
- return;
- }
-
- //接收并判定后续的4字节数据
- for(i=0;i<4;i++) //循环接收4个字节
- {
- for(j=0;j<8;j++) //循环接收判定每个字节的八位
- {
- time=GetLowTime();
- if((time<313)||(time>718)) //时间判定范围为340us~780us,超出范围则为误码
- {
- IE0=0;
- return;
- }
- time=GetHighTime();
- if((time>313)&&(time<718)) //时间判定范围为340us~780us,在此范围内说明该位为0
- {
- byt>>=1; //低位在先,数据右移,高位置零
- }
- else if((time>1345)&&(time<1751)) //时间判定范围为1460us~1900us,在此范围内说明该位为1
- {
- byt>>1; //低位在先,数据右移
- byt|=0x80; //高位置1
- }
- else
- {
- IE0=0;
- return;
- }
- }
- ircode[i]=byt; //接收完一个字节后保存到数组
- }
- IE0=0; //清零INT0标志
- }
复制代码
程序编译后有一个警告:
|