学习红外遥控实验的时候的疑问

2019-07-21 00:45发布

在学习红外遥控实验的时候遇到了下面问题,发给原子哥,几天了也没回复我,可能比较忙吧!
再一次在这发帖求助,希望大家一起学习交流!
我用
探索者F4的红外遥控带代码,在主循环里扫描
if(Remote_Scan()) 
{
  GPIO_SetBits(GPIOF,GPIO_Pin_8);//BEEP
  delay_ms(20);
}
else  
   GPIO_ResetBits(GPIOF,GPIO_Pin_8);
也就是如果有按键动作蜂鸣器就会短暂响下,可是我结果我按下按键蜂鸣器就长鸣一下,如果按住按键不放就会一直响。
我仔细分析了代码
if(RmtSta&0x80)//上次有数据被接收到了

    RmtSta&=~0X10; //取消上升沿已经被捕获标记
    if((RmtSta&0X0F)==0X00)RmtSta|=1<<6;//标记已经完成一次按键的键值信息采集
    if((RmtSta&0X0F)<14)RmtSta++;
else
{
    RmtSta&=~(1<<7);//清空引导标识
    RmtSta&=0XF0; //清空计数器 
}   

发现如果没有连发码,在过140ms之后就认为完成一次完整的按键接收了,可是 RmtSta&=~(1<<7);//清空引导标识  
就不立即响应了,必须要等下次定时器溢出进入 if(RmtSta&0x80)里,进行按键信息采集完成标记,以让主循环响应,可是,之前超时的时候已经清空了引导标识,所有必须等到下一次按键开始捕获的时候才让执行上一次的动作。
如果收到连发码就会立即响应连发码,想问下我的分析对不对?我很纠结这。
按键完成一次信息收集最起码要100ms以上,收到完成标记之后,就算主循环扫描立即响应,打开蜂鸣器发声并延时20ms,在这20ms中如果又发生按键或者在接受连发码,接收连发码或者按键的时间至少100ms,也就是说假设是主循环很快开始也至少会是响20ms后停80ms,然后再响20ms.这与结果不服,我在Remote_Scan(void)里添加printf()打印按键的结果,波特率设置460800,每次按键总是打印好几次按键值。
想问下原子哥分析下告诉我,我自己在基础上修改,之前每次捕获上升沿就给定时器置零,我绝对如果定时还用在其他地方这样做不好,就取出当前值,在捕获下降沿是在做了防溢出处理值将得到值减去之前的值,得到脉冲时间。我的结果和我分析的相符,可是我却不知是我的这样结果正确还是你的是正确的。请原子个分析下,附上代码,初始化都和参数都一样的,就中断处理有些差异
u8 REMOTE_STA;
//u8 REMOTE_RES;
u16 REMOTE_CNT;
u32 REMOTE_VAL;
void TIM1_CC_IRQHandler(void)
{
if(TIM_GetITStatus(TIM1,TIM_IT_CC1)!=RESET)
{
if(RDATA)
{
REMOTE_CNT=TIM_GetCounter(TIM1);
TIM_OC1PolarityConfig(TIM1,TIM_ICPolarity_Falling);
REMOTE_STA|=0x40;
}
else

if((REMOTE_STA&0x1f)<3)//大于20ms以上不用计算
REMOTE_CNT=TIM_GetCapture1(TIM1)+((REMOTE_STA&0x1f)*10000)-REMOTE_CNT;
else REMOTE_CNT=0;
TIM_OC1PolarityConfig(TIM1,TIM_ICPolarity_Rising);
if(REMOTE_STA&0x40)//捕获完上升沿,完成下降捕获
{
if(REMOTE_STA&0x20)//收到引导码
{
if(300<REMOTE_CNT&&REMOTE_CNT<800)//560us
{
  REMOTE_VAL<<=1;
  REMOTE_VAL|=0;
}
else if(1400<REMOTE_CNT&&REMOTE_CNT<1800)//1680us
{
REMOTE_VAL<<=1;
REMOTE_VAL|=1;
}
else if(2200<REMOTE_CNT&&REMOTE_CNT<2700)//2500
{
//REMOTE_RES++;
REMOTE_STA|=0x80;

}
else if(4200<REMOTE_CNT&&REMOTE_CNT<4700)

  REMOTE_STA|=0x20; 
 // REMOTE_RES=0;
}

REMOTE_STA&=0xA0;//清除捕获上升沿标志及计数 
}
TIM_ClearITPendingBit(TIM1,TIM_IT_CC1);
}
}
void TIM1_UP_TIM10_IRQHandler(void)
{
if(TIM_GetITStatus(TIM1,TIM_IT_Update)!=RESET)
{
if(REMOTE_STA&0x40)
REMOTE_STA++;
if(REMOTE_STA&0x20)
{
if(14<(REMOTE_STA&0x1f))//当捕获的时间大于140ms认为已经没有按键动作了
{
REMOTE_STA=0x80;//标志接收完成
REMOTE_CNT=0;//清空前一次定时器的起始值
}

TIM_ClearITPendingBit(TIM1,TIM_IT_Update);
}
}
u8 Remote_Scan(void)
{
u8 t1=0,t2=0;
u8 sta=0;
if(REMOTE_STA&0x80)

t1=REMOTE_VAL>>24;
t2=REMOTE_VAL>>16;
if((u8)~t1==t2)
{
t1=REMOTE_VAL>>8;
t2=(unsigned char)REMOTE_VAL;
if(t1==(u8)~t2)
{
sta=t1;
printf("键值:%d ",sta);
}
}
REMOTE_STA&=0x7f;
}
return sta;
}
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
5条回答
爱我别走
2019-07-21 06:38
回复【2楼】lycreturn:
---------------------------------
看了你的解答我明白了,假设没有收到连发码,会在收到数据之后的10ms标记采样完成,当主函数扫描到之后进入20ms的延时,蜂鸣器会响,20ms延时过后,新的扫描到来,由于之前已经清楚收到数据标识位,主循环会关掉蜂鸣器,而此时中断在每隔10ms溢出进入中断,直到130ms过后,也就是说没有连发码,蜂鸣器会响20多ms,可是为啥会响的不止是20ms,如果收到连发码也是130ms左右会标记数据采集完成一次,而20ms,对于130ms来说,也就是说即使一直受到连发码也会想20ms,然后停80ms,之后又到底连发码标志数据接收完成,虽然在听的这80ms中蜂鸣器是不在响,中断也会进入退出,知道标记数据接收完成,蜂鸣器响。虽然明白了你们写的代码的原理,也觉得这样处理很好,可是为什么我的实验结果不是响20ms,停80ms,再停再响,时间可能会有些偏差,但至少响的不是20ms,而是20ms以上,以至于听不出中间有停顿过,我的代码如果一直是的连发码会每110ms标记一次,期间响20ms,停90ms,感觉你们的代码标记的速度比我的快,我会在分析下看具体的时间差异。

一周热门 更多>