打印
[51单片机]

红外反射开关问题求助

[复制链接]
841|7
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
li123ds|  楼主 | 2019-9-26 12:05 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

//红外反射开关,接收头HS0038B,发射管用pnp三极管驱动
//第一次上电,灯亮1秒后熄灭,
//手挡一次开,再挡一次关,如此循环
//实验板测试手挡一次开,再挡一次关 开关正常;
//但是有一个问题,如果手一直挡在前面,LED会不停的亮--灭        -- 亮--灭
//请大神们看下,怎样才能做到手挡在前面不移开,保持一种状态
#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;        //

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


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


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

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

        ET0=1;
        TR0=1;
        led=0;
        delay(500);
        led=1;
        while(1)
        {
                if(flag==0 )
                {
                        fa_38k();  //发38K
                }
                else ir=1;           //停止发射
           
               




        if(ir_in==0)          //手挡住
        {
                flag_key=1;
                cont1++;
                key_lock=1;       
        }
        else flag_key=0; //手移开
       
        if(flag_key==1 && cont1==100)
        {         
                 ir=1;
                 cont1=0;
                 led = !led;
                 delay(1000);

        }

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



        }
}

void timer0() interrupt 1
{
        TH0 = (65536-1000)/256;  //重装1ms初值
        TL0 = (65536-1000)%256;
                cont++;
        if(cont==100)  
        {        
                cont=0;
                flag=!flag;         //发100ms 38K,停100ms

        }

}

使用特权

评论回复

相关帖子

沙发
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的高低脉冲。
你只要理解上述原理,就会找到故障原因。
另外,红外接收器,也会误码,即使没有任何红外信号,也会时不时输出一些窄脉冲,这些都需要软件考虑的。
你这个软件根本不实用的。

使用特权

评论回复
5
18990194628| | 2019-9-26 13:53 | 只看该作者
新增一个变量,保存当前状态之前的状态
比如当前状态为flag
上一次状态为last_flag
判断当前状态和上一次状态的区别
if(上一次状态为没挡住 && 现在状态为挡住)
{
last_flag = flag
led亮
}
else if(上一次为挡住 && 现在为没挡住)
{
last_flag = flag
led灭
}

使用特权

评论回复
评论
li123ds 2019-9-26 15:18 回复TA
等会试一试 
6
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,就可以了

使用特权

评论回复
7
li123ds|  楼主 | 2019-9-26 15:18 | 只看该作者
18990194628 发表于 2019-9-26 13:53
新增一个变量,保存当前状态之前的状态
比如当前状态为flag
上一次状态为last_flag

等会试一试

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

2

主题

19

帖子

0

粉丝