`
经过几天的研究,终于把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
#include
#include
#include
#include
#include
#include
"pmplatform.h"
#include
"Pkfuncs.h"
#include
#include
#include
"gpioentry_reg.h"
#include
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);//
延时
us
BOOLIRS_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 "),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;
}
//
判断遥控接收引脚低电平,返回
true
BOOLIRS_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 ")));
returnTRUE;
}
DWORDIRS_Init(DWORD dwContext)
{
RETAILMSG(1,(TEXT("Key_Gpio_Setting---- ")));
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 ")));
returnTRUE;
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
BOOLIRS_Close(DWORD hOpenContext)
{
RETAILMSG(0,(TEXT("USERLED: IRS_Close ")));
returnTRUE;
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void
IRS_PowerDown(DWORD hDeviceContext)
{
RETAILMSG(0,(TEXT("USERLED: IRS_PowerDown ")));
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void
IRS_PowerUp(DWORD hDeviceContext)
{
RETAILMSG(0,(TEXT("USERLED: IRS_PowerUp ")));
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
DWORDIRS_Read(DWORD hOpenContext, LPVOID pBuffer, DWORD Count)
{
RETAILMSG(0,(TEXT("USERLED: IRS_Read ")));
returnTRUE;
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
DWORDIRS_Seek(DWORD hOpenContext, long Amount, DWORDType)
{
RETAILMSG(0,(TEXT("USERLED: IRS_Seek ")));
return 0;
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
DWORDIRS_Write(DWORD hOpenContext, LPCVOID pSourceBytes, DWORD NumberOfBytes)
{
RETAILMSG(0,(TEXT("USERLED: IRS_Write ")));
return 0;
}
6.
实验结果,当你按下遥控器上的按键时,
dnw
或超级终端上会显示相应的按键码如下:
|