若要在android中使用还有诸多问题,比如:android平台中有较多的中断会导致延时的误差很大,因此我有做改进,通过实验证实是很可靠的。
思路:用户空间:获取GPIO驱动设备句柄,将要发送的IR CODE write到dev中;
内核空间:利用内核中现有的GPIO驱动输出高低电平,使用内核软中断防止模拟时序时被中断导致延时误差大;GPIO设备读取数据后引发软中断产生模拟IR。
代码:
1. .h文件中的数据结构以及宏定义
struct IR_CODE { U16 uHead; U8 uScancode; U8 bOutreverse; }; typedef struct GPIO_Reg GPIO_Reg_t; typedef struct IR_CODE IR_CODE_t; //add by yanxi for ir out start 140117 #define IR_HEAD0 0 #define IR_HEAD1 1 #define IR_TIME_BASE 2 #define IR_CODE_0 3 #define IR_CODE_1 4 #define IR_CODE_END 5 //38k = 26.315us #define TIMER_9000US 342 #define TIMER_4500US 171 #define TIMER_560US 21 #define TIMER_1680US 63 //add by yanxi for ir out end 140117
2.当用户空间写数据到设备节点时, _MDrv_GPIO_Write被执行,通过copy_from_user 获取IR数据,并使用_MDrv_GPIO_SendIR发送IR
static ssize_t _MDrv_GPIO_Write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos) { IR_CODE_t mIR_CODE_t; GPIO_PRINT("%s is invoked\n", __FUNCTION__); copy_from_user(&mIR_CODE_t, (IR_CODE_t __user *) buf, sizeof(IR_CODE_t)); printk("\n yanxidebug uHead:%x uScancode:%x bOutreverse:%d",mIR_CODE_t.uHead,mIR_CODE_t.uScancode,mIR_CODE_t.bOutreverse); _MDrv_GPIO_SendIR((unsigned int)mIR_CODE_t.uHead,(unsigned int)mIR_CODE_t.uScancode,(BOOL)mIR_CODE_t.bOutreverse); return 0; }
3、主要是通过raise_softirq使能软中断
static void _MDrv_GPIO_SendIR(unsigned int Head, int scancode, BOOL bOutreverse) { GPIO_PRINT("\n %s Head:%d scancode:%d bOutreverse:%d\n", __FUNCTION__,Head,scancode,bOutreverse); mHead = Head; mscancode = scancode; mbOutreverse = bOutreverse; raise_softirq(SENDIR_SOFTIRQ); }
4、中断处理函数,依据mscancode发送IR
int irq_handle_function(int irq, void *device_id) { GPIO_PRINT("\n %s \n", __FUNCTION__); S8 TranselateBitPos; U8 Ir_trans_sta; int mcount = 0; unsigned int head = 0x007f; U8 head0 = head >> 8; U8 head1 = head &0x00ff; U16 mkeycode = mscancode; BOOL outreverse = true; //init state Ir_trans_sta=IR_HEAD0; TranselateBitPos=32; //send ir code while(TranselateBitPos>=0) { mcount = 0; switch(Ir_trans_sta) { case IR_HEAD0: Ir_trans_sta= IR_HEAD1; if(outreverse) { mcount = TIMER_9000US; } else { MHal_GPIO_Set_Low(0); mdelay(9); } break; case IR_HEAD1: Ir_trans_sta= IR_TIME_BASE; if(!outreverse)//outreverse true { mcount = TIMER_4500US;//output high ;38k } else { MHal_GPIO_Set_High(0);//outreverse false,low vol mdelay(4); udelay(500); } break; case IR_TIME_BASE: if(TranselateBitPos>24) { if( ((head0>>(32-TranselateBitPos)) & 0x1) == 0x1 ) Ir_trans_sta= IR_CODE_1; else Ir_trans_sta= IR_CODE_0; } else if(TranselateBitPos>16) { if( ((head1>>(24-TranselateBitPos)) & 0x1) == 0x1 ) Ir_trans_sta= IR_CODE_1; else Ir_trans_sta= IR_CODE_0; } else if(TranselateBitPos>8) { if( ((mkeycode>>(16-TranselateBitPos))&0x1) == 0x1 ){ Ir_trans_sta= IR_CODE_1; } else { Ir_trans_sta= IR_CODE_0; } } else if(TranselateBitPos>0) { if( ((mkeycode>>(8-TranselateBitPos))&0x1) == 0x1 ) Ir_trans_sta= IR_CODE_0; else Ir_trans_sta= IR_CODE_1; } else { Ir_trans_sta= IR_CODE_END; } if(!outreverse) { MHal_GPIO_Set_Low(0); udelay(560); } else { mcount = TIMER_560US; } break; case IR_CODE_0: Ir_trans_sta= IR_TIME_BASE; if(outreverse) { MHal_GPIO_Set_Low(0); udelay(500); } else { mcount = TIMER_560US; } TranselateBitPos--; break; case IR_CODE_1: Ir_trans_sta= IR_TIME_BASE; if(outreverse) { MHal_GPIO_Set_Low(0); udelay(1680); } else { mcount = TIMER_1680US; } TranselateBitPos--; break; case IR_CODE_END: Ir_trans_sta= IR_HEAD0; MHal_GPIO_Set_High(0); TranselateBitPos=-1;//force to exit. break; default:break; } //38k generate while(mcount-- > 0){ MHal_GPIO_Set_High(0); MHal_GPIO_Set_High(0); MHal_GPIO_Set_High(0); MHal_GPIO_Set_High(0); udelay(11); MHal_GPIO_Set_Low(0); MHal_GPIO_Set_Low(0); MHal_GPIO_Set_Low(0); MHal_GPIO_Set_Low(0); udelay(11); } } return IRQ_NONE; } 完...