OK210开发板使用感想续之亲自设计红外驱动
经过几天的研究,终于把OK210开发板wince红外驱动的部分给完成了。
开发工具:vs2005,飞凌官方OK210开发板,杜邦线3根,烙铁一把,焊锡,4.7k电阻一个。
开发软件:Win CE 6.0
下图是所需的开发工具
从网上找了好久,不是不能用,就是骗子代码,根本不能用,最可气的就是挂羊头卖狗肉,标着红外驱动,用自己宝贵的积分,下载下来一看根本就不是,浪费了我很多时间,最后没办法只能自己动手了,这里充分体现了毛主席“自己动手,丰衣足食”这句话的重要性。好了废话不多说吧我自己的这几天的思路告诉大家让大家以后少走弯路,在这里我也希望广大网友能够不吝惜自己的劳动成果,把自己的奋斗果实奉献下,这样能让很多网友少走弯路,大家庆幸之余也会非常感激”挖井人“的。首先,我是按照单片机解码的思路,开始制作的Win CE操作系统的红外驱动,可把我害苦了。我用的是中断+定时器。思路呢和网上所有的都一样,但是总是卡死在定时器上,定时器我用的是微秒级别的延时,这样已进入系统,总是不停地去响应定时器的中断,这样就卡死在线程了。系统连起都起不来了,害的我倒腾了好几天,最后没办法只能放弃了,改用延时,网上有现成的函数。解码的遥控器类型有很多,这里我只做了最通用的NEC遥控器,其他的只需要改一下高低电平时间就行了。NEC红外协议,作为接收端来讲,首先是引导码,有9ms的低电平,然后是4.5ms的高电平,然后是32位的操作码,对于按键来说我们只需要解第三组就可以了,其他的NEC协议的知识可以从网上搜索下有很多的。现在只做红外接收模块,将准备好的杜邦线插在红外的三个引脚上,引脚顺序,大家从网上搜索下,然后就是找一个直插的4.7k上拉电阻,接到hs0038的接受引脚和5v引脚中间。由于我的红外解码思路是中断所以只能找中断引脚了,但是通篇的找飞凌OK210开发板上中断引脚真的是太难找了,(⊙o⊙)最后没办法只能找已经引出的引脚了,最后发现按键上每个引脚都能用,都是中断引脚,最后我选择了外部中断6,开发板的k4按键,将按键的上拉电阻去掉,然后焊接出一条引线,接到红外接收器的接收引脚。下面是自己焊的红外接收模块。
好了硬件准备完毕,现在开始写驱动。1.包含的头文件://made in 2013-6-7 by mr wang #include "stdafx.h"#include <windows.h>#include <ceddk.h>#include <nkintr.h>#include <pm.h>#include <drvmsg.h>#include <drvlib_mem.h>#include "pmplatform.h"#include "Pkfuncs.h"#include <types.h>#include <bsp.h>#include "gpioentry_reg.h"#include <assert.h>typedef enum{ EINT_SIGNAL_LOW_LEVEL = 0, EINT_SIGNAL_HIGH_LEVEL, EINT_SIGNAL_FALL_EDGE, EINT_SIGNAL_RISE_EDGE, EINT_SIGNAL_BOTH_EDGE}EINT_SIGNAL_METHOD; typedef enum{ EINT_FILTER_DISABLE = 0, EINT_FILTER_DELAY, EINT_FILTER_DIGITAL}EINT_FILTER_METHOD; static volatile GPIO_REG* g_pGPIOReg = NULL;static DWORD g_dwSysIntrHS38= SYSINTR_UNDEFINED;static HANDLE g_hEventHS38= NULL;static HANDLE g_hEventResetBtn= NULL;static HANDLE g_hThreadHS38= NULL;static BOOL g_bExitThread= FALSE;static BOOL pwstatus=TRUE; void Delay_us(int n);//延时usBOOLIRS_date(void);//判断遥控低电平static void InitInterrupt(void);//中断初始化void IRS_port_init(void); //引脚初始化void IRS_enable_interrupt(void);//使能中断void IRS_disable_interrupt(void);//不使能中断void IRS_clear_interrupt_pending(void);//清楚中断屏蔽位BOOLIRS_set_filter_method(EINT_FILTER_METHOD eMethod, unsignedint uiFilterWidth);//选择中断的filter方式BOOLIRS_set_interrupt_method(EINT_SIGNAL_METHOD eMethod);//设置中断方式2.解码线程:INTWINAPI HS38Thread(void){ int i,j; byte ircode[4];//四位编码 while(!g_bExitThread) { WaitForSingleObject(g_hEventHS38,INFINITE); if(g_bExitThread) { break; } IRS_disable_interrupt(); // 禁止中断 IRS_clear_interrupt_pending(); // 清除中断标志位 InterruptDone(g_dwSysIntrHS38); //中断完成,开始解码 Delay_us(8000);//延时掉ms的低电平, while(IRS_date()); Delay_us(4000);//4.5ms高电平 while(!IRS_date()); for(j=0;j<4;j++) { for(i=0;i<8;i++) { while(IRS_date()); Delay_us(700); if(IRS_date())// send 0 { ircode[j]=ircode[j]>>1; } else { ircode[j]=ircode[j]|0x80; ircode[j]=ircode[j]>>1; Delay_us(1200); } } } Sleep(100); RETAILMSG(1,(TEXT("******* ircode[3] = %x\r\n"),ircode[3]));//打印第三组操作码,便是按键的键码 IRS_enable_interrupt(); } return 0;}3.微妙延时函数void Delay_us(int n){ LARGE_INTEGER litmp; LONGLONG QPart1,QPart2; doubledfMinus, dfFreq, dfTim; if(QueryPerformanceFrequency(&litmp)==FALSE) { return; } dfFreq = (double)litmp.QuadPart; QueryPerformanceCounter(&litmp); QPart1 = litmp.QuadPart; do { QueryPerformanceCounter(&litmp); QPart2=litmp.QuadPart; dfMinus=(double)(QPart2-QPart1); dfTim=dfMinus/dfFreq; }while(dfTim<0.000001*n); }4.其他流驱动接口函数//设置寄存器地址BOOLHS38_initialize_register_address(void*pGPIOReg)//,void *pHSReg){ if(pGPIOReg == NULL) { returnFALSE; } else { g_pGPIOReg = (GPIO_REG *)pGPIOReg; } returnTRUE;}//初始化void IRS_port_init(void){ Set_PinFunction(g_pGPIOReg,GPH06_EXT_INT_6); Set_PinPullUD(g_pGPIOReg,GPH06_EXT_INT_6, sgip_PULL_UP); } //使能引脚中断void IRS_enable_interrupt(void){ Unmask_EXTINT(g_pGPIOReg, EXT_INT_6);} //禁止引脚中断void IRS_disable_interrupt(void){ Mask_EXTINT(g_pGPIOReg, EXT_INT_6); } //清除引脚中断void IRS_clear_interrupt_pending(void){ Clear_EXTINT(g_pGPIOReg, EXT_INT_6); } //设置中断方式BOOLIRS_set_interrupt_method(EINT_SIGNAL_METHOD eMethod){ BOOL Ret = TRUE; switch(eMethod) { caseEINT_SIGNAL_LOW_LEVEL: Set_EXTINT_TRLVL(g_pGPIOReg,EXT_INT_6, sgip_LOW_LEVEL); break; caseEINT_SIGNAL_HIGH_LEVEL: Set_EXTINT_TRLVL(g_pGPIOReg,EXT_INT_6, sgip_HIGH_LEVEL); break; caseEINT_SIGNAL_FALL_EDGE: Set_EXTINT_TRLVL(g_pGPIOReg,EXT_INT_6, sgip_FALLING_EDGE); break; caseEINT_SIGNAL_RISE_EDGE: Set_EXTINT_TRLVL(g_pGPIOReg,EXT_INT_6, sgip_RISING_EDGE); break; caseEINT_SIGNAL_BOTH_EDGE: Set_EXTINT_TRLVL(g_pGPIOReg,EXT_INT_6, sgip_BOTH_EDGE); break; default: Ret = FALSE; break; } returnRet;} //设置中断filter方式BOOLIRS_set_filter_method(EINT_FILTER_METHOD eMethod, unsignedint uiFilterWidth){ BOOL Ret =TRUE; switch(eMethod) { caseEINT_FILTER_DISABLE: Clr_EXTINT_FILTER(g_pGPIOReg,EXT_INT_6); break; caseEINT_FILTER_DELAY: Set_EXTINT_FILTER(g_pGPIOReg,EXT_INT_6, sgip_DELAY_FLT, 0); break; caseEINT_FILTER_DIGITAL: Set_EXTINT_FILTER(g_pGPIOReg,EXT_INT_6, sgip_DIGITAL_FLT, uiFilterWidth); break; default: Ret = FALSE; break; } returnRet;} //判断遥控接收引脚低电平,返回trueBOOLIRS_date(void){ if(Get_PinData(g_pGPIOReg,GPH06_EXT_INT_6)) { returnFALSE; // LowActive Switch (Pull-up switch) } else { returnTRUE; }} static BOOL AllocResources(void){ DWORD dwIRQ; PHYSICAL_ADDRESS ioPhysicalBase = {0,0}; //------------------ // GPIOController SFR //------------------ ioPhysicalBase.LowPart =BASE_REG_PA_GPIO; g_pGPIOReg = (GPIO_REG*)MmMapIoSpace(ioPhysicalBase, sizeof(GPIO_REG),FALSE); if(g_pGPIOReg == NULL) { returnFALSE; } dwIRQ = IRQ_EINT6; g_dwSysIntrHS38 = SYSINTR_UNDEFINED; g_hEventHS38 = NULL; if(!KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &dwIRQ, sizeof(DWORD), &g_dwSysIntrHS38, sizeof(DWORD), NULL)) { g_dwSysIntrHS38 =SYSINTR_UNDEFINED; returnFALSE; } g_hEventHS38 = CreateEvent(NULL, FALSE,FALSE, NULL); if(NULL== g_hEventHS38) { returnFALSE; } if(!(InterruptInitialize(g_dwSysIntrHS38, g_hEventHS38, 0, 0))) { returnFALSE; } returnTRUE;}static voidReleaseResources(void){ if(g_pGPIOReg != NULL) { MmUnmapIoSpace((PVOID)g_pGPIOReg, sizeof(GPIO_REG)); g_pGPIOReg = NULL; } if(g_dwSysIntrHS38 != SYSINTR_UNDEFINED) { InterruptDisable(g_dwSysIntrHS38); } if(g_hEventHS38 != NULL) { CloseHandle(g_hEventHS38); } if(g_dwSysIntrHS38 != SYSINTR_UNDEFINED) { KernelIoControl(IOCTL_HAL_RELEASE_SYSINTR,&g_dwSysIntrHS38, sizeof(DWORD), NULL, 0,NULL); } g_pGPIOReg = NULL; g_dwSysIntrHS38 = SYSINTR_UNDEFINED; g_hEventHS38 = NULL; } static void InitInterrupt(void){ // 禁止中断 IRS_disable_interrupt(); // I初始化端口 IRS_port_init(); // 设置中断模式 IRS_set_interrupt_method(EINT_SIGNAL_BOTH_EDGE); IRS_set_filter_method(EINT_FILTER_DELAY,0); // 清除中断标志位 IRS_clear_interrupt_pending(); // 使能中断 IRS_enable_interrupt();} BOOLWINAPI DllEntry(HANDLE hinstDLL, DWORD dwReason, LPVOID /* lpvReserved */){ switch(dwReason) { caseDLL_PROCESS_ATTACH: DEBUGREGISTER((HINSTANCE)hinstDLL); returnTRUE; caseDLL_THREAD_ATTACH: break; caseDLL_THREAD_DETACH: break; caseDLL_PROCESS_DETACH: break;#ifdef UNDER_CE caseDLL_PROCESS_EXITING: break; caseDLL_SYSTEM_STARTED: break;#endif } returnTRUE;} BOOLIRS_Deinit(DWORD hDeviceContext){ g_bExitThread = TRUE; if(g_hThreadHS38) // Make Sure if thread is exist { IRS_disable_interrupt(); IRS_clear_interrupt_pending(); //Signal Thread to Finish SetEvent(g_hEventHS38); // Waitfor Thread to Finish WaitForSingleObject(g_hThreadHS38,INFINITE); CloseHandle(g_hThreadHS38); g_hThreadHS38 = NULL; } ReleaseResources(); //RETAILMSG(1,(TEXT("USERLED:IRS_Deinit\r\n"))); returnTRUE;} DWORDIRS_Init(DWORD dwContext){ RETAILMSG(1,(TEXT("Key_Gpio_Setting----\r\n"))); if(AllocResources() == FALSE) { gotoCleanUp; } HS38_initialize_register_address((void *)g_pGPIOReg); InitInterrupt(); g_hThreadHS38 = CreateThread(NULL, 0,(LPTHREAD_START_ROUTINE) HS38Thread, NULL, 0, NULL); if(g_hThreadHS38 == NULL ) { gotoCleanUp; } returnTRUE; CleanUp: IRS_Deinit(0); returnFALSE;} //-----------------------------------------------------------------------------//-----------------------------------------------------------------------------BOOLIRS_IOControl(DWORD hOpenContext, DWORD dwCode, PBYTE pBufIn, DWORD dwLenIn, PBYTE pBufOut, DWORD dwLenOut, PDWORD pdwActualOut){ returnTRUE;} //-----------------------------------------------------------------------------//-----------------------------------------------------------------------------DWORDIRS_Open(DWORD hDeviceContext, DWORD AccessCode, DWORD ShareMode){ RETAILMSG(0,(TEXT("USERLED: IRS_Open\r\n"))); returnTRUE;} //-----------------------------------------------------------------------------//-----------------------------------------------------------------------------BOOLIRS_Close(DWORD hOpenContext){ RETAILMSG(0,(TEXT("USERLED: IRS_Close\r\n"))); returnTRUE;} //-----------------------------------------------------------------------------//-----------------------------------------------------------------------------void IRS_PowerDown(DWORD hDeviceContext){ RETAILMSG(0,(TEXT("USERLED: IRS_PowerDown\r\n")));} //-----------------------------------------------------------------------------//-----------------------------------------------------------------------------void IRS_PowerUp(DWORD hDeviceContext){ RETAILMSG(0,(TEXT("USERLED: IRS_PowerUp\r\n"))); } //-----------------------------------------------------------------------------//-----------------------------------------------------------------------------DWORDIRS_Read(DWORD hOpenContext, LPVOID pBuffer, DWORD Count){ RETAILMSG(0,(TEXT("USERLED: IRS_Read\r\n"))); returnTRUE;} //-----------------------------------------------------------------------------//-----------------------------------------------------------------------------DWORDIRS_Seek(DWORD hOpenContext, long Amount, DWORDType){ RETAILMSG(0,(TEXT("USERLED: IRS_Seek\r\n"))); return 0;} //-----------------------------------------------------------------------------//-----------------------------------------------------------------------------DWORDIRS_Write(DWORD hOpenContext, LPCVOID pSourceBytes, DWORD NumberOfBytes){ RETAILMSG(0,(TEXT("USERLED: IRS_Write\r\n"))); return 0;}6.实验结果,当你按下遥控器上的按键时,dnw或超级终端上会显示相应的按键码如下:
长时间按某一个按键,会显示同一个键值如下:
自己动手才是王道,顶小编
代码部分好乱啊
好东西
小编有才,小编就是靠着开发板自学的吗?
小编都开始玩arm了,,我还停留在51的阶段,,而且还有很多搞不懂
不好意思当时发的比较匆忙
差不多吧,大学的时候学习的是单片机,,后来买的arm9的开发板,现在主要是安卓比较火才买的210开发板
小编是做嵌入式开发工作的?
噢 我是学单片机出身的,还没接触过操作系统,能直接上210吗?
晕
晕
加油,坚持,胜利就在前方
代码格式没有排版好
嗯 是的 在学校学过单片机,没理解自己买的单片机开发板当时,后来跟着做才来的兴趣
学习一下,谢谢分享!