代码文件和测试

点击打开在线编译器,边学边练

创建好“infrared.c”和“infrared.h”文件。


1.infrared.c的代码

#include <reg52.h>
#include <infrared.h>
  
unsigned char irflag = 0; //红外接收标志,收到一帧正确数据后置1
unsigned char ircode[4];  //红外代码接收缓冲区
  
/* 初始化红外接收功能 */
void InitInfrared()
{
    IR_INPUT = 1;  //确保红外接收引脚被释放
    TMOD &= 0x0F;  //清零T1的控制位
    TMOD |= 0x10;  //配置T1为模式1
    TR1 = 0;       //停止T1计数
    ET1 = 0;       //禁止T1中断
    IT1 = 1;       //设置INT1为负边沿触发
    EX1 = 1;       //使能INT1中断
}
 
/* 获取当前高电平的持续时间 */
unsigned int GetHighTime()
{
    TH1 = 0;                //清零T1计数初值
    TL1 = 0;
    TR1 = 1;                //启动T1计数
    while (IR_INPUT)        //红外输入引脚为1时循环检测等待,变为0时则结束本循环
    {
        if (TH1 >= 0x40)
        {                   //当T1计数值大于0x4000,即高电平持续时间超过约18ms时,
            break;          //强制退出循环,是为了避免信号异常时,程序假死在这里。
        }
    }
    TR1 = 0;                //停止T1计数
   
    return (TH1*256 + TL1); //T1计数值合成为16bit整型数,并返回该数
}
 
/* 获取当前低电平的持续时间 */
unsigned int GetLowTime()
{
    TH1 = 0;                //清零T1计数初值
    TL1 = 0;
    TR1 = 1;                //启动T1计数
    while (!IR_INPUT)       //红外输入引脚为0时循环检测等待,变为1时则结束本循环
    {
        if (TH1 >= 0x40)
        {                   //当T1计数值大于0x4000,即低电平持续时间超过约18ms时,
            break;          //强制退出循环,是为了避免信号异常时,程序假死在这里。
        }
    }
    TR1 = 0;                //停止T1计数
   
    return (TH1*256 + TL1); //T1计数值合成为16bit整型数,并返回该数
}
 
/* INT1中断服务函数,执行红外接收及解码 */
void EXINT1_ISR() interrupt 2
{
    unsigned char i,j;
    unsigned char byt;
    unsigned int time;
     
    //接收并判定引导码的9ms低电平
    time = GetLowTime();
    if ((time<7833) || (time>8755))  //时间判定范围为8.5~9.5ms,
    {                                //超过此范围则说明为误码,直接退出
        IE1 = 0;                     //退出前清零INT1中断标志
        return;
    }
    //接收并判定引导码的4.5ms高电平
    time = GetHighTime();
    if ((time<3686) || (time>4608))  //时间判定范围为4.0~5.0ms,
    {                                //超过此范围则说明为误码,直接退出
        IE1 = 0;
        return;
    }
 
    //接收并判定后续的4字节数据
    for (i=0; i<4; i++)     //循环接收4个字节
    {
        for (j=0; j<8; j++) //循环接收判定每字节的8个bit
        {
            //接收判定每bit的560us低电平
            time = GetLowTime();
            if ((time<313) || (time>718))        //时间判定范围为340~780us,
            {                                    //超过此范围则说明为误码,直接退出
                IE1 = 0;
                return;
            }
            //接收每bit高电平时间,判定该bit的值
            time = GetHighTime();
            if ((time>313) && (time<718))        //时间判定范围为340~780us,
            {                                    //在此范围内说明该bit值为0
                byt >>= 1;                       //因低位在先,所以数据右移,高位为0
            }
            else if ((time>1345) && (time<1751)) //时间判定范围为1460~1900us,
            {                                    //在此范围内说明该bit值为1
                byt >>= 1;   //因低位在先,所以数据右移,
                byt |= 0x80; //高位置1
            }
            else             //不在上述范围内则说明为误码,直接退出
            {
                IE1 = 0;
                return;
            }
        }
        ircode[i] = byt;     //接收完一个字节后保存到缓冲区
    }
    irflag = 1;              //接收完毕后设置标志
    IE1 = 0;                 //退出前清零INT1中断标志
}


2.infrared.h的代码

因为主函数中只需要使用“InitInfrared();”函数来初始化,而“unsigned int GetHighTime()”和“unsigned int GetLowTime()”都是只在“void EXINT1_ISR() interrupt 2”中使用,所以头文件不用声明这三部分的函数。

#ifndef __INFRARED_H__
#define __INFRARED_H__
  
sbit IR_INPUT = P3^3;           //红外接收引脚
extern unsigned char irflag;    //红外接收标志,收到一帧正确数据后置1
extern unsigned char ircode[4]; //红外代码接收缓冲区
  
void InitInfrared();            //初始化红外接收功能
  
#endif


代码


3.main.c测试代码

我们在宋老师的例程lesson16_1中通过按红外遥控器上的按键得知,第一行的三个按键会使ircode[2]分别变为0x45、0x46、0x47显示在数码管上,那么我们只需要判断ircode[2]的数据就可以知道按下的是哪个按键然后去执行相关任务就可以了。

我们用小灯测试红外遥控器的按键是否有效,有效则会切换小灯的亮灭。

#include <reg52.h>
#include <function.h>//详见第六章第8讲
#include <infrared.h>
 
void main()
{
    LED_Init();//初始化LED硬件模块
    EA = 1; 
    InitInfrared();
  
    while (1)
    {
        if (irflag)  
        {
            irflag = 0;   
            //以下是遥控器第一行按键
            if(ircode[2]==0x45)LED9=!LED9;
            if(ircode[2]==0x46)LED8=!LED8;
            if(ircode[2]==0x47)LED7=!LED7;
      
            //以下是遥控器第二行按键
            if(ircode[2]==0x44)LED4=!LED4;
            if(ircode[2]==0x40)LED3=!LED3;
            if(ircode[2]==0x43)LED2=!LED2;    
        }  
    }
}

本文固定URL:https://www.dotcpp.com/course/396

第一章 单片机入门
第二章 LED
第三章 蜂鸣器
第四章 数码管
第五章 独立按键
第六章 多文件编程
第七章 外部中断
第八章 定时器
第九章 舵机与超声波模块
第十章 串口通信
第十一章 1602液晶屏
第十二章 IIC通信
第十三章 红外遥控与温度传感器
第十四章 AD与DA
第十五章 混合例程
第十六章 完结
Dotcpp在线编译      (登录可减少运行等待时间)