wince制作模块时如何将GPIO口与事件绑定?
2014-3-24
以下是将模块红外传感器 GPIO0(8) 设置成中断源并与事件绑定的具体步骤:
一:OAL 配置
1.在 c:\wince600\platform\tt6x0bd\src\inc\Oemintr.h中添加
在物理中断号后面添加(IRQ开头的为物理中断号动态分配,按序排列的)
//2014-03-20 uidp4146 Gesture IRQ
#define IRQ_GESTURE_DETECT_IRQ (IRQ_AUXIN_DETEXT_IRQ-1)
在系统中断号后面添加(SYSINTR开头的为系统中断号动态分配,按序排列的)
//2014-03-22
#define SYSINTR_GESTURE_DETECT_IRQ (SYSINTR_AUXIN_DETECT-1)
2.在 c:\wince600\platform\tt6x0bd\src\oal\oallib\Intr.c中添加
1)#define GPIO_GROUTP_GESTURE_INT GPIO_GROUP(0)
#define GPIO_INDEX_ GESTURE _INT GPIO_INDEX(8)
2)在函数 BSPIntrInit()中添加
OALIntrStaticTranslate(SYSINTR_GESTURE_DETECT_IRQ, IRQ_GESTURE_DETECT_IRQ);
3)在函数 BSPIntrEnableIrq中添加
case IRQ_GESTURE_DETECT_IRQ: if(!OALGpioIntrIsRegisterd(GPIO_NUM(GPIO_GROUTP_ GESTURE _INT,
GPIO_INDEX_ GESTURE _INT)))
{
RETAILMSG(1,(TEXT("^^==========61=========^^^^IRQ_JACK enable 2\r\n")));
OALGpioRegisterIntr(GPIO_NUM(GPIO_GROUTP_ GESTURE _INT,
GPIO_INDEX_ GESTURE _INT),
GPIO_INTTYPE_FALLING_EDGE, SYSINTR_GESTURE_DETECT_IRQ, IRQ_GESTURE_DETECT_IRQ); //目的在与注册系统 ID和中断服务 ID
GPIO_PAD_EN_SET(GPIO_GROUTP_ GESTURE _INT,1 << GPIO_INDEX_ GESTURE _INT); //1<<GPIO_INDEX_ GESTURE _INT is the same to PIO_MASK(Index)
//PIO_OUTPUT_DISABLE(GPIO,GPIO_GROUTP_ GESTURE _INT,
GPIO_INDEX_ GESTURE _INT); //It has no function
PIO_INT_ENABLE(GPIO,GPIO_GROUTP_ GESTURE _INT,
GPIO_INDEX_ GESTURE _INT);
}
break;
4)在函数 BSPIntrDoneIrq中添加
case IRQ_GESTURE_DETECT_IRQ: //2014-3-24 ZJ add for Interrupt
PIO_INT_ENABLE(GPIO,GPIO_GROUTP_ GESTURE _INT,
GPIO_INDEX_ GESTURE _INT);
break;
目的是 ENABLE IO口的中断
5)在函数 BSPIntrDisableIrq中添加
case IRQ_GESTURE_DETECT_IRQ: //2014-3-24 ZJ add for GPIO Interrupt
PIO_INT_DISABLE(GPIO,GPIO_GROUTP_ GESTURE _INT,
GPIO_INDEX_ GESTURE _INT);
break;
目的是 DISABLE IO口的中断
二:中断服务程序
Note:该程序可置于任意在 Platform.reg和 Platform.bib添加了信息的驱动中,在这里我添加在自己添加的 GPIO命名的流驱动中
1.创建事件
1)全局变量 HANDLE m_hIrEvent;
2)在函数 IRR_Init中添加
m_hIrEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
if (!m_hIrEvent)
{
RETAILMSG(1,(TEXT("\r\nCreateEvent ERROR!!--\r\n")));
return FALSE;
}
Else
RETAILMSG(1,(TEXT("\r\nCreateEvent OK!!--\r\n")));
2.初始化中断
1)系统中断ID: SYSINTR_GESTURE_DETECT_IRQ与事件关联
BOOL bSuccess;
bSuccess = InterruptInitialize(SYSINTR_GESTURE_DETECT_IRQ, m_hIrEvent, NULL, 0);
此时会调用OAL 中UINT32 BSPIntrEnableIrq(UINT32irq),进行中断的注册
2)由于存在SYSINTR_GESTURE_DETECT_IRQ,因此需要添加头文件oemintr.h,还要在 IR_GESTURE的Source文件中添加该头文件路径
$(_TARGETPLATROOT)\SRC\INC;$(INCLUDES)
3.创建线程
1)全局变量 HANDLE m_hIrThread; //2014-3-24 ZJ add
2)在 IRR_Init中添加
m_hIrThread = CreateThread(NULL,
0,
(LPTHREAD_START_ROUTINE)IrThread,
NULL,
0,
NULL);
if (!m_hIrThread)
{
RETAILMSG(1,(TEXT("\r\nCreateThread ERROR!!--\r\n")));
return FALSE;
}
else RETAILMSG(1,(TEXT("\r\nCreateThread Successfully!!--\r\n")));
4.中断线程函数
void IrThread()
{
while(TRUE)
{
InterruptDone(SYSINTR_GESTURE_DETECT_IRQ);
WaitForSingleObject(m_hIrEvent,INFINITE);//等待中断事件发生,即向下执行
RETAILMSG(1,(TEXT("m_hGpioThread: WaitForSingleObject -m_hIrEvent!\r\n")));
}
}
在 Prima EVB 板上,最好是用 GPIO0_8作为练习对象,原因有二:
一是它本身是个按钮,便于触发;
二是是按钮的三个按键中有两个是有中断的,如果再用,会产生冲突。
经验心得
1:不必一定要把 IO口设置成输入状态,才能 ENABLE IO口中断,故 PIO_OUTPUT_DISABLE加与不加效果一样;
2:ENABLE IO口中断,此时 IO口默认为输入状态。
3:InterruptDone(SYSINTR_CHARGEDONE); 的作用是恢复原来状态,以便下次按键继续触发。