35 红外接收头在linux内核里的驱动

红外是一种光, 对于人类是不可见的光,但摄像头可以捕捉到红外光.

红外可用不同的频谱来表二进制的0和1(高/低电平).
传输分成发送端(遥控器),接收端(红外接收头)

发送端发出表示高低电平的不同的光, 接收端收到红外光后还原成对应的高低电平来表示二进制的0和1.

发送端可由专门的红外发射芯片来实现,如图:
这里写图片描述

红外发射芯片会自动扫描矩阵键盘电路,根据不同的键码,生成一串二进制数据,再按每位的二进制数据用相应的红外光发出.
遥控器上的一个按键的数据:
这里写图片描述

其中引导码用于标识一个键码数据的开始。 用户编码由两个8位组成,用于标识遥控器的厂家。键数据码用于区别按下的键。键数据码的反码用于校验使用, 确保数据完整.

除了引导码外,共有32位数据位,每位数据不是二进制0就是二进制1.从低位开始传输.
引导码的表示, 数据0和数据1的表示,参考下图:
这里写图片描述
如上图,数据0的信号周期为1.12ms, 数据1的信号周期为2.24ms.

当同一键连续按下按键下,发出的数据都是完整的一帔键数据(有些发射芯片处理方式不同),如下图:
这里写图片描述

/
红外接收头收到光后,会把光还原成对应数据0/1的高低电平信号.
需要注意, 在接收头收到的信号的相位是相反的, 可能是发送端的使用三极管来放大信号的原因。
接收部分的图,用逻辑分析仪抓取出来的图:

这里写图片描述
这里写图片描述
注意:用的遥控器是benQ投影仪,并不是用发射芯片SC902。但除了引导码不同外,其它一样.

//
测试驱动代码:
test.c


#include <linux/init.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <mach/gpio.h>
#include <linux/gpio.h>
#include <linux/ktime.h>

//红外接收头,三个引脚
// 三个引脚向下, 突出的半圆面向自己,从左往右引脚分别是: 数据脚(接IO口), 地线(gnd),  电源线(vcc, 3.3v)

// 红外接收头的数据脚接的是PL11
#define IR_IO  GPIOL(11)

int flag = 0; //表示数据帧的开始
int num = 0; //表示数据帧里的第几位数据
static long long prev = 0; //记录上次的时间
unsigned int times[40]; //记录每位数据的时间

irqreturn_t irq_func(int irqno, void *arg)
{
    long long now = ktime_to_us(ktime_get());
    unsigned int offset;
    int i, j, tmp;

    if (!flag) //数据开始
    {
        flag = 1;
        prev = now;
        return IRQ_HANDLED;
    }

    offset = now - prev;
    prev = now;
    if ((offset > 13000) && (offset < 14000)) //判断是否收到引导码,引导码13.5ms
    {
        num = 0;
        return IRQ_HANDLED;
    }   


    //不是引导码时间,数据位时间
    if (num < 32)
        times[num++] = offset;

    if (num >= 32)
    {
        for (i = 0; i < 4; i++) //共4个字节
        {
            tmp = 0;
            for (j = 0; j < 8; j++) //每字节8位
            {
                if (times[i*8+j] > 2000) //如果数据位的信号周期大于2ms, 则是二进制数据1
                    tmp |= 1<<j;
            }
            printk("%02x ", tmp);
        }
        printk("\n");
        flag = 0; //重新开始帧
    }
    return IRQ_HANDLED;
}

static int __init test_init(void)
{
    int ret;

    ret = request_irq(gpio_to_irq(IR_IO), irq_func, IRQF_TRIGGER_FALLING, "myir", NULL);
    if (ret < 0)
        goto err0;

    return 0;
err0:
    return ret;

}


static void __exit test_exit(void)
{
    free_irq(gpio_to_irq(IR_IO), NULL);
}

module_init(test_init);
module_exit(test_exit);

MODULE_LICENSE("GPL");
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值