红外接收模块定时器采集

 1.硬件接口

2.红外协议介绍

红外线是波长在750nm至1mm之间的电磁波,其频率高于微波而低于可见光,是一种人的眼睛看不到的光线。无线电波和微波已被广泛应用在长距离的无线通信中,但由于红外线的波长较短,对障碍物的衍射能力差,所以更适合应用在需要短距离无线通信场合点对点的直线数据传输。

在实际的通信领域,发出来的信号一般有较宽的频谱,而且都是在比较低的频率段分布大量的能量,所以称之为基带信号,这种信号是不适合直接在信道中传输的。为便于传输、提高抗干扰能力和有效的利用带宽,通常需要将信号调制到适合信道和噪声特性的频率范围内进行传输,这就叫做信号调制。我们平时用到的红外遥控器里的红外通信,通常是使用38KHz左右的载波进行调制的。

 

  1. 红外遥控协议组成:一般是引导码用户码按键码、重复码、按键反码、结束码等组成;
  2. 红外遥控载波频率:33K、36K、36.6K、38K、40K、56K。常用38K以37.916K最准确;
  3. 红外载波占空比:1/2、1/3;不常用的有1/4;
  4. 调制方式:脉宽调制和相位调制;                                                                                                  针对于接收方:
    1. 引导码:9ms的低电平 + 4.5ms高电平;
    2. 重复码:9ms的低电平 + 2.25ms高电平;
    3. 停止位:560us的低电平;
    4. 逻辑0:560us的低电平 + 560us的高电平;
    5. 逻辑1:560us的低电平 + 1680us的高电平

 以下是我利用逻辑分析仪捕获的时序表:

 一般来说可以采用外部中断加定时器的方式配合采集红外信号,也可以采用PWM的外部边沿捕获来达到效果,但是这里就介绍以下最近新学的单个使用定时器来达到效果的方法,若有不对之处请大佬指正。大概思路介绍,首先配置一个100us的定时器

 

然后配置对应的信号引脚为输入模式,然后记录这个引脚发生电平变化的时间(这边可以理解为次数),然后根据对应的引导码,用户码,按键码等的时间来判断高低电平的情况。代码如下:

/*************  红外接收程序变量声明    **************/
//sbit    P_IR_RX = P3^5;         //定义红外接收输入IO口
#define SysTick     10000       // 次/秒, 系统滴答频率, 在4000~16000之间

u8  IR_SampleCnt;       //采样计数
u8  IR_BitCnt;          //编码位数
u8  IR_UserH;           //用户码(地址)高字节
u8  IR_UserL;           //用户码(地址)低字节
u8  IR_data;            //数据原码
u8  IR_DataShit;        //数据移位

bit P_IR_RX_temp;       //Last sample
bit B_IR_Sync;          //已收到同步标志
bit B_IR_Press;         //红外接收标志
u8  IR_code;            //红外键码
u16 UserCode;           //用户码.
u8 count=0;

/******************** 红外采样时间宏定义, 用户不要随意修改  *******************/
#define IR_SAMPLE_TIME      (1000000UL/SysTick)     //查询时间间隔, us, 红外接收要求在60us~250us之间
#if ((IR_SAMPLE_TIME <= 250) && (IR_SAMPLE_TIME >= 60))
    #define D_IR_sample         IR_SAMPLE_TIME      //定义采样时间,在60us~250us之间
#endif

#define D_IR_SYNC_MAX       (15000/D_IR_sample) //SYNC max time
#define D_IR_SYNC_MIN       (9700 /D_IR_sample) //SYNC min time
#define D_IR_SYNC_DIVIDE    (12375/D_IR_sample) //decide data 0 or 1
#define D_IR_DATA_MAX       (3000 /D_IR_sample) //data max time
#define D_IR_DATA_MIN       (600  /D_IR_sample) //data min time
#define D_IR_DATA_DIVIDE    (1687 /D_IR_sample) //decide data 0 or 1
#define D_IR_BIT_NUMBER     32                  //bit number

//*******************************************************************************************
//**************************** IR RECEIVE MODULE ********************************************

void IR_Int(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_PU;
    GPIO_InitStructure.GPIO_AFType = GPIO_AFType_AF0;
    GPIO_Init(GPIO_P1, &GPIO_InitStructure);
}

void IR_RX_NEC(void)
{
    u8  SampleTime;
    IR_SampleCnt++;                         //Sample + 1

    
    F0 = P_IR_RX_temp;                      //Save Last sample status
    P_IR_RX_temp = P_IR_RX;                 //Read current status
    if(F0 && !P_IR_RX_temp)                 //Pre-sample is high,and current sample is low, so is fall edge
    {
        SampleTime = IR_SampleCnt;          //get the sample time
        IR_SampleCnt = 0;                   //Clear the sample counter

             if(SampleTime > D_IR_SYNC_MAX)     B_IR_Sync = 0;  //large the Maxim SYNC time, then error
        else if(SampleTime >= D_IR_SYNC_MIN)                    //SYNC
        {
            if(SampleTime >= D_IR_SYNC_DIVIDE)
            {
                B_IR_Sync = 1;                  //has received SYNC
                IR_BitCnt = D_IR_BIT_NUMBER;    //Load bit number
            }
        }
        else if(B_IR_Sync)                      //has received SYNC
        {
            if(SampleTime > D_IR_DATA_MAX)      B_IR_Sync=0;    //data samlpe time too large
            else
            {
                IR_DataShit >>= 1;                  //data shift right 1 bit
                if(SampleTime >= D_IR_DATA_DIVIDE)  IR_DataShit |= 0x80;    //devide data 0 or 1
                if(--IR_BitCnt == 0)                //bit number is over?
                {
                    B_IR_Sync = 0;                  //Clear SYNC
                    if(~IR_DataShit == IR_data)     //判断数据正反码
                    {
                        UserCode = ((u16)IR_UserH << 8) + IR_UserL;
                        IR_code      = IR_data;
                        B_IR_Press   = 1;           //数据有效
                    }
                }
                else if((IR_BitCnt & 7)== 0)        //one byte receive
                {
                    IR_UserL = IR_UserH;            //Save the User code high byte
                    IR_UserH = IR_data;             //Save the User code low byte
                    IR_data  = IR_DataShit;         //Save the IR data byte
                }
            }
        }
    }
}

最后利用B_IR_Press   这个标志位来判断是否有红外信号发生:

if(IR_code == 64 && B_IR_Press)//遥控器电源键 IR_code -- 对应的数据
    {
        B_IR_Press = 0;
        //这里就可以写你需要在发生这个事件时要做的逻辑
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值