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
红外可用不同的频谱来表二进制的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");
相关文章推荐
- 【转】Linux那些事儿 之 戏说USB(35)驱动的生命线(三)
- 从 2.4 到 2.6:Linux 内核可装载模块机制的改变对设备驱动的影响
- 从 2.4 到 2.6:Linux 内核可装载模块机制的改变对设备驱动的影响
- Linux2.6内核驱动移植参考
- vmware中升级linux内核及安装网卡驱动
- 编译和安装linux内核2.6.24,并且写一个简单的内核驱动测试之
- 基于S3C2410平台的Linux 2.6.14内核+平台驱动的移植指南(最终版)
- Linux2.6内核驱动与2.4的区别
- 【转载】从 2.4 到 2.6:Linux 内核可装载模块机制的改变对设备驱动的影响
- Linux 2.6 内核驱动移植
- 一个Linux2.6版内核字符驱动的例子
- 基于S3C2410平台的Linux 2.6.14内核+平台驱动的移植指南(最终版)
- Linux2.6内核驱动移植参考
- Linux2.6内核驱动移植参考
- 学习内核---Linux网卡驱动分析
- 从 2.4 到 2.6:Linux 内核可装载模块机制的改变对设备驱动的影响
- 【嵌入式Linux学习七步曲之第五篇 Linux内核及驱动编程】全面解析Linux内核的同步与互斥机制--同步篇
- Linux2.6内核驱动与2.4的区别
- Linux2.6内核驱动hello.c
- 从 2.4 到 2.6:Linux 内核可装载模块机制的改变对设备驱动的影响