[51单片机] 红外反射开关问题求助

[复制链接]
 楼主| li123ds 发表于 2019-9-26 12:05 | 显示全部楼层 |阅读模式

  1. //红外反射开关,接收头HS0038B,发射管用pnp三极管驱动
  2. //第一次上电,灯亮1秒后熄灭,
  3. //手挡一次开,再挡一次关,如此循环
  4. //实验板测试手挡一次开,再挡一次关 开关正常;
  5. //但是有一个问题,如果手一直挡在前面,LED会不停的亮--灭        -- 亮--灭
  6. //请大神们看下,怎样才能做到手挡在前面不移开,保持一种状态
  7. #include <reg52.h>
  8. #include <intrins.h>
  9. #define uchar unsigned char
  10. #define uint  unsigned int

  11. sbit ir=P2^4;    //红外发射
  12. sbit ir_in=P3^2; //红外接收
  13. sbit led=P1^1;        //

  14. uint cont,cont1;
  15. bit flag_key;         //按键按下标志
  16. bit key_lock=0;


  17. void delay(uint z)           //ms
  18. {
  19.         uint x,y;
  20.         for(x=z; x>0; x--)
  21.                 for(y=114; y>0; y--);
  22. }


  23. void fa_38k()          //38k 载波                         //接收头前面有滤光片,发射管要用黑色热缩套管套起来
  24. {                                  //不是很准,没有逻辑分析仪,搞不准,现在的反射距离在60厘米左右(发射管串100欧电阻)
  25.         ir=0;                  
  26.         _nop_();_nop_();_nop_();_nop_();
  27.         _nop_();_nop_();_nop_();_nop_();
  28.         
  29.         ir=1;
  30.         _nop_();_nop_();_nop_();_nop_();
  31.         _nop_();_nop_();_nop_();_nop_();
  32.         _nop_();_nop_();_nop_();_nop_();
  33.         _nop_();_nop_();_nop_();_nop_();
  34.         _nop_();//_nop_();
  35. }

  36. void main()
  37. {
  38.         TMOD |= 0X01;                          //T0定时器,模式1, 16位计数
  39.         TH0 = (65536-1000)/256;  //1ms初值 @12MHz晶振
  40.         TL0 = (65536-1000)%256;
  41.         

  42.         ET0=1;
  43.         TR0=1;
  44.         led=0;
  45.         delay(500);
  46.         led=1;
  47.         while(1)
  48.         {
  49.                 if(flag==0 )
  50.                 {
  51.                         fa_38k();  //发38K
  52.                 }
  53.                 else ir=1;           //停止发射
  54.            
  55.                




  56.         if(ir_in==0)          //手挡住
  57.         {
  58.                 flag_key=1;
  59.                 cont1++;
  60.                 key_lock=1;       
  61.         }
  62.         else flag_key=0; //手移开
  63.        
  64.         if(flag_key==1 && cont1==100)
  65.         {         
  66.                  ir=1;
  67.                  cont1=0;
  68.                  led = !led;
  69.                  delay(1000);

  70.         }

  71.        
  72.         if(ir_in==1) cont1=0;        //这句抗干扰很好,遥控器对着按,都没反应                       



  73.         }
  74. }

  75. void timer0() interrupt 1
  76. {
  77.         TH0 = (65536-1000)/256;  //重装1ms初值
  78.         TL0 = (65536-1000)%256;
  79.                 cont++;
  80.         if(cont==100)  
  81.         {        
  82.                 cont=0;
  83.                 flag=!flag;         //发100ms 38K,停100ms

  84.         }

  85. }
gx_huang 发表于 2019-9-26 12:25 | 显示全部楼层
系统结构需要重新整理一下,起码38KHz要准确可控。
至于手挡和LED亮灭,采取状态机更好,或者保存上次状态,状态改变瞬间才处理一次。
 楼主| li123ds 发表于 2019-9-26 12:30 | 显示全部楼层
gx_huang 发表于 2019-9-26 12:25
系统结构需要重新整理一下,起码38KHz要准确可控。
至于手挡和LED亮灭,采取状态机更好,或者保存上次状态 ...

现在感应是很灵敏的,就是状态锁不住
gx_huang 发表于 2019-9-26 12:37 | 显示全部楼层
你先把发射原理、接收原理搞清楚。
发射是间隔100ms发射一串红外载波,如果没有手挡住,接收端是间隔100ms的高低脉冲。
你只要理解上述原理,就会找到故障原因。
另外,红外接收器,也会误码,即使没有任何红外信号,也会时不时输出一些窄脉冲,这些都需要软件考虑的。
你这个软件根本不实用的。
18990194628 发表于 2019-9-26 13:53 | 显示全部楼层
新增一个变量,保存当前状态之前的状态
比如当前状态为flag
上一次状态为last_flag
判断当前状态和上一次状态的区别
if(上一次状态为没挡住 && 现在状态为挡住)
{
last_flag = flag
led亮
}
else if(上一次为挡住 && 现在为没挡住)
{
last_flag = flag
led灭
}

评论

等会试一试  发表于 2019-9-26 15:18
 楼主| li123ds 发表于 2019-9-26 14:58 | 显示全部楼层
本帖最后由 li123ds 于 2019-9-26 15:16 编辑
18990194628 发表于 2019-9-26 13:53
新增一个变量,保存当前状态之前的状态
比如当前状态为flag
上一次状态为last_flag

//红外反射开关,接收头HS0038B,发射管用pnp三极管驱动
//第一次上电,灯亮0.5秒后熄灭,
//挡一下开,再挡关,如此循环
//实验板测试正常
//手挡在前面,不再来回开关了//隔着5mm厚的玻璃也能感应,抗干扰也可以,用遥控器对着接收头不停的按,都不会有误动作
#include <reg52.h>
#include <intrins.h>
#define uchar unsigned char
#define uint  unsigned int

sbit ir=P2^4;    //红外发射
sbit ir_in=P3^2; //红外接收
sbit led=P1^1;


#define const_key_time1 2000  //感应去抖动延时的时间
uint uiKeyTimeCnt1=0; //感应去抖动延时计数器
uchar ucKeyLock1=0;   //感应触发后自锁的变量标志




void delay(uint z)           //ms
{
        uint x,y;
        for(x=z; x>0; x--)
                for(y=114; y>0; y--);
}

         
void main()
{

                TMOD |= 0x02;                //设置定时器模式
                TL0 = 0xF4;                //设置定时初值                  13us
                TH0 = 0xF4;                //设置定时重载值               
                EA=1;
        ET0=1;
        TR0=1;
        led=0;
        delay(500);
        led=1;
        while(1)
        {

                if(ir_in==1)        //没有感应 要及时清零一些标志
                {
        
                        ucKeyLock1=0;   //感应自锁标志清零
                        uiKeyTimeCnt1=0;//感应去抖动延时计数器清零
               
                }
                else if(ucKeyLock1==0)//有感应,且是第一次感应
                {        
                        ++uiKeyTimeCnt1;  //延时计数器
                        if(uiKeyTimeCnt1>const_key_time1)
                        {
                                uiKeyTimeCnt1=0;
                                ucKeyLock1=1; //自锁按键置位,避免一直触发
                                led = !led;
                        }               
                }


        }
}

void timer0() interrupt 1
{

        ir=!ir;
}

我现在就让它不停的发38K载波,感应就正常了;    不再发100ms,停100ms,就可以了

 楼主| li123ds 发表于 2019-9-26 15:18 | 显示全部楼层
18990194628 发表于 2019-9-26 13:53
新增一个变量,保存当前状态之前的状态
比如当前状态为flag
上一次状态为last_flag

等会试一试
您需要登录后才可以回帖 登录 | 注册

本版积分规则

2

主题

20

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部