外部中断作为处理器响应外部事件的通道,在控制系统中起着非常重要的作用。从前面的讨论中我们知道,在NVIC中有8个外部中断源,下面就来讨论一下这8个外部中断的使用情况。
LPC824的每一根引脚都可以响应一个外部中断,所以理论上有多少个引脚就有多少个外部中断。但由于LPC824采用了引脚挂接外部中断源的形式,所以并不是所有的引脚都可以同时设置为外部中断引脚。在LPC824中,可同时响应的外部中断源只有8个(即NVIC的8路引脚中断),所以同时只能有8个外部中断引脚在工作,但这8个外部中断引脚可选择从PIO0_0至PIO0_28中的任意一根。
LPC824外部引脚中断所涉及到的寄存器如下表所示。
从上表中可以看到,在LPC824的引脚中断控制中,一共使用了13个寄存器。下面是这些寄存器组所对应的结构体形式(位于头文件LPC82x.h中)。
typedef struct {
__IO uint32_t ISEL;
__IO uint32_t IENR;
__O uint32_t SIENR;
__O uint32_t CIENR;
__IO uint32_t IENF;
__O uint32_t SIENF;
__O uint32_t CIENF;
__IO uint32_t RISE;
__IO uint32_t FALL;
__IO uint32_t IST;
__IO uint32_t PMCTRL;
__IO uint32_t PMSRC;
__IO uint32_t PMCFG;
} LPC_PIN_INT_Type;
因为引脚中断寄存器组的基址为0xA0004000,所以要将基址指针强制转换为上述结构体,还必须要加上下面的定义。
#define LPC_PIN_INT_BASE 0xA0004000UL
#define LPC_PIN_INT ((LPC_PIN_INT_Type *) LPC_PIN_INT_BASE)
下面先对其中与外部引脚中断相关的10个寄存器的功能进行讨论,另外3个与模式匹配相关的寄存器后面再专门讨论。先来看引脚中断模式寄存器ISEL,其字节地址为0xA0004000,下表给出了它的全部位结构。
(1)第0到7位为8个外部中断引脚的模式选择位,置0时,对应的外部中断被设置为边沿触发型,置1时,设置为电平触发型,默认为边沿触发型。
(2)第8到31位为保留位。
下表给出的是引脚中断电平或上升沿中断使能寄存器IENR的全部位结构,其字节地址为0xA0004004。
(1)第0到7位为引脚中断的上升沿或电平中断选择位,置0时,对应的外部中断被禁用上升沿或电平中断,置1时,使能上升沿或电平中断,默认为禁用上升沿或电平中断。
(2)第8到31位为保留位。
下表给出的是引脚中断电平或上升沿中断置位寄存器SIENR的全部位结构,其字节地址为0xA0004008。SIENR寄存器实际上为了对IENR寄存器进行单独的置位操作而设立的,如果是按字(或字节)操作直接写IENR寄存器即可。
(1)在第0到7位中写入1会置位IENR寄存器中相对应的位,从而使能上升沿或电平中断,置0时无影响。
(2)第8到31位为保留位。
下表给出的是引脚中断电平或上升沿中断清零寄存器CIENR的全部位结构,其字节地址为0xA000400C。CIENR寄存器实际上为了对IENR寄存器进行单独的清零操作而设立的,如果是按字(或字节)操作直接写IENR寄存器即可。
(1)在第0到7位中写入1会清零IENR寄存器中相对应的位,从而禁用上升沿或电平中断,置0时无影响。
(2)第8到31位为保留位。
下表给出的是引脚中断有效电平或下降沿中断使能寄存器IENF的全部位结构,其字节地址为0xA0004010。
(1)第0到7位为引脚中断的下降沿或有效中断电平选择位,置0时,对应的外部中断被禁用下降沿中断或置位有效中断电平为低电平,置1时,使能下降沿中断使能或置位有效中断电平为高电平,默认为禁用下降沿中断或置位有效中断电平为低电平。
(2)第8到31位为保留位。
下表给出的是引脚中断有效电平或下降沿中断置位寄存器SIENF的全部位结构,其字节地址为0xA0004014。SIENF寄存器实际上为了对IENF寄存器进行单独的置位操作而设立的,如果是按字(或字节)操作直接写IENF寄存器即可。
(1)在第0到7位中写入1会置位IENF寄存器中相对应的位,从而使能下降沿中断或置位有效中断电平为高电平,写0时无影响。
(2)第8到31位为保留位。
下表给出的是引脚中断有效电平或下降沿中断清零寄存器CIENF的全部位结构,其字节地址为0xA0004018。CIENF寄存器实际上为了对IENF寄存器进行单独的清零操作而设立的,如果是按字(或字节)操作直接写IENF寄存器即可。
(1)在第0到7位中写入1会清零IENF寄存器中相对应的位,从而禁用下降沿中断或置位有效中断电平为低电平,写0时无影响。
(2)第8到31位为保留位。
下表给出的是引脚中断上升沿寄存器RISE的全部位结构,其字节地址为0xA000401C。
(1)在第0到7位中写入1会清除相应引脚的上升沿检测标记,从而为下一次上升沿检测作准备,写0时无影响。若在相应的位上读取到1,则表示自复位或上一次向该位写1清除起,对应的引脚上检测到了上升沿,读取到0,则表示对应引脚上未检测到上升沿。
(2)第8到31位为保留位。
下表给出的是引脚中断下降沿寄存器FALL的全部位结构,其字节地址为0xA0004020。
(1)在第0到7位中写入1会清除相应引脚的下降沿检测标记,从而为下一次下降沿检测作准备,写0时无影响。若在相应的位上读取到1,则表示自复位或上一次向该位写1清除起,对应的引脚上检测到了下降沿,读取到0,则表示对应引脚上未检测到下降沿。
(2)第8到31位为保留位。
下表给出的是引脚中断状态寄存器IST的全部位结构,其字节地址为0xA0004024。
(1)在第0到7位中写入1时,对于边沿触发型中断,将会清除对应引脚的上升和下降沿检测,对于电平触发型中断,将会切换对应引脚上的有效电平,写0时无影响。若在相应的位上读取到1,则表示对应的中断引脚上有正在请求的外部中断,读取到0,则表示对应的中断引脚上无正在请求的外部中断。
(2)第8到31位为保留位。
注意,电平触发的中断会由硬件在有效电平消失时自动清除标志,并没有软件清除电平中断标志的操作。
以上10个寄存器就是LPC824中与外部引脚中断相关寄存器,其实除了这10个寄存器以外,还有1个名为PINTSEL的寄存器也与外部引脚中断密切相关,只不过它不在上述寄存器组中,而是位于SYSCON模块中。下表就给出了引脚中断选择寄存器PINTSEL的全部位结构,这样的寄存器一共有8个(PINTSEL0~PINTSEL7),其字节地址从0x40048178到0x40048194。
(1)第0到5位用来选择外部中断的引脚编号,范围从PIO0_0到PIO0_28共29根引脚。
(2)第6到31位为保留位。
注意,PINTSEL寄存器一共有8个,也即LPC824的外部引脚中断同时最多只能使用8个,但每一个外部中断都可以在全部PIO0_0到PIO0_28端口中选择引脚。 相当于PINTSEL0~PINTSEL7是8个外部中断源,具体哪个中断源使用哪个引脚,是根据PINTSEL寄存器的配置来确定的。
在讨论完了寄存器的功能后,下面就来分解一下把某个引脚配置为外部中断模式的具体步骤:
1、确定要配置为中断模式的引脚,然后在SYSCON模块的PINTSEL寄存器中进行选择设置,一共可以配置8个外部中断引脚。例如,执行“LPC_SYSCON->PINTSEL0 |= 0x01;”语句后,就把PIO0_1引脚设置为了外部中断引脚。
2、确定是电平触发还是边沿触发,通过ISEL寄存器进行选择配置。例如,执行“LPC_PIN_INT->ISEL &= ~0x01;”语句后,就把PIO0_1引脚设置为边沿触发方式(其实默认就是边沿触发方式,此句也可不写)。
3、若上一步配置成电平触发,则需要确定是低电平触发还是高电平触发,若是边沿触发,则需要确定是上升沿触发还是下降沿触发,通过IENR或IENF寄存器进行执行配置。例如,执行“LPC_PIN_INT->IENR |= 0x01;”语句后,就把PIO0_1引脚设置为上升沿触发方式;执行“LPC_PIN_INT->IENF |= 0x01;”语句后,就把PIO0_1引脚设置为下降沿触发方式。
4、在第3步中,还可以通过访问SIENR和CIENR寄存器来更改IENR寄存器中的某一位,通过访问SIENF和CIENF寄存器来更改IENF寄存器中的某一位。SIENR、CIENR和SIENF、CIENF这四个寄存器其实是IENR和IENF寄存器的伴侣寄存器,用来优化位操作,以避免对IENR和IENF寄存器直接执行“读—改—写”的操作,提高效率。
5、使能NVIC中的相关外部中断。例如,执行“NVIC_EnableIRQ(PIN_INT0_IRQn);”语句后,就使能了PIO0_1上的外部引脚中断。
6、在中断服务程序中,需要清除原有的外部中断标记,以保证下一次外部中断顺利触发,通过访问RISE寄存器来清除上升沿中断标记,通过访问FALL寄存器来清除下降沿标记。例如,执行“LPC_PIN_INT->RISE |= 0x01;”语句后,PIO0_1原来的上升沿中断标记就被清除了。执行“LPC_PIN_INT->FALL |= 0x01;”语句后,PIO0_1原来的下降沿中断标记就被清除了。
7、在第6步中,也可以通过访问IST寄存器来清除边沿(包括上升沿和下降沿)触发的标记。执行“LPC_PIN_INT->IST |= 0x01;”语句后,PIO0_1原来的边沿中断标记就被清除了。
上述步骤也可通过下图来描述。
最后需要说明一点,即使某个引脚并不作为GPIO使用,也能配接到PININT的中断源上。比如:要自动探测4个I2C接口中哪一个被连接到主机上,即可以把它们4个的SCL线所在的IO引脚分别配接到4路PININT中断上。通信时,发生哪个中断,就认为连接到了哪个I2C接口上。而此时,IO引脚并没有作为GPIO使用,而是作为I2C的SCL信号接口。
此外,对于外部引脚中断,在MDK5的开发环境中有特定的入口函数形式,比如对于PINTSEL0的中断,函数形式如下所示。
void PIN_INT0_IRQHandler(void)
{
PINTSEL0中断服务程序部分
}
下面来看一个外部引脚中断的实际例子,电路原理图如下所示。
在上面的电路中,两个按键S1和S2分别接到了引脚PIO0_4和PIO0_1上,并且都为其配置了上拉阻。现在要求按下S1时,对LED1状态进行取反,按下S2时,对LED2状态进行取反,其中S1采用上升沿方式检测,S2采用下降沿方式检测。完整代码如下:
#include
//************************端口初始化***********************************
void Port_init(void)
{
LPC_GPIO_PORT->DIRSET0 = (1<<7) | (1<<13); //设置端口为输出方向
LPC_GPIO_PORT->SET0 = (1<<7) | (1<<13); //熄灭LED
}
//***************************主函数************************************
int main(void)
{
Port_init(); //调用端口初始化
LPC_SYSCON->PINTSEL0 = 0x1;//选择PIO0_1作为外部中断引脚
LPC_SYSCON->PINTSEL1 = 0x4;//选择PIO0_4作为外部中断引脚
// LPC_PIN_INT->ISEL &= ~0x3; //边沿触发
LPC_PIN_INT->IENR |= 0x1; //PINTSEL0上升沿使能
LPC_PIN_INT->IENF |= 0x2; //PINTSEL1下降沿使能
NVIC_EnableIRQ(PIN_INT0_IRQn);//使能PINTSEL0中断
NVIC_EnableIRQ(PIN_INT1_IRQn);//使能PINTSEL1中断
while(1)
{
;
}
}
//*********************PINTSEL0中断(S2)*****************************
void PIN_INT0_IRQHandler(void)
{
LPC_GPIO_PORT->NOT0 = 0x2000; //LED2取反
LPC_PIN_INT->RISE |= 0x1;
}
//*********************PINTSEL1中断(S1)*****************************
void PIN_INT1_IRQHandler(void)
{
LPC_GPIO_PORT->NOT0 = 0x80; //LED1取反
LPC_PIN_INT->FALL |= 0x2;
}
把程序编译后下载到LPC824中,初始状态LED都不亮,按下S1,LED1仍然不亮,松开S1,LED1亮,证明上升沿有效,再次按下S1,LED1仍然亮,松开S1,LED1熄灭,证明上升沿有效。 按下S2,LED2亮,松开S2,LED2仍然亮,证明下降沿有效,再次按下S2,LED2熄灭,松开S2,LED2仍然熄灭,证明下降沿有效。
上一篇:LPC824-系统定时器SysTick
下一篇:采用处理器实现便携式振动测试分析仪的改进设计
推荐帖子
- 为什么用示波器一测示电波形,家里就断电,并且探针的小夹子还烧掉了一小块?
- 为什么用示波器一测示电波形,家里就断电,并且探针的小夹子还烧掉了一小块?有人说是接地线的问题,让把示波器插头的接地插片剪掉,只插零线和火线两个插片。问题是解决了,可是一直没搞懂是什么原理,请大家解释一下。为什么用示波器一测示电波形,家里就断电,并且探针的小夹子还烧掉了一小块?你应该是用示波器去测量“热地”部分的信号了吧。。。。示波器探头的地线夹是与示波器电源插头的PE地相连的。。。所以火/零线-“热地”-地线夹-PE地就相通了,配电箱的漏电保护器就跳闸了。你
- 深圳小花 PCB设计
- CC2540 从机如何发送数据
- 最近在研究TI的协议栈用的是CC2540,我想问问作为从机,是如何向主机发送数据的,用了什么函数,请详细介绍下~~~CC2540从机如何发送数据
- 最后无事 TI技术论坛
- 直流电机原理与驱动技术
- 直流电机原理与驱动技术还可以很早的文件不错,正想看直流电机的资料谢谢,正好要用学习一下就前半本,后面没了直流电机的两层含义:用的是直流电,电力不需特别处理就可直接产生动力。要驱动不难,看清机上的极性标志,加上足够的电压,机械负载不过量,马达就能正常的动起来。咋看不到啊?
- 追梦1988 模拟电子
- WINCE5.0 USB驱动如何确定设备扩展信息的长度
- LINUX下的usbcore驱动定义的数据结构中都有一个字端来保存扩展信息的长度,例如:/*host-sidewrapperforoneinterfacesetting\'sparseddescriptors*/structusb_host_interface{structusb_interface_descriptordesc;/*arrayofdesc.bNumEndpointendpointsassociatedwith
- jinwen39325568 WindowsCE
- 关于GPS模块
- 参加了一个科创比赛:利用STC15和GPS模块实现公交车自动报站功能。求各位大神推荐一款性价比高的GPS模块,不胜感激!!关于GPS模块UBLOX的吧,资料多,也比较成熟!谢谢,那价格怎么样?个人小批量应用去淘宝根据价格和资料去选择就行,跟产品级的采购要求完全不同,二手货只要功能完好都可以用。
- 神雕侠 51单片机
- 关于PB中定制操作系统后分辨率的问题
- 在PB中定制的操作系统的分辨率设制为320x240,编译通过,再版在上显示正常,但是打开新窗口后,窗口的一部分是在界面外,或分辨率超出了320x240,请教高手,如何解决?谢谢·!关于PB中定制操作系统后分辨率的问题看看你的LCD_BUFFER的地址(当然,你的显存可能是另外的名字)和你的config中DISPLAY定义的地址和长度是否一致注意设置你的LCD的场频,祯频参数,看看下面的一些参数VLinesTotal=dword:;VSyncStartStop=dword:
- diedong123 嵌入式系统
设计资源 培训 开发板 精华推荐
- LT3091IT7 并联线性稳压器的典型应用
- LT3493 演示板、1.2A、750KHz 降压型开关稳压器,采用 2mm3mm DFN
- LT1170CT、-10 至 -26/5A LCD 对比度电源的典型应用
- #第五届立创电子设计大赛#带hall传感器的BLDC无刷电机的单电阻采样FOC矢量控制
- LTC2242CUP-12 演示板,LVDS OUT,VCC = 2.5V,250Msps,12 位,10MHz< AIN< 250MHz
- LTC4242 演示板、双端口、PCI Express 热插拔控制器
- 使用 Analog Devices 的 ADM3062EBCPZ-R7 的参考设计
- 用于按钮控制复位的 LTC2953CDD-1 电压监控器的典型应用电路
- LT6654AMPS6-4.096 升压输出电流电压基准的典型应用
- #第七届立创电赛#USB电流表