//=====================================================================
//TITLE:
// TCC89x外部中断使用详解
//AUTHOR:
// norains
//DATE:
// Wednesday 03-November-2010
//Environment:
// Windows CE 6.0
// Telechips TCC8900
//=====================================================================
在嵌入式设备中,外部中断的使用很频繁,最简单的例子,用一个GPIO来检测耳机的插入或拔出,从而依此决定是否对喇叭静音。如果是采用Windows CE 系统,流程基本都相同,流程图如下:
接下来的我们要做的事情,就是在TCC8900这颗CPU上,看看如何将这流程具现为代码吧。有目的才有动力,我们就自己给自己找个题目,题目内容就是将GPIO_D05作为输入,当外部电平分别为高或低时,就产生一个中断,然后我们打印出相应的信息。
依照流程图,我们首先要做的是,设置中断寄存器。查看TCC8900的DataSheet可以发现,该CPU一共有64个中断源,其中有12个外部中断,如图:
在这12个外部输入中断中,是不是可以随便选呢?我觉得最好不要,因为BSP已经用了其中一部分,为了不和现有的驱动相冲突,我们应该选择闲置的外部中断号。已经使用和闲置的外部中断如下表所示:
外部中断号 |
BSP使用 |
IRQ_EI0 |
无 |
IRQ_EI1 |
无 |
IRQ_EI2 |
Touch2 |
IRQ_EI3 |
SPI |
IRQ_EI4 |
SianoSpi Touch1 |
IRQ_EI5 |
无 |
IRQ_EI6 |
GpioExp |
IRQ_EI7 |
PwrBtn |
IRQ_EI8 |
无 |
IRQ_EI9 |
无 |
IRQ_EI10 |
无 |
IRQ_EI11 |
Nand_Dll |
在接下来的代码里,我们选择的是IRQ_EI9。那么,我们又如何将这IRQ_EI9和GPIO_D05相联系起来?这时候,就需要设置EINTSEL寄存器了。对于该功能寄存器,一共有三个,如图:
每个中断源占了6bit,可以表示0~63的范围。而这些数值,每个对应于一个输入源,如图:
从图中可以获知,如果要IRQ_EI9和GPIO_D05相联系,需要做的就是EINTSEL2寄存器的8~13bit设置为16即可。
准备工作就绪,就是开始干活,设置中断寄存器吧:
采用Telechips提供的宏定义,寥寥几行代码就将相关寄存器设置完毕。接下来,就是将调用KernelIoControl函数将IRQ_EI9和某个系统中断号相连接:
当KernelIoControl函数调用成功后,dwSysIrq存储的则是申请的和IRQ_EI9联系起来的系统中断号。成功获取之后,就是将这系统中断号和一个事件相联系起来:
当这一切都准备就绪之后,我们就可以调用WaitForSingleObject来等待事件了。因为系统会在发生中断的时候,通过将事件置为有效状态来进行通知。一般在实际使用中,我们都是通过循环来监视中断,如:
不过这里可能会有一个抖动的问题存在,就是在外部电平改变时,会有上下波动,具体到打印信息可能会输出如下序列:
Input is low
Input is low
Input is low
Input is high
Input is high
Input is low
Input is high
Input is low
虽然最终状态还是Low,但在变换的过程中,却突变出现了三次high。要解决这个问题其实也很简单,当持续有中断发生时,我们不做任何处理;等待一段时间之后,没有了中断,才进行相应处理。根据此思想,上面的代码我们可以变换为: