机甲老顽童 发表于 2016-10-29 23:20:35

闪闪闪!怎么保持住呢?

我爱萝丽爱萝丽 发表于 2016-10-30 05:24:48

1.2 发射38kHz红外信号


什么是红外线?红外线也是光的一种,只是人眼看不见而已。所有的物体都会发射红外线,电灯也会发射红外线,为什么开了灯红外接收机的灯不亮,只有按下电视遥控器灯才会亮?
这是因为在红外接收头里,已经秘密做了协议,只有收到闪烁频率为38KHz的红外线,才会认为有正确信号。
也就是说,如果你能把一个手电筒一秒内开关3万8千次,就可以被红外接收机识别。


人没有那么快,但是神奇的单片机可以啊,一秒开关一百万次都轻松,你需要动脑筋想想怎么去写程序实现?


很简单,算一下38KHz的周期大概是26微秒,让遥控器发射13微秒红外线,再关闭13微秒,循环发射即可。


按下按键就能让接收机有反应的程序:

我是天才 发表于 2016-10-30 07:17:03

我爱萝丽爱萝丽 发表于 2016-10-30 05:24
1.2 发射38kHz红外信号




如果发射和接受离得很远,一直按着按键,亮半秒就不亮了,如果发射接受离得很近,那么按下去就可以一直亮,不知道为什么

815023524 发表于 2016-10-30 07:27:43

讲的简单易懂,这样好,可以从易到难,好学

飞来峰 发表于 2016-10-30 07:29:15

好帖学习了

wurenji 发表于 2016-10-30 08:07:51

是沙发吗,收藏了,感谢楼主的无私分享

哈哈哈哈哈123 发表于 2016-10-30 10:41:03

支持支持

3300178839 发表于 2016-10-30 11:48:52

学习啦,感谢分享。。。。。。。。。。。。。。

我爱萝丽爱萝丽 发表于 2016-10-30 18:14:27

本帖最后由 我爱萝丽爱萝丽 于 2016-11-1 00:55 编辑

1.3 引脚推挽输出模式

做完1.2,你应该会发现我们的遥控器距离没有电视的遥控器距离远,几米外就没反应了。为什么?


复习知识点(11),这是因为现在单片机的高电平输出电流只有不到1ma,发射的红外线太小。
除了像第一个项目一样用三极管放大电流,只驱动一个LED的话,还可以直接使用单片机20ma电流的推挽输出模式。


知识点(38) 声明特殊寄存器 sfr P3M0=0xb2;

sfr 是声明寄存器的关键词;
P3M0 是设置P3口输出模式的寄存器;
0xb2 是P3M0这个寄存器的地址。
就跟sbit声明单片机引脚一样,声明之后程序里就可以使用。


知识点(39) <reg51.h>里装了什么
有足够好奇心的话你可以右键reg51、open打开看一看。其实里面都是寄存器声明哦,以后学习会逐个用到。
至于P3M0寄存器,是新型STC单片机新加入的,所以你要自己声明。


知识点(40) P3M0寄存器是什么
什么是寄存器?你可以想象为一个寄存器里有8个小房间,每个房间控制一个引脚,可以装1或者0,1代表打开推挽模式,0代表关。



知识点(41) 设置寄存器
怎么设置?直接写P3M0=0010 0000吗?
当然不是,我们人类用的是10进制,计算机用的是二进制,需要先换算才能正确写。
我知道很多人一想到进制之间的换算就会头晕,所以我推荐你使用电脑自带的强大工具“计算器”
打开Windows计算器工具,选择程序员选项:

点击BIN二进制选项,输入0010 0000,(最前面的0不起作用)
你会看到DEC十进制选项里已经自动转换成10进制32,所以正确的设置应该是P3M0=32;
同时HEX十六进制选项里也显示了20,写成P3M0=0x20;也是可以的,加上0x代表16进制。



改了程序以后遥控距离瞬间提高十米:
#include<reg51.h>

sfr P3M0=0xb2;   //声明寄存器

sbit IR_LED=P3^5;//定义红外LED引脚
sbit Key1=P3^0;    //定义按键1

void Delay13us()                //@12.000MHz
{
      unsigned char i;

      i = 36;   
      while (--i);
}

main()
{
      P3M0=32;      //设置P3.5引脚为大电流模式

      while(1)
      {
                if(Key1==0)      //按键按下变成低电平
                {
                        IR_LED=1;      //发射38KHz方波红外信号
                        Delay13us();
                        IR_LED=0;
                        Delay13us();
                }
                else
                {
                        IR_LED=0;
                }
      }
}


我爱萝丽爱萝丽 发表于 2016-10-31 01:01:30

我是天才 发表于 2016-10-30 07:17
如果发射和接受离得很远,一直按着按键,亮半秒就不亮了,如果发射接受离得很近,那么按下去就可以一直亮 ...

接收头饱和了

nigesb942 发表于 2016-10-31 16:34:48

楼主,您好,请问您懂PPM、PWM、SBUS的转码麽?求赐教

我爱萝丽爱萝丽 发表于 2016-10-31 18:12:29

nigesb942 发表于 2016-10-31 16:34
楼主,您好,请问您懂PPM、PWM、SBUS的转码麽?求赐教

PWM、PPM用脉宽测量,SBUS就是反向串口,具体协议百度有

panlongdian 发表于 2016-10-31 18:38:32

天天看一眼第八课看有没有更新,结果跑到第九课了,把我急的哟,谢谢萝莉。

我爱萝丽爱萝丽 发表于 2016-11-1 03:58:32

本帖最后由 我爱萝丽爱萝丽 于 2016-11-1 04:18 编辑

1.4 制定一个简单的通信协议


实验到这里,还有一个很不爽的问题需要解决:别的遥控器也能控制我们的接收机!
怎样让电视的遥控器只能控制电视,我们的遥控器只控制我们的呢?


这就跟二战时的电台谍战一样了,我们的电台可以收到敌人的信息,敌人的电台也能收到我们的,当时是怎么保密的呢?
欲保密,先加密。
制定一套跟别人不同的通信协议,就能让别的遥控器对你失灵了!


电视遥控器的通信协议很复杂,我们不必学他,给自己添烦恼,而是另辟蹊径,自己定义自己的协议。
这里先举个例子,定义一个超简单的协议:
发射20ms红外信号,代表按键1;
发射30ms红外信号,代表按键2;
发射40ms红外信号,代表按键3……
是不是特别简单(∩_∩)


在上一小节,我们发射红外的程序,发射一次是26微秒,发射100次才2.6ms,20ms需要769次。
用程序控制循环的时间,是不是跟以前的学的delay_n_ms()类似?如果忘记可以回去复习一下知识点(18)。
void TX_IR(unsigned int n)//发射N个红外信号 时间是26us*N
{
      while(n)
      {
                IR_LED=1;      //发射一个38KHz方波红外信号
                Delay13us();
                IR_LED=0;
                Delay13us();
               
                n=n-1;
      }
}





遥控器用旧知识可以搞定,接收机要测量时间需要新技能:
知识点(42) 用while测量低电平时间
while(IR_IN==0)//如果引脚一直为低电平,一直循环
{
    Delay1ms();
    time=time+1;//每循环一次,就记录了1ms时间
}
循环程序不仅可以用来延时,还可以用来计时。当引脚变成高电平1时,IR_IN==0就不是“真”的了,
循环自动结束,这时看time的值就知道时间过去多少毫秒了。


当遥控器发射了20ms,由于环境的干扰,接收机可能收到20ms,也可能只收到18ms,有没有办法判断一个范围呢?
知识点(43) && “并且”运算符
if(time>15 && time<25)
两个&&代表“并且”的意思,time大于15,并且小于25,两个都正确才行。
用这样的方式,可以同时判断两个条件。


接收机参考程序,遥控器可以控制接收机的亮灭,更多功能就要看大家自己的练习了。甚至可以和第一个项目结合起来,遥控控制七色光芒。大家可以把自己的程序上传上来相互交流。
#include<reg51.h>

sbit LED=P3^5;    //定义指示灯
sbit IR_IN=P3^4;//定义红外接收头引脚


unsigned char time;    //定义一个数据,记录时间


void Delay1ms()                //@12.000MHz
{
      unsigned char i, j;

      i = 12;
      j = 169;
      do
      {
                while (--j);
      } while (--i);
}


main()
{
      
      while(1)
      {
               
                if(IR_IN==0)      //收到红外数据引脚变成低电平,开始测量
                {
                        time=0;//先把时间清零
                        while(IR_IN==0)//如果引脚一直为低电平,一直循环
                        {
                              Delay1ms();
                              time=time+1;//每循环一次,就记录了1ms时间
                        }
                        //引脚变成高电平,循环结束
                        
                        if(time>15&&time<25)//16ms~24ms低电平,按键1按下
                        {
                              LED=1;
                        }      
                        
                        if(time>25&&time<35)//26ms~34ms低电平,按键2按下
                        {
                              LED=0;
                        }                              
                }
               
      }
}

遥控器参考程序:
#include<reg51.h>

sfr P3M0=0xb2;   //声明寄存器

sbit IR_LED=P3^5;//定义红外LED引脚
sbit Key1=P3^0;    //定义按键1
sbit Key2=P3^1;    //定义按键2


unsigned char Key1_old;    //定义一个数据,记录Key1过去出现低电平
unsigned char Key1_action; //定义一个数据,传递Key1是否动作的消息
unsigned char Key2_old;    //定义一个数据,记录Key2过去出现低电平
unsigned char Key2_action; //定义一个数据,传递Key2是否动作的消息


void Delay1ms()                //@12.000MHz
{
      unsigned char i, j;

      i = 12;
      j = 169;
      do
      {
                while (--j);
      } while (--i);
}

void delay_n_ms(unsigned int n) //自己定义的延时n毫秒函数
{
      while(n)         
      {
                Delay1ms();
                n=n-1;//每循环一次n减小1
      }   
}


void Delay13us()                //@12.000MHz
{
      unsigned char i;

      i = 36;   
      while (--i);
}

void TX_IR(unsigned int n)//发射N个红外信号 时间是26us*N
{
      while(n)
      {
                IR_LED=1;      //发射一个38KHz方波红外信号
                Delay13us();
                IR_LED=0;
                Delay13us();
                           
                n=n-1;
      }
}


main()
{
      IR_LED=0;//关闭红外LED
      P3M0=32;      //设置P3.5引脚为大电流模式
      
      Key1_old=1;   //进入循环前,先初始化标志位。按键还没按下,old是高电平
      Key2_old=1;
      
      while(1)   
      {

                delay_n_ms(10);   //系统周期,每循环一次10ms
                                    
                        
                if(Key1==1)
                {
                        if(Key1_old==0) //如果本次是高电平,上次是低电平,检测到按键
                        {
                              Key1_action=1;                                                                        
                        }
                }
               
                Key1_old=Key1;   //保存高低电平


                if(Key2==1)
                {
                        if(Key2_old==0) //如果本次是高电平,上次是低电平,检测到按键
                        {
                              Key2_action=1;                                                                        
                        }
                }
               
                Key2_old=Key2;   //保存高低电平
               
                              
                //上面是完全模块化的按键检测程序,只传递出两个action消息
                ////////////////////////////////////////////
               
                if(Key1_action==1)//有按键消息,处理按键功能
                {
                        Key1_action=0;   //处理过按键后要清0
                        
                        TX_IR(769);//按键1发射20ms红外
                }
               
                if(Key2_action==1)//有按键消息,处理按键功能
                {
                        Key2_action=0;   //处理过按键后要清0
                        
                        TX_IR(1153);//按键2发射30ms红外
                }
               
               
      }
}


panlongdian 发表于 2016-11-1 06:48:10

我爱萝丽爱萝丽 发表于 2016-11-1 03:58
1.4 制定一个简单的通信协议




实在感谢萝莉老师百忙之中抽出时间来交我们学习单片机知识,用生动而又易懂的语言让我们轻松掌握复杂的程序,举一反三的让我们发挥想象,使枯燥的计算机语言变得丰富多彩。衷心感谢萝莉老师。

我是天才 发表于 2016-11-2 00:03:28

我爱萝丽爱萝丽 发表于 2016-11-1 03:58
1.4 制定一个简单的通信协议




感觉这个接收程序也能检测航模接收机的ppm信号,是不大神?

我爱萝丽爱萝丽 发表于 2016-11-2 01:23:48

我是天才 发表于 2016-11-2 00:03
感觉这个接收程序也能检测航模接收机的ppm信号,是不大神?

是的

cxmoya 发表于 2016-11-2 06:59:32

学习中……回头再看……

shikun888 发表于 2016-11-2 08:21:18

有点儿明白了

独行者 发表于 2016-11-2 09:46:55

老师辛苦,谢谢!
页: 1 [2] 3 4
查看完整版本: 第九课:看不见的信使——红外线