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");

 

posted @ 2017-04-03 21:49  宁次  阅读(1964)  评论(0编辑  收藏  举报