经过几天的研究,终于把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);//延时us
BOOL IRS_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);//清楚中断屏蔽位
BOOL IRS_set_filter_method(EINT_FILTER_METHOD eMethod, unsigned int uiFilterWidth);//选择中断的filter方式
BOOL IRS_set_interrupt_method(EINT_SIGNAL_METHOD eMethod);//设置中断方式
2.解码线程:
INT WINAPI 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;
double dfMinus, 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.其他流驱动接口函数
//设置寄存器地址
BOOL HS38_initialize_register_address(void *pGPIOReg)//,void *pHSReg)
{
if (pGPIOReg == NULL)
{
return FALSE;
}
else
{
g_pGPIOReg = (GPIO_REG *)pGPIOReg;
}
return TRUE;
}
//初始化
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);
}
//设置中断方式
BOOL IRS_set_interrupt_method(EINT_SIGNAL_METHOD eMethod)
{
BOOL Ret = TRUE;
switch(eMethod)
{
case EINT_SIGNAL_LOW_LEVEL:
Set_EXTINT_TRLVL(g_pGPIOReg, EXT_INT_6, sgip_LOW_LEVEL);
break;
case EINT_SIGNAL_HIGH_LEVEL:
Set_EXTINT_TRLVL(g_pGPIOReg, EXT_INT_6, sgip_HIGH_LEVEL);
break;
case EINT_SIGNAL_FALL_EDGE:
Set_EXTINT_TRLVL(g_pGPIOReg, EXT_INT_6, sgip_FALLING_EDGE);
break;
case EINT_SIGNAL_RISE_EDGE:
Set_EXTINT_TRLVL(g_pGPIOReg, EXT_INT_6, sgip_RISING_EDGE);
break;
case EINT_SIGNAL_BOTH_EDGE:
Set_EXTINT_TRLVL(g_pGPIOReg, EXT_INT_6, sgip_BOTH_EDGE);
break;
default:
Ret = FALSE;
break;
}
return Ret;
}
//设置中断filter方式
BOOL IRS_set_filter_method(EINT_FILTER_METHOD eMethod, unsigned int uiFilterWidth)
{
BOOL Ret =TRUE;
switch(eMethod)
{
case EINT_FILTER_DISABLE:
Clr_EXTINT_FILTER(g_pGPIOReg, EXT_INT_6);
break;
case EINT_FILTER_DELAY:
Set_EXTINT_FILTER(g_pGPIOReg, EXT_INT_6, sgip_DELAY_FLT, 0);
break;
case EINT_FILTER_DIGITAL:
Set_EXTINT_FILTER(g_pGPIOReg, EXT_INT_6, sgip_DIGITAL_FLT, uiFilterWidth);
break;
default:
Ret = FALSE;
break;
}
return Ret;
}
//判断遥控接收引脚低电平,返回true
BOOL IRS_date(void)
{
if(Get_PinData(g_pGPIOReg,GPH06_EXT_INT_6))
{
return FALSE; // Low Active Switch (Pull-up switch)
}
else
{
return TRUE;
}
}
static BOOL AllocResources(void)
{
DWORD dwIRQ;
PHYSICAL_ADDRESS ioPhysicalBase = {0,0};
//------------------
// GPIO Controller SFR
//------------------
ioPhysicalBase.LowPart = BASE_REG_PA_GPIO;
g_pGPIOReg = (GPIO_REG *)MmMapIoSpace(ioPhysicalBase, sizeof(GPIO_REG), FALSE);
if (g_pGPIOReg == NULL)
{
return FALSE;
}
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;
return FALSE;
}
g_hEventHS38 = CreateEvent(NULL, FALSE, FALSE, NULL);
if(NULL == g_hEventHS38)
{
return FALSE;
}
if (!(InterruptInitialize(g_dwSysIntrHS38, g_hEventHS38, 0, 0)))
{
return FALSE;
}
return TRUE;
}
static void ReleaseResources(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();
}
BOOL WINAPI
DllEntry(HANDLE hinstDLL,
DWORD dwReason,
LPVOID /* lpvReserved */)
{
switch(dwReason)
{
case DLL_PROCESS_ATTACH:
DEBUGREGISTER((HINSTANCE)hinstDLL);
return TRUE;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
break;
#ifdef UNDER_CE
case DLL_PROCESS_EXITING:
break;
case DLL_SYSTEM_STARTED:
break;
#endif
}
return TRUE;
}
BOOL IRS_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);
// Wait for Thread to Finish
WaitForSingleObject(g_hThreadHS38, INFINITE);
CloseHandle(g_hThreadHS38);
g_hThreadHS38 = NULL;
}
ReleaseResources();
//RETAILMSG(1,(TEXT("USERLED: IRS_Deinit\r\n")));
return TRUE;
}
DWORD IRS_Init(DWORD dwContext)
{
RETAILMSG(1,(TEXT("Key_Gpio_Setting----\r\n")));
if (AllocResources() == FALSE)
{
goto CleanUp;
}
HS38_initialize_register_address((void *)g_pGPIOReg);
InitInterrupt();
g_hThreadHS38 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) HS38Thread, NULL, 0, NULL);
if (g_hThreadHS38 == NULL )
{
goto CleanUp;
}
return TRUE;
CleanUp:
IRS_Deinit(0);
return FALSE;
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
BOOL IRS_IOControl(DWORD hOpenContext,
DWORD dwCode,
PBYTE pBufIn,
DWORD dwLenIn,
PBYTE pBufOut,
DWORD dwLenOut,
PDWORD pdwActualOut)
{
return TRUE;
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
DWORD IRS_Open(DWORD hDeviceContext, DWORD AccessCode, DWORD ShareMode)
{
RETAILMSG(0,(TEXT("USERLED: IRS_Open\r\n")));
return TRUE;
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
BOOL IRS_Close(DWORD hOpenContext)
{
RETAILMSG(0,(TEXT("USERLED: IRS_Close\r\n")));
return TRUE;
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
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")));
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
DWORD IRS_Read(DWORD hOpenContext, LPVOID pBuffer, DWORD Count)
{
RETAILMSG(0,(TEXT("USERLED: IRS_Read\r\n")));
return TRUE;
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
DWORD IRS_Seek(DWORD hOpenContext, long Amount, DWORD Type)
{
RETAILMSG(0,(TEXT("USERLED: IRS_Seek\r\n")));
return 0;
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
DWORD IRS_Write(DWORD hOpenContext, LPCVOID pSourceBytes, DWORD NumberOfBytes)
{
RETAILMSG(0,(TEXT("USERLED: IRS_Write\r\n")));
return 0;
}
6.实验结果,当你按下遥控器上的按键时,dnw或超级终端上会显示相应的按键码如下:
长时间按某一个按键,会显示同一个键值如下:
|