IRM3800 红外遥控器解码 linux驱动
这一次还是接在 Cemera 上。用 中断引脚 EINT20 也就是 GPG12.
之前焊的 51 板子上有一个红外接收器。
请注意了,是
标准的 NEC 码规范:
首次发送的是9ms的高电平脉冲,其后是4.5ms的低电平,接下来就是8bit的地址码(从低有效位开始发),
而后是8bit的地址码的反码(主要是用于校验是否出错)。然后是8bit 的命令码(也是从低有效位开始发),
而后也是8bit 的命令码的反码。其“0”为载波发射0.56ms,不发射0.565ms,其“1”为载波发射0.56ms,
不发射1.69ms。
这是一种不太好的实现方式,以后会更新其它更好的算法。
原理比较简单,当有中断发生中,将GPG12设为输入功能,通过读引脚的电平,配合时间,就能得到 红外遥控器发出的代码。
代码共4个,厂家ID 高, 厂家ID 低, 命令 , 命令反码
经过试验,发现,命令只有低6个bit 是正常的,
驱动源码
1 #include <linux/consolemap.h> 2 #include <linux/module.h> 3 #include <linux/sched.h> 4 #include <linux/tty.h> 5 #include <linux/tty_flip.h> 6 #include <linux/mm.h> 7 #include <linux/string.h> 8 #include <linux/init.h> 9 #include <linux/slab.h> 10 11 #include <linux/kbd_kern.h> 12 #include <linux/kbd_diacr.h> 13 #include <linux/vt_kern.h> 14 #include <linux/input.h> 15 #include <linux/reboot.h> 16 #include <linux/notifier.h> 17 #include <linux/jiffies.h> 18 #include <linux/uaccess.h> 19 20 #include <asm/irq_regs.h> 21 #include <linux/interrupt.h> 22 #include <linux/irq.h> 23 #include <linux/delay.h> 24 25 #include <linux/gpio.h> 26 #include <mach/regs-gpio.h> 27 #include <mach/gpio-samsung.h> 28 #include <mach/hardware.h> 29 #include <plat/gpio-cfg.h> 30 31 /* 32 标准的 NEC 码规范: 33 首次发送的是9ms的高电平脉冲,其后是4.5ms的低电平,接下来就是8bit的地址码(从低有效位开始发), 34 而后是8bit的地址码的反码(主要是用于校验是否出错)。然后是8bit 的命令码(也是从低有效位开始发), 35 而后也是8bit 的命令码的反码。其“0”为载波发射0.56ms,不发射0.565ms,其“1”为载波发射0.56ms, 36 不发射1.69ms。 37 */ 38 39 #define IR gpio_get_value(S3C2410_GPG(12)) 40 41 static irqreturn_t irm_irq(int irq, void *dev_id) 42 { 43 int k,i; 44 unsigned char irm_code[4] = {0, 0, 0, 0}; 45 46 /* 操作原理 当有中断发生中 配置引脚功能为 GPIO 输入型 直接读IRM信号电平高低 */ 47 s3c_gpio_cfgpin(S3C2410_GPG(12), S3C2410_GPIO_INPUT); 48 mdelay(5); //9ms 内必须是低电平否则就不是头信息 49 if(0 == IR) 50 { 51 while(! IR);//等待4.5ms的高电平 52 53 //检测是否是 2.5ms 重码 54 mdelay(3); 55 if(1 == IR) 56 { 57 //k 4位编码 58 for(k=0; k<4; k++) 59 { 60 //i 每一个编码的 8bit 61 for(i=0;i<8;i++) 62 { 63 while(IR); //等待变为低电平时 64 while(! IR); //等待变为高电平后 65 udelay(700); //休眠700us 后读值 66 irm_code[k] |= (IR & 1)<<i;//先存低位 67 } 68 } 69 70 //计算反码 code码是否正确 71 if((irm_code[2]&0x3f) == (~(irm_code[3]) & 0x3f)) 72 { 73 printk("FID:0x%x 0x%x CID: 0x%x 0x%x\n", irm_code[0], irm_code[1], irm_code[2], irm_code[3]); 74 } 75 } 76 } 77 s3c_gpio_cfgpin(S3C2410_GPG(12), S3C2410_GPIO_IRQ); 78 return IRQ_HANDLED; 79 } 80 81 static int irm_init(void) 82 { 83 int ret; 84 //注册中断 上升沿触发 85 ret = request_irq(IRQ_EINT20, irm_irq, IRQF_TRIGGER_RISING, "irm_irq", NULL); 86 return 0; 87 } 88 89 static void irm_exit(void) 90 { 91 free_irq(IRQ_EINT20, NULL); 92 } 93 94 module_init(irm_init); 95 module_exit(irm_exit); 96 MODULE_LICENSE("GPL");