Linux驱动开发-编写NEC红外线协议解码驱动

[摘要] NEC协议是众多红外协议之一,广泛应用于电视机和投影仪设备中。很久以前经常说的万能电视遥控器就是NEC协议。目前,本文介绍了如何在Linux下通过红外接收模块编写一个NEC协议的红外解码驱动程序,分析遥控器传来的各种控制指令,并完成相应的动作响应。驱动程序采用外部中断接收数据,定时器计算间隔时间完成解码。

1.红外知识点介绍光谱中波长在760nm到400um的电磁波称为红外线,是不可见光。目前几乎所有的视音频设备都可以用红外遥控器遥控,如电视机、空调、DVD播放机等。而且可以看到红外遥控的影子。这项技术的应用非常广泛,相应的应用设备也非常便宜,所以红外遥控是我们日常设备控制的理想方式。

红外遥控是应用最广泛的通讯和遥控手段。由于红外遥控装置具有体积小、功耗低、功能强、成本低等特点,所以继彩电、录像机之后,红外遥控还应用于录音机、音响设备、空调、玩具等其他小型电器设备。在工业设备中,在高电压、辐射、有毒气体和粉尘的环境中,红外遥控不仅完全可靠而且能有效隔离电气干扰。

NEC协议是众多红外协议之一,曾经广泛应用于电视机和投影仪设备。很久以前经常说的万能电视遥控器就是NEC协议。

目前,本文介绍了如何在Linux下通过红外接收模块编写一个NEC协议的红外解码驱动程序,分析遥控器传来的各种控制指令,并完成相应的动作响应。驱动程序采用外部中断接收数据,定时器计算间隔时间完成解码。

NEC协议的特点如下:

单个码分为五部分(不算重码):引导码用户码用户反码关键码关键反码。

对于receiver _ pilot码:低电平9ms,高电平4.5 ms

接收的数据为0: 560us低电平和560us高电平。

接收的数据是1: 560us低电平和1680us高电平。

2.硬件环境目前开发板采用友好arm的Tiny4412,CPU为三星的EXYNOS4412,最高主频1.5GHZ,Linux内核版本3.5。

以下是红外接收模块的原理图:

通过杜邦线连接到开发板的中断输入引脚:(GPX1_0接口,9号引脚排列。)

安装驱动程序后,解码的效果:

3.案例代码驱动的代码思路:使用外部中断接收NEC数据,在工作队列中完成协议分析,最后通过printk打印出来。

#包括#包括#包括#包括#包括#包括#包括#包括静态int IRQ # define NEC _ INFRARED _ GPIO exy nos 4 _ gpx 1(0)static struct work _ struct work;static u32 GetTimeH(void){ ktime _ t my _ time,my _ time 2;无符号int i,j;my _ time=ktime _ get();//获取当前时间i=ktime_to_us(我的_ time);//转us while(GPIO _ get _ value(NEC _ INFRARED _ GPIO)){ } my _ time 2=ktime _ get();//获取当前时间j=ktime _ to _ us(my _ time 2);//转美国返回j-I;}static u32 GetTimeL(void){ ktime _ t my _ time,my _ time 2;无符号int i,j;my _ time=ktime _ get();//获取当前时间i=ktime_to_us(我的_ time);//转us while(GPIO _ get _ value(NEC _红外线_ GPIO)==0){ } my _ time 2=k time _ get();//获取当前时间j=ktime _ to _ us(my _ time 2);//转美国返回j-I;}static u8 buf[4];//[0]用户码[1]用户反码[2]按键码[3]按键反码静态void new _ work _ func(struct work _ struct * work){ u8 data=0;u32 time _ ustime _ us=GetTimeL();if(time _ us 12000 | | time _ us 6000 | | time _ us 3000)返回;//标准4500int i,j;for(I=0;i4;I){ for(j=0;j700 || time_us 400)退货;//标准560 time _ us=GetTimeH();if(time_us400) //0:标准560 { data=1;}else if(time_us1500) //1:标准1680 { data=1;数据|=0x01}否则{返回;} } buf[I]=data;}printk('用户码:%d,按键码:%d\n 'buf[0],buf[2]);}IRQ return _ t nec _ IRQ _ handler _ func(int IRQ,void *dev){调度_工作(工作);返回IRQ _ HANDLED } static int _ _ init tiny 4412 _ hello _ module _ init(void){INIT_WORK(work,new _ WORK _ func);IRQ=GPIO _ to _ IRQ(NEC _红外线_ GPIO);request_irq(irq,nec_irq_handler_func,IRQF_TRIGGER_FALLING,' tinyy412_nec 'NULL);printk('驱动测试:驱动安装成功\ n’);返回0;}静态void _ _ exit tiny 4412 _ hello _ module _ clean up(void){ free _ IRQ(IRQ,NULL);printk('驱动测试:驱动卸载成功\ n’);}模块_初始化(tiny4412 _你好_模块_初始化);module _ exit(微小4412 _ hello _ module _ clean up);MODULE _ LICENSE(' GPL ');