您的位置:首页 > 运维架构 > Linux

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

2017-06-20 14:38 369 查看
红外是一种光, 对于人类是不可见的光,但摄像头可以捕捉到红外光.

红外可用不同的频谱来表二进制的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:
retur
b400
n 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");
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息