首页 龙芯1B开发板一体化红外接收头+20键迷你红外遥控器驱动

龙芯1B开发板一体化红外接收头+20键迷你红外遥控器驱动

举报
开通vip

龙芯1B开发板一体化红外接收头+20键迷你红外遥控器驱动龙芯1B开发板一体化红外接收头+20键迷你红外遥控器驱动 1. 红外知识简介 .............................................................................................................................. 3 1.1. 怎么判断遥控板是否发射了红外命令(是否有电) .................................................. 3 1.2. 红外遥...

龙芯1B开发板一体化红外接收头+20键迷你红外遥控器驱动
龙芯1B开发板一体化红外接收头+20键迷你红外遥控器驱动 1. 红外知识简介 .............................................................................................................................. 3 1.1. 怎么判断遥控板是否发射了红外命令(是否有电) .................................................. 3 1.2. 红外遥控器是怎样解决干扰问 快递公司问题件快递公司问题件货款处理关于圆的周长面积重点题型关于解方程组的题及答案关于南海问题 的 .............................................................................. 3 2. 硬件简介...................................................................................................................................... 3 2.1. 一体化红外接收头 .......................................................................................................... 4 2.1.1. 一体化红外接收头在开发板上的位置 ................................................................ 4 2.1.2. 一体化红外接收头原理图 .................................................................................... 5 2.1.3. 一体化红外接收头原理 ........................................................................................ 7 2.2. 迷你20键38K红外遥控板 ........................................................................................... 7 2.2.1. 遥控器按键编码 关于同志近三年现实表现材料材料类招标技术评分表图表与交易pdf视力表打印pdf用图表说话 pdf ................................................................................................ 7 2.2.2. NEC编码分析 ........................................................................................................ 8 3. 源码分析...................................................................................................................................... 9 3.1. 主要思路 .......................................................................................................................... 9 3.2. 阻塞IO ........................................................................................................................... 10 3.3. 中断的上下半部 ............................................................................................................ 10 3.4. 内核定时器 .................................................................................................................... 11 4. 运行效果.................................................................................................................................... 12 4.1. 打开调试开关的效果 .................................................................................................... 12 4.2. 不打开调试开关的效果 ................................................................................................ 17 5. 源码清单.................................................................................................................................... 18 5.1. 驱动程序 ........................................................................................................................ 18 5.1.1. ls1b_ir.h ................................................................................................................. 18 5.1.2. ls1b_ir.c ................................................................................................................. 18 5.1.3. Platform.c .............................................................................................................. 29 5.2. 应用程序 ........................................................................................................................ 30 5.2.1. ls1b_ir_test_app.c.................................................................................................. 30 6. 参考文档.................................................................................................................................... 31 版本 更新日期 更新内容 V1.0 2014.4.5 创建 1. 红外知识简介 个人认为百度文库中的文档《全面了解红外遥控(中文版).pdf》讲得很好。我这里只是把要点提一下。 1.1. 怎么判断遥控板是否发射了红外命令(是否有电) 我们时常会碰到一个问题——到底遥控器还有电没有。对于电视遥控器可以取下电池看看,但是对于这里使用的迷你遥控器怎么办,使用的是锂电池。 办法是通过手机的摄像头看遥控器的红外发射管。当按下遥控器按键时,如果有电会发射红外命令,遥控器上的红外发射管会发出红外光,手机的摄像头能看到这种光。下图《全面了解红外遥控(中文版).pdf》为通过手机摄像头看遥控器的图片 1.2. 红外遥控器是怎样解决干扰问题的 只要有发热的物体都有红外光,问题是这么多红外光源,遥控器是怎样进行准确的传递信息的呢, 采取了两种措施:一、采用指定波长(940nm)的红外光;二、对940nm的红外光进行调制,调制到38Khz上。 虽然发出红外光的光源有很多,但是每个发出红外光的波长不一定一样,就算是都发出940nm的红外光,通常也没有什么规律,为了排除干扰能够进行准确的通信,遥控器还将940nm的红外光调制到38Khz上。 2. 硬件简介 说了这么久,还不知道开发板和遥控器到底是哪一款,来个合影吧。 注意:本驱动是针对图中所示的遥控器的驱动。 2.1. 一体化红外接收头 2.1.1.一体化红外接收头在开发板上的位置 先来看一下开发板上一体化红外接收头在哪里 位于电源和网口之间。 2.1.2.一体化红外接收头原理图 再来看看原理图中的一体化红外接收头的电路 由图可知,一体化红外接收头有3个引脚,分别为5v电源,地和信号输出引脚。 注意:原理图中信号输出引脚为GPIO60,这是原理图中的标注,实际上是龙芯1B处 理器的GPIO61,这点很重要。原理图中也有说明,如下图所示 2.1.3.一体化红外接收头原理 左边为遥控器发射的38khz的红外信号,右边为一体化红外接收头收到信号后,解调得到的信号。即没有38khz红外信号时,一体化红外接收头输出高电平;有38khz红外信号时,输出低电平。 2.2. 迷你20键38K红外遥控板 2.2.1.遥控器按键编码表 为了在linux驱动中能够正确解析遥控器的红外命令,并判断出具体是哪个按键被按下,必须知道遥控器按键编码。这里选择的这款遥控器的按键编码是已知的,如下图所示 注意:第一行中间那个(编码为46的)按键本遥控器没有。其它的编码都正确,详细请看后面的测试结果。 如果不幸没有这个编码表,只有通过示波器来找出每个按键的编码值了。 2.2.2.NEC编码分析 参考文档《全面了解红外遥控(中文版).pdf》中给出了NEC编码格式,如下图所示 针对这里使用的遥控器,对应的编码如下 其中address就是用户码0x00,按键编码为按键编码表中的值,比如“开关”按键的编码值为0x45,“menu”按键的编码值为0x47,“Test”按键的编码值为0x44,“倒退”按键的编码值为0x43等等。 驱动中要得到的就是按键编码。 上图中的逻辑‘1’和逻辑‘0’对应红外接收头信号引脚的高低电平,NEC编码规定:560us高电平+1690us低电平表示逻辑‘1’,560高电平+560低电平表示逻辑‘0’。如下图所示。 3. 源码分析 3.1. 主要思路 简单来说,应用程序执行read()函数,然后阻塞,直到有红外命令并解析后,驱动才将获取的“按键编码”返回给应用程序,应用程序的read()才返回。 获取按键编码的 方法 快递客服问题件处理详细方法山木方法pdf计算方法pdf华与华方法下载八字理论方法下载 是:一体化红外接收头在收到遥控器信号后,在信号输出引脚输出高低电平,并产生中断,中断程序中计算两次中断间隔的时间如果为2.25ms则表示逻辑‘1’,间隔时间为1.12ms则为逻辑‘0’,再转换为4字节的十六进制,其中第三字节为按键编码。 在实现上,为了实现快速中断,使用了tasklet机制。在中断程序中只记录了当前时间,就调用中断的下半部并返回了。在下半部中计算两次中断的时间间隔并保存起来。为了判断一条红外命令是否结束,这里采用了一个内核定时器,如果两次中断时间超过50ms,则认为一条红外命令已经结束。 这里没有考虑按键一直按住遥控器会在110ms发射重复码的情况,所以最长的间隔时间为引导码的9ms,即这里把定时器超时时间设置为50ms是合理的,经过实际测试也证明了这点。 3.2. 阻塞IO 在接收完一条红外命令后,应该唤醒驱动中的read()函数,并将解析结果返回给应用程序。这里采用的是wake_up_interruptible()和wait_event_interruptible()的形式,具体参考LDD3的第六章第二节Blocking I/O,相关原文截图如下 截图已经完整展示了wait_event()的使用方法。 3.3. 中断的上下半部 这里也按照规范把中断实现分为上半部和下半部。实现方式有tasklet和workqueue,这两种方式的区别是tasklet在软中断上下文中执行,很快,是以原子模式执行,但是workqueue可以休眠。LDD3中经典原文如下 Tasklet的使用方法也在LDD3中可以找到,如下所示 3.4. 内核定时器 同样,LDD3中也有内核定时器的相关介绍,如下所示。 4. 运行效果 4.1. 打开调试开关的效果 Freeing unused kernel memory: 184k freed Algorithmics/MIPS FPU Emulator v1.5 #mount all..... #Starting mdev..... Processing /etc/profile..... Done! [LOONSON@Loongson-gz:/]#echo 8 > /proc/sys/kernel/printk [LOONSON@Loongson-gz:/]#cd test/ [LOONSON@Loongson-gz:/test]#./ls1b_ir_test_app ----------one cmd--------- interval= 0, inteval_binary=2 interval= 13437, inteval_binary=2 interval= 1084, inteval_binary=0 interval= 1149, inteval_binary=0 interval= 1084, inteval_binary=0 interval= 1119, inteval_binary=0 interval= 1154, inteval_binary=0 interval= 1084, inteval_binary=0 interval= 1119, inteval_binary=0 interval= 1125, inteval_binary=0 interval= 2261, inteval_binary=1 interval= 2235, inteval_binary=1 interval= 2226, inteval_binary=1 interval= 2258, inteval_binary=1 interval= 2210, inteval_binary=1 interval= 2274, inteval_binary=1 interval= 2208, inteval_binary=1 interval= 2258, inteval_binary=1 interval= 2225, inteval_binary=1 interval= 1123, inteval_binary=0 interval= 2236, inteval_binary=1 interval= 1143, inteval_binary=0 interval= 1095, inteval_binary=0 interval= 1117, inteval_binary=0 interval= 2259, inteval_binary=1 interval= 1104, inteval_binary=0 interval= 1107, inteval_binary=0 interval= 2277, inteval_binary=1 interval= 1082, inteval_binary=0 interval= 2261, inteval_binary=1 interval= 2220, inteval_binary=1 interval= 2267, inteval_binary=1 interval= 1095, inteval_binary=0 interval= 2262, inteval_binary=1 interval= 40320, inteval_binary=2 interval= 11203, inteval_binary=2 ir cmd code= 0x0, 0xff, 0x45, 0xba ------------end------------- key = 0x45 ----------one cmd--------- interval= 0, inteval_binary=2 interval= 13422, inteval_binary=2 interval= 1092, inteval_binary=0 interval= 1153, inteval_binary=0 interval= 1081, inteval_binary=0 interval= 1119, inteval_binary=0 interval= 1123, inteval_binary=0 interval= 1144, inteval_binary=0 interval= 1097, inteval_binary=0 interval= 1121, inteval_binary=0 interval= 2246, inteval_binary=1 interval= 2225, inteval_binary=1 interval= 2281, inteval_binary=1 interval= 2204, inteval_binary=1 interval= 2259, inteval_binary=1 interval= 2246, inteval_binary=1 interval= 2209, inteval_binary=1 interval= 2263, inteval_binary=1 interval= 1099, inteval_binary=0 interval= 1120, inteval_binary=0 interval= 2267, inteval_binary=1 interval= 1097, inteval_binary=0 interval= 1106, inteval_binary=0 interval= 1154, inteval_binary=0 interval= 2204, inteval_binary=1 interval= 1154, inteval_binary=0 interval= 2207, inteval_binary=1 interval= 2274, inteval_binary=1 interval= 1084, inteval_binary=0 interval= 2243, inteval_binary=1 interval= 2265, inteval_binary=1 interval= 2235, inteval_binary=1 interval= 1100, inteval_binary=0 interval= 2228, inteval_binary=1 ir cmd code= 0x0, 0xff, 0x44, 0xbb ------------end------------- key = 0x44 ----------one cmd--------- interval= 0, inteval_binary=2 interval= 13435, inteval_binary=2 interval= 1082, inteval_binary=0 interval= 1104, inteval_binary=0 interval= 1156, inteval_binary=0 interval= 1098, inteval_binary=0 interval= 1101, inteval_binary=0 interval= 1125, inteval_binary=0 interval= 1157, inteval_binary=0 interval= 1082, inteval_binary=0 interval= 2273, inteval_binary=1 interval= 2211, inteval_binary=1 interval= 2258, inteval_binary=1 interval= 2226, inteval_binary=1 interval= 2254, inteval_binary=1 interval= 2209, inteval_binary=1 interval= 2279, inteval_binary=1 interval= 2204, inteval_binary=1 interval= 2259, inteval_binary=1 interval= 2254, inteval_binary=1 interval= 2206, inteval_binary=1 interval= 1123, inteval_binary=0 interval= 1140, inteval_binary=0 interval= 1097, inteval_binary=0 interval= 1120, inteval_binary=0 interval= 1140, inteval_binary=0 interval= 1100, inteval_binary=0 interval= 1122, inteval_binary=0 interval= 1106, inteval_binary=0 interval= 2263, inteval_binary=1 interval= 2258, inteval_binary=1 interval= 2199, inteval_binary=1 interval= 2278, inteval_binary=1 interval= 2204, inteval_binary=1 interval= 40346, inteval_binary=2 interval= 11205, inteval_binary=2 ir cmd code= 0x0, 0xff, 0x7, 0xf8 ------------end------------- key = 0x7 ----------one cmd--------- interval= 0, inteval_binary=2 interval= 13428, inteval_binary=2 interval= 1110, inteval_binary=0 interval= 1086, inteval_binary=0 interval= 1118, inteval_binary=0 interval= 1156, inteval_binary=0 interval= 1080, inteval_binary=0 interval= 1122, inteval_binary=0 interval= 1123, inteval_binary=0 interval= 1143, inteval_binary=0 interval= 2222, inteval_binary=1 interval= 2259, inteval_binary=1 interval= 2205, inteval_binary=1 interval= 2277, inteval_binary=1 interval= 2208, inteval_binary=1 interval= 2258, inteval_binary=1 interval= 2252, inteval_binary=1 interval= 2205, inteval_binary=1 interval= 1125, inteval_binary=0 interval= 2260, inteval_binary=1 interval= 2233, inteval_binary=1 interval= 1102, inteval_binary=0 interval= 2228, inteval_binary=1 interval= 1155, inteval_binary=0 interval= 1100, inteval_binary=0 interval= 1104, inteval_binary=0 interval= 2283, inteval_binary=1 interval= 1081, inteval_binary=0 interval= 1121, inteval_binary=0 interval= 2245, inteval_binary=1 interval= 1119, inteval_binary=0 interval= 2265, inteval_binary=1 interval= 2218, inteval_binary=1 interval= 2260, inteval_binary=1 interval= 40305, inteval_binary=2 interval= 11217, inteval_binary=2 ir cmd code= 0x0, 0xff, 0x16, 0xe9 ------------end------------- key = 0x16 ----------one cmd--------- interval= 0, inteval_binary=2 interval= 13420, inteval_binary=2 interval= 1093, inteval_binary=0 interval= 1102, inteval_binary=0 interval= 1157, inteval_binary=0 interval= 1098, inteval_binary=0 interval= 1104, inteval_binary=0 interval= 1125, inteval_binary=0 interval= 1154, inteval_binary=0 interval= 1084, inteval_binary=0 interval= 2245, inteval_binary=1 interval= 2250, inteval_binary=1 interval= 2254, inteval_binary=1 interval= 2218, inteval_binary=1 interval= 2243, inteval_binary=1 interval= 2222, inteval_binary=1 interval= 2284, inteval_binary=1 interval= 2204, inteval_binary=1 interval= 1149, inteval_binary=0 interval= 1084, inteval_binary=0 interval= 2277, inteval_binary=1 interval= 2204, inteval_binary=1 interval= 1120, inteval_binary=0 interval= 1139, inteval_binary=0 interval= 1102, inteval_binary=0 interval= 1118, inteval_binary=0 interval= 2262, inteval_binary=1 interval= 2205, inteval_binary=1 interval= 1155, inteval_binary=0 interval= 1099, inteval_binary=0 interval= 2230, inteval_binary=1 interval= 2260, inteval_binary=1 interval= 2254, inteval_binary=1 interval= 2209, inteval_binary=1 interval= 40339, inteval_binary=2 interval= 11196, inteval_binary=2 ir cmd code= 0x0, 0xff, 0xc, 0xf3 ------------end------------- key = 0xc 4.2. 不打开调试开关的效果 devtmpfs: mounted Freeing unused kernel memory: 184k freed Algorithmics/MIPS FPU Emulator v1.5 #mount all..... #Starting mdev..... Processing /etc/profile..... Done! [LOONSON@Loongson-gz:/]#/test/ls1b_ir_test_app key = 0x45 key = 0x44 key = 0x7 key = 0x16 key = 0xc key = 0x8 key = 0x42 key = 0x40 key = 0x15 key = 0x19 key = 0x18 key = 0x1c key = 0x52 key = 0x47 key = 0x43 key = 0x9 key = 0xd key = 0x5e key = 0x5a key = 0x4a ^C [LOONSON@Loongson-gz:/]# 5. 源码清单 5.1. 驱动程序 5.1.1.ls1b_ir.h #ifndef _LS1B_IR_H_ #define _LS1B_IR_H_ #endif 5.1.2.ls1b_ir.c #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "ls1b_ir.h" // 一体化红外接收头所在引脚 #define GPIO_IR 61 // 如果一个中断后一定时间还未发生中断,则认为一条红外命令已经结束 // 本驱动是针对20键迷你红外遥控器的, // 该款遥控器使用NEC 协议 离婚协议模板下载合伙人协议 下载渠道分销协议免费下载敬业协议下载授课协议下载 ,该遥控器最长的是9ms的引导码 // 暂不考虑重复码的情况 // 注意超时时间一定要加上jiffies #define LS1B_IR_ONE_CMD_TIME_OUT (jiffies+HZ/20) // 50ms // 阻塞IO DECLARE_WAIT_QUEUE_HEAD(ls1b_ir_wate_queue); // 中断下半部 void ls1b_ir_do_tasklet(unsigned long); DECLARE_TASKLET(ls1b_ir_tasklet, ls1b_ir_do_tasklet, 0); // 如果一个中断后一定时间还未发生中断,则认为一条红外命令已经结束 static struct timer_list ls1b_ir_one_cmd_timer; //static spinlock_t ls1b_ir_lock = SPIN_LOCK_UNLOCKED; static DEFINE_SPINLOCK(ls1b_ir_lock); static struct resource *ls1b_ir_res = NULL; static struct ls1b_board_intc_regs volatile *ls1b_board_int0_regs = (struct ls1b_board_intc_regs volatile *)(KSEG1ADDR(LS1B_BOARD_INTREG_BASE)); static unsigned int ls1b_ir_irq = 0; // 中断时间 static struct timeval ls1b_ir_current_tv = {0, 0}; // 最近一条中断发生的时间 static struct timeval ls1b_ir_last_tv = {0, 0}; // 倒数第二条中断发生的时间 // 一条红外命令的基本信息 #define LS1B_IR_ONE_CMD_MAX_INTERVAL_NUM (512) // 一条红外命令最大的中断次数 #define LS1B_IR_ONE_CMD_CODE_MAX_LEN (4) #define LS1B_IR_BIT_1_INTERVAL (2250) // 2.25ms左右为1 #define LS1B_IR_BIT_0_INTERVAL (1120) // 1.12ms左右为0 #define LS1B_IR_BIT_ERROR_SCOPE (200) // 0.2ms作为误差界限 #define LS1B_IR_BIT_1_INTERVAL_MIN (LS1B_IR_BIT_1_INTERVAL-LS1B_IR_BIT_ERROR_SCOPE) #define LS1B_IR_BIT_1_INTERVAL_MAX (LS1B_IR_BIT_1_INTERVAL+LS1B_IR_BIT_ERROR_SCOPE) #define LS1B_IR_BIT_0_INTERVAL_MIN (LS1B_IR_BIT_0_INTERVAL-LS1B_IR_BIT_ERROR_SCOPE) #define LS1B_IR_BIT_0_INTERVAL_MAX (LS1B_IR_BIT_0_INTERVAL+LS1B_IR_BIT_ERROR_SCOPE) // 与标准的2.25ms或1.12ms相比,超过0.2ms则为非法值 typedef enum { LS1B_IR_BIT_0 = 0, // 对应的间隔时间为2.05ms到2.45ms LS1B_IR_BIT_1 = 1, // 对应的间隔时间为0.92ms到1.32ms LS1B_IR_BIT_INVALID = 2, // 不在以上两个范围内的所有间隔时间 }LS1B_IR_BIT_VALUE_ENUM; // 每次间隔在一条红外命令码中的具体含义 // 本20键38k迷你红外遥控器采用的是NEC编码 // 具体编码规则为1bit引导码+2byte用户码(固定为0x00ff)+1byte命令码+1byte命令反码 typedef enum { // 缓存中的第一个间隔固定为0 LS1B_IR_BIT_USER_CODE_BYTE_0 = 0, // 1bit引导码 LS1B_IR_BIT_USER_CODE_BYTE_1, // 2byte的用户码(固定为0x00ff) LS1B_IR_BIT_CMD_CODE, // 1byte命令码 LS1B_IR_BIT_CMD_OPPOSITE_CODE, // 1byte命令码反码 }LS1B_IR_BIT_CODE_ENUM; typedef struct { // 相邻中断的间隔 unsigned int inteval[LS1B_IR_ONE_CMD_MAX_INTERVAL_NUM]; // 根据间隔长度,转换为具体的0或者1 // 2.25ms左右,则为1;1.12ms左右则为0 unsigned char inteval_binary[LS1B_IR_ONE_CMD_MAX_INTERVAL_NUM]; // 十六进制的编码值,由inteval_binary转换得到 unsigned char code[LS1B_IR_ONE_CMD_CODE_MAX_LEN]; unsigned int interval_num; // 有效间隔的总个数 }LS1B_IR_ONE_CMD_STRU; LS1B_IR_ONE_CMD_STRU ls1b_ir_cmd_buff; // 接收完一条红外命令 typedef enum { LS1B_IR_ONE_CMD_RECEIVE_OK = 0, LS1B_IR_ONE_CMD_RECEIVE_NOT_OK = 1, }LS1B_IR_ONE_CMD_RECEIVE_ENUM; static int ls1b_ir_one_cmd_received_ok_flag = LS1B_IR_ONE_CMD_RECEIVE_NOT_OK; // 一条红外命令的第一次中断标志 typedef enum { LS1B_IR_ONE_CMD_FIRST_INTR_INIT = 0, LS1B_IR_ONE_CMD_FIRST_INTR_TRUE = 1, LS1B_IR_ONE_CMD_FIRST_INTR_FALSE = 2, }LS1B_IR_ONE_CMD_FIRST_INTR_FLAG; static int ls1b_ir_one_cmd_first_flag = LS1B_IR_ONE_CMD_FIRST_INTR_INIT; void ls1b_ir_one_cmd_timer_stop(void); // 初始化定时器 void ls1b_ir_one_cmd_timer_init(void) { init_timer(&ls1b_ir_one_cmd_timer); } // 定时器超时处理器函数 void ls1b_ir_one_cmd_timer_handler(unsigned long data) { // 停止定时器 ls1b_ir_one_cmd_timer_stop(); // 重置标志 ls1b_ir_one_cmd_first_flag = LS1B_IR_ONE_CMD_FIRST_INTR_INIT; // 唤醒read()函数 ls1b_ir_one_cmd_received_ok_flag = LS1B_IR_ONE_CMD_RECEIVE_OK; wake_up_interruptible(&ls1b_ir_wate_queue); return ; } // 启动定时器 void ls1b_ir_one_cmd_timer_start(void) { ls1b_ir_one_cmd_timer.function = ls1b_ir_one_cmd_timer_handler; ls1b_ir_one_cmd_timer.expires = LS1B_IR_ONE_CMD_TIME_OUT; add_timer(&ls1b_ir_one_cmd_timer); return ; } // 重启定时器 void ls1b_ir_one_cmd_timer_restart(void) { mod_timer(&ls1b_ir_one_cmd_timer, LS1B_IR_ONE_CMD_TIME_OUT); } // 停止定时器 void ls1b_ir_one_cmd_timer_stop(void) { del_timer(&ls1b_ir_one_cmd_timer); } // 红外命令缓存初始化 void ls1b_ir_cmd_buff_init(void) { memset(&ls1b_ir_cmd_buff, 0, sizeof(ls1b_ir_cmd_buff)); return ; } // 追加一个间隔到缓存中 void ls1b_ir_cmd_buff_append_interval(unsigned int interval) { unsigned int index = ls1b_ir_cmd_buff.interval_num; // 判断缓存是否已满 if (LS1B_IR_ONE_CMD_MAX_INTERVAL_NUM <= index) { printk(KERN_DEBUG "%s: ir cmd buff is full\n", __FUNCTION__); return ; } // 保存数据 ls1b_ir_cmd_buff.inteval[index] = interval; ls1b_ir_cmd_buff.interval_num++; return ; } // 根据红外命令的间隔时间,获取其编码值 void ls1b_ir_cmd_buff_code(void) { unsigned int interval_num = ls1b_ir_cmd_buff.interval_num; unsigned int interval = 0; unsigned int index = 0; unsigned char interval_binary = 0; unsigned char code = 0; unsigned char tmp = 0; int i, j; // 将红外命令的时间间隔转换为具体的0或者1 // 2.25ms左右,则为1;1.12ms左右则为0 for (index=0; index= interval)) { interval_binary = LS1B_IR_BIT_1; } else if ((LS1B_IR_BIT_0_INTERVAL_MIN <= interval) && (LS1B_IR_BIT_0_INTERVAL_MAX >= interval)) { interval_binary = LS1B_IR_BIT_0; } else { interval_binary = LS1B_IR_BIT_INVALID; } ls1b_ir_cmd_buff.inteval_binary[index] = interval_binary; } // 本20键38k迷你红外遥控器采用的是NEC编码 // 具体编码规则为1bit引导码+2byte用户码(固定为0x00ff)+1byte命令码+1byte命令反 码 index=2; // 缓存中,第0位间隔固定为0,第1位为引导码,所 以从第三位开始 for (i=0; i<4; i++) // 4字节=2字节用户码+1字节命令码+1字节命令反码 { // 将每8位转换为1字节 code = 0; for (j=0; j<8; j++) // 1字节 { tmp = ls1b_ir_cmd_buff.inteval_binary[index]; index++; tmp = tmp << j; code = code | tmp; // printk(KERN_DEBUG "%s: tmp=0x%x, code=0x%x\n", __FUNCTION__, tmp, code); } // 保存每字节 ls1b_ir_cmd_buff.code[i] = code; } return ; } // 获取按键编码,即红外命令码 unsigned char ls1b_ir_get_key_code(void) { // 具体编码规则为1bit引导码+2byte用户码(固定为0x00ff)+1byte命令码+1byte命令反 码 return ls1b_ir_cmd_buff.code[LS1B_IR_BIT_CMD_CODE]; } // 打印缓存中的红外命令信息 void ls1b_ir_cmd_buff_print(void) { unsigned int interval_num = ls1b_ir_cmd_buff.interval_num; unsigned int index = 0; printk(KERN_DEBUG "\n----------one cmd---------\n"); for (index=0; index> (GPIO_IR - 32)) & 0x01); return ret; } static void ls1b_ir_irq_enable(void) { unsigned int ret; unsigned long flag; spin_lock(&ls1b_ir_lock); local_irq_save(flag); ret = *(volatile unsigned int *)(KSEG1ADDR(REG_GPIO_CFG1)); ret |= (1 << (GPIO_IR - 32)); *(volatile unsigned int *)(KSEG1ADDR(REG_GPIO_CFG1)) = ret; ret = *(volatile unsigned int *)(KSEG1ADDR(REG_GPIO_OE1)); ret |= (1 << (GPIO_IR - 32)); *(volatile unsigned int *)(KSEG1ADDR(REG_GPIO_OE1)) = ret; (ls1b_board_int0_regs + 3) -> int_edge |= (1 << (GPIO_IR - 32)); (ls1b_board_int0_regs + 3) -> int_pol &= ~(1 << (GPIO_IR - 32)); (ls1b_board_int0_regs + 3) -> int_clr |= (1 << (GPIO_IR - 32)); (ls1b_board_int0_regs + 3) -> int_set &= ~(1 << (GPIO_IR - 32)); (ls1b_board_int0_regs + 3) -> int_en |= (1 << (GPIO_IR - 32)); local_irq_restore(flag); spin_unlock(&ls1b_ir_lock); } // 中断程序下半部 void ls1b_ir_do_tasklet(unsigned long unused) { unsigned int interval = 0; // 计算两次中断间隔 if (ls1b_ir_current_tv.tv_sec == ls1b_ir_last_tv.tv_sec) { interval = ls1b_ir_current_tv.tv_usec - ls1b_ir_last_tv.tv_usec; } else { interval = 1000000 - ls1b_ir_last_tv.tv_usec + ls1b_ir_current_tv.tv_usec; } // 判断是否为第一次中断 if (LS1B_IR_ONE_CMD_FIRST_INTR_INIT == ls1b_ir_one_cmd_first_flag) { // 是第一次中断,则启动定时器 ls1b_ir_one_cmd_first_flag = LS1B_IR_ONE_CMD_FIRST_INTR_TRUE; ls1b_ir_one_cmd_timer_start(); interval = 0; // 规定第一次中断间隔为0 } else { // 不是第一次中断,则重启定时器 ls1b_ir_one_cmd_timer_restart(); } // 保存间隔时间 ls1b_ir_cmd_buff_append_interval(interval); // 更新 ls1b_ir_last_tv = ls1b_ir_current_tv; return ; } // 中断程序(上半部) static irqreturn_t ls1b_ir_irq_handler(int i, void *blah) { /* udelay(50); if (ls1b_ir_pinstate() != 0) return IRQ_HANDLED; */ // 获取当前时间 do_gettimeofday(&ls1b_ir_current_tv); // 调用下半部 tasklet_schedule(&ls1b_ir_tasklet); // 清中断标志 (ls1b_board_int0_regs + 3) -> int_clr |= (1 << (GPIO_IR - 32)); // 返回 return (IRQ_HANDLED); } static ssize_t ls1b_ir_read(struct file *filp, char __user *buf, size_t count, loff_t *offp) { unsigned char key_code = 0; // 等待红外命令到来,并且接收完成 wait_event_interruptible(ls1b_ir_wate_queue, LS1B_IR_ONE_CMD_RECEIVE_OK==ls1b_ir_one_cmd_received_ok_flag); ls1b_ir_one_cmd_received_ok_flag = LS1B_IR_ONE_CMD_RECEIVE_NOT_OK; // 解析红外命令 ls1b_ir_cmd_buff_code(); // 打印详细的红外命令信息 ls1b_ir_cmd_buff_print(); // 获取按键编码 key_code = ls1b_ir_get_key_code(); if (copy_to_user(buf, &key_code, sizeof(key_code))) { printk(KERN_DEBUG "%s:ls1b_ir_read error!\n", __FUNCTION__); return -EFAULT; } // 重新初始化缓存 ls1b_ir_cmd_buff_init(); return sizeof(unsigned char); } static int ls1b_ir_open(struct inode *inode, struct file *filep) { int ret; // 初始化变量 ls1b_ir_one_cmd_received_ok_flag = LS1B_IR_ONE_CMD_RECEIVE_NOT_OK; ls1b_ir_one_cmd_first_flag = LS1B_IR_ONE_CMD_FIRST_INTR_INIT; ls1b_ir_cmd_buff_init(); // 初始化定时器 ls1b_ir_one_cmd_timer_init(); // ir中断使能 ls1b_ir_irq_enable(); ret = request_irq(ls1b_ir_irq, ls1b_ir_irq_handler, IRQF_DISABLED, "ls1b_ir", NULL); if (ret) { printk("IR:ir_irq_handler resigered Error:%d\n", ret); return ret; } return 0; } static int ls1b_ir_close(struct inode *inode, struct file *filp) { free_irq(ls1b_ir_irq, NULL); return 0; } static const struct file_operations ls1b_ir_ops = { .owner = THIS_MODULE, .open = ls1b_ir_open, .release = ls1b_ir_close, .read = ls1b_ir_read, }; static struct miscdevice ls1b_ir_miscdev = { MISC_DYNAMIC_MINOR, "ls1b_ir", &ls1b_ir_ops, }; static int __devinit ls1b_ir_probe(struct platform_device *pdev) { ls1b_ir_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); ls1b_ir_irq = ls1b_ir_res->start; return 0; } static struct platform_driver ls1b_ir_driver = { .probe = ls1b_ir_probe, .driver = { .name = "ls1b_ir", }, }; static int __init ls1b_ir_init(void) { if (misc_register(&ls1b_ir_miscdev)) { printk(KERN_WARNING "IR: Couldn't register device!\n "); return -EBUSY; } return platform_driver_register(&ls1b_ir_driver); } static void __exit ls1b_ir_exit(void) { free_irq(ls1b_ir_irq,NULL); misc_deregister(&ls1b_ir_miscdev); platform_driver_unregister(&ls1b_ir_driver); } MODULE_AUTHOR("zhuangweilin-gz@loongson.cn"); MODULE_DESCRIPTION("Infrared remote receiver driver for the ls1b."); module_init(ls1b_ir_init); module_exit(ls1b_ir_exit); MODULE_LICENSE("GPL"); 5.1.3.Platform.c 没有任何改动 5.2. 应用程序 5.2.1.ls1b_ir_test_app.c // 龙芯1B开发板上的一体化红外接收头的测试程序 // 本测试程序是通过解析20键迷你红外遥控器的红外命令来判断具体是哪个按键被按下 #include #include #include #include int main(void) { int fd = 0; unsigned char key = 0; int ret = 0; // 打开设备文件 fd = open("/dev/ls1b_ir", O_RDWR); if (-1 == fd) { printf("open /dev/ls1b_ir fail.\n"); return fd; } while (1) { key = 0; // 等待红外命令,并从驱动获取具体是哪个按键被按下 ret = read(fd, &key, sizeof(char)); if (sizeof(char) > ret) { printf("read error, ret=%d\n", ret); close(fd); return ret; } printf("key = 0x%x\n", key); } close(fd); return 0; } 6. 参考文档 百度文库 《全面了解红外遥控(中文版).pdf》 百度文库 《21键遥控器规格 关于书的成语关于读书的排比句社区图书漂流公约怎么写关于读书的小报汉书pdf .pdf》
本文档为【龙芯1B开发板一体化红外接收头+20键迷你红外遥控器驱动】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
该文档来自用户分享,如有侵权行为请发邮件ishare@vip.sina.com联系网站客服,我们会及时删除。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。
本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。
网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
下载需要: 免费 已有0 人下载
最新资料
资料动态
专题动态
is_358746
暂无简介~
格式:doc
大小:328KB
软件:Word
页数:37
分类:企业经营
上传时间:2017-10-16
浏览量:27