【已解决】51简单的红外程序,出了邪门了,大家都来帮帮...
本帖最后由 512826028 于 2012-4-26 23:59 编辑我是今天买了一个红外的遥控器,写了一个红外接收的程序。一开始,解码都正常。后来,我在中断中添加一个加一,和减一的代码。但是,结果出人意料,程序会自动运行两边。本意是这样的,按下一个键,表示加一,计数增加一。程序放在中断中进行,进入中断就关闭了EA,应该不会再自动重复进入中断吧?我先给大家上中断部分的程序。
/************************中断0解码服务子程序**********************/
void int0(void) interrupt 0
{
EA=0;
irdalow = IRDA_JIEMA();//得到解码的数据 这个数据只包括数据码!
Delay_ms(255);//
Delay_ms(255);//
if(irdalow == 0x0df2) //如果按下的向上,就减一
{
Delay_ms(200);
if(SCREEN_MUSIC>0)
SCREEN_MUSIC = SCREEN_MUSIC-1; //向上翻
}
if(irdalow == 0x0ef1)//如果按下的是向下,就加一
{
Delay_ms(200);
SCREEN_MUSIC = SCREEN_MUSIC+1; //向下翻
if(SCREEN_MUSIC>7)//不可以超出7
SCREEN_MUSIC=7;
LCD12864S_WCOM(0x86);//这句和下句是在LCD的指定位置显示出SCREEN_MUSIC的值。+0x30是转换成字符。
LCD12864S_WDATA(0x30+SCREEN_MUSIC);
}
Delay_ms(255);//
Delay_ms(255);//
SCREEN_DISP();//刷新显示函数
SCREEN_GUANGBIAO(SCREEN_MUSIC-SCREEN_ROW);//这个是控制光标位置的。移动光标。
Delay_ms(255);//
Delay_ms(255);//
EA=1;
}
我在说一下问题。这个中断程序就是这样。运行起来之后,我按下向下键,就会自动增加2,而不是一。为了能看出变化,我添加了LCD显示SCREEN_MUSIC值的语句,同时,在中断的多个地方,做了大量的延时处理,最后看出了程序执行的过程。
程序是直接运行了两边!按下“向下键”之后,在LCD上可以看到显示的SCREEN_MUSIC从0显示为1,然后移动一下光标。然后,LCD上又看到SCREEN_MUSIC的值变为2,又移动了一次光标。
这样,按下一次,程序就是增加的二!而且是从头到尾的执行了两遍!!
我真的不知道这个事什么问题导致的。希望大家都能帮帮。。。。。。。。。。。谢谢啦! 现在的感觉就是,按下一次之后,好像就是产生了两次中断。不知道怎么解决这个问题。延时再长,但是,都是运行两边。很是郁闷。。。{:dizzy:} 用的什么格式遥控码,“一开始,解码都正常”,你是怎么知道正常的?
向上翻/向下翻的动作不要放在中断代码里面 本帖最后由 HeP028 于 2012-4-26 22:24 编辑
那你把中断最后的EA = 1先去掉测试嘛!先干一次看对不对塞!
另外把你红外读取的函数展览出来塞!指不定问题出那里面呢! sf49ers 发表于 2012-4-26 21:27 static/image/common/back.gif
用的什么格式遥控码,“一开始,解码都正常”,你是怎么知道正常的?
这个之前是先用LCD显示出所有的按键的用户码,做了一个表格。然后才进行的这一步。 HeP028 发表于 2012-4-26 22:23 static/image/common/back.gif
那你把中断最后的EA = 1先去掉测试嘛!先干一次看对不对塞!
另外把你红外读取的函数展览出来塞!指不定问 ...
这个是拿的别人的程序改的。这个是源代码。
/************************中断0解码服务子程序**********************/
void int0(void) interrupt 0
{
EA=0;
for(k=0;k<10;k++)
{
Delay0_9ms();
if (IRDATA==1) //如果0.9ms后IRDATA=1,说明不是引导码
{k=10;break;}
else if(k==9) //如果持续了10×0.9ms=9ms的低电平,说明是引导码
{
while(IRDATA==0);
Delay4_5ms(); //跳过持续4.5ms的高电平
for(i=0;i<4;i++) //分别读取4个字节
{for(j=1;j<=8;j++) //每个字节8个bit的判断
{
while(IRDATA==0); //等待上升沿
Delay0_9ms(); //从上升沿那一时刻开始延时0.9ms,再判断IRDATA
if(IRDATA==1) //如果IRDATA是"1",则向右移入一位"1"
{
Delay1ms();
CodeTemp=CodeTemp|0x80;
if(j<8) CodeTemp=CodeTemp>>1;
}
else if(j<8)
CodeTemp=CodeTemp>>1;//如果IRDATA是"0",则向右移一位,自动补"0"
}
hongwaicode=CodeTemp;
CodeTemp=0;
}
}
}
recodehigh=hongwaicode<<8|hongwaicode;
recodelow=hongwaicode<<8|hongwaicode;
recode=recodehigh;
recode=recode<<16;
recode=recode|recodelow;
//显示出读出的数据
// printf("%#X\n",hongwaicode);
// printf("%#X\n",recodehigh);
// printf("%#X\n",recodelow);
// printf("%#X\n",recode);
//LCD12864S_WSTR(1,0,hongwaicode);
IRDA_DISP();
EA=1;
}
再附上 全部的延时函数:
/**************************延时50us子程序**********************/
void Delay_50us(INT16U t)
{
INT8U j;
for(;t>0;t--)
for(j=20;j>0;j--);
}
/**************************延时0.9ms子程序**********************/
void Delay0_9ms(void)
{INT8U j,k;
for(j=18;j>0;j--)
for(k=20;k>0;k--) ;
}
/***************************延时1ms子程序**********************/
void Delay1ms(void)
{INT8U i,j;
for(i=2;i>0;i--)
for(j=240;j>0;j--) ;
}
/***************************延时4.5ms子程序**********************/
void Delay4_5ms(void)
{INT8U i,j;
for(i=10;i>0;i--)
for(j=230;j>0;j--) ;
}
说明:此程序来源于 长沙太阳人”杯红外波形显示单片机设计大赛 制作人:小杨(杨再兴) <2010.7.5> lxa0 发表于 2012-4-26 22:12 static/image/common/back.gif
向上翻/向下翻的动作不要放在中断代码里面
谢谢大哥。这个是正解。
我设定了部分全局变量
在中断中,只是置位对应的变量,然后,在主程序的while循环里判断就可以解决这个问题了。呵呵
中断程序如下:
/************************中断0解码服务子程序**********************/
void int0(void) interrupt 0
{
EA=0;
irdalow = IRDA_JIEMA();//得到解码的数据 这个数据只包括数据码!
Delay_ms(20);
//sprintf(yonghuma,"%04X",irdalow);
//强制格式化,把数据转为4位的16进制数据。
if(irdalow == 0x0af5)
; //你按下了音量+
if(irdalow == 0x09f6)
; //你按下了音量—
if(irdalow == 0x0df2) {KEY_UP = 1; } //上翻标志置一
if(irdalow == 0x0ef1) {KEY_DOWN = 1; } //下翻标志置一
if(irdalow == 0x02fd) {KEY_PLAY = 1; } //播放音乐标志置位
if(irdalow == 0x01fe) {KEY_MENU = 1; } //菜单键意味着返回键的意思。
if(irdalow == 0x09F6) {KEY_VOL_LOW = 1; } //VOL--
if(irdalow == 0x0AF5) {KEY_VOL_HIGH = 1; } //vol++
EA=1;
}
页:
[1]