微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > LPC1114外部中断

LPC1114外部中断

时间:11-13 来源:互联网 点击:

从上述代码中可以看出,除了32路中断源外,还加入了优先级更高5个中断源。这里先不进行说明,在后面用到时再来讨论。定义好上述代码后,就可以来写中断所需要的函数了。下面就是依据CMSIS规范所定义的8个中断操作函数(位于头文件core_cm0.h中)。

1.允许某个中断或异常

static __INLINE void NVIC_EnableIRQ(IRQn_Type IRQn)
{
NVIC->ISER[0] = (1 < ((uint32_t)(IRQn) & 0x1F));
}

2.禁止某个中断或异常

static __INLINE void NVIC_DisableIRQ(IRQn_Type IRQn)
{
NVIC->ICER[0] = (1 < ((uint32_t)(IRQn) & 0x1F));
}

3.读取某个中断或异常的挂起状态

static __INLINE uint32_t NVIC_GetPendingIRQ(IRQn_Type IRQn)
{
return((uint32_t) ((NVIC->ISPR[0] & (1 < ((uint32_t)(IRQn) & 0x1F)))?1:0));
}

4.把某个中断或异常的挂起状态设为1

static __INLINE void NVIC_SetPendingIRQ(IRQn_Type IRQn)
{
NVIC->ISPR[0] = (1 < ((uint32_t)(IRQn) & 0x1F));
}

5.把某个中断或异常的挂起状态清为0

static __INLINE void NVIC_ClearPendingIRQ(IRQn_Type IRQn)
{
NVIC->ICPR[0] = (1 < ((uint32_t)(IRQn) & 0x1F)); /* Clear pending interrupt */
}

6.把某个中断或异常的可配置优先级设为1

static __INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
{
if(IRQn < 0) {
SCB->SHP[_SHP_IDX(IRQn)] = (SCB->SHP[_SHP_IDX(IRQn)] & ~(0xFF < _BIT_SHIFT(IRQn))) |
(((priority < (8 - __NVIC_PRIO_BITS)) & 0xFF) < _BIT_SHIFT(IRQn)); }
else {
NVIC->IP[_IP_IDX(IRQn)] = (NVIC->IP[_IP_IDX(IRQn)] & ~(0xFF < _BIT_SHIFT(IRQn))) |
(((priority < (8 - __NVIC_PRIO_BITS)) & 0xFF) < _BIT_SHIFT(IRQn)); }
}

7.读取某个中断或异常的优先级

static __INLINE uint32_t NVIC_GetPriority(IRQn_Type IRQn)
{

if(IRQn < 0) {
return((uint32_t)((SCB->SHP[_SHP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) >> (8 - __NVIC_PRIO_BITS))); } /* get priority for Cortex-M0 system interrupts */
else {
return((uint32_t)((NVIC->IP[ _IP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) >> (8 - __NVIC_PRIO_BITS))); } /* get priority for device specific interrupts */
}

8.复位NVIC

static __INLINE void NVIC_SystemReset(void)
{
__DSB(); /* Ensure all outstanding memory accesses included buffered write are completed before reset */
SCB->AIRCR = ((0x5FA < SCB_AIRCR_VECTKEY_Pos)| SCB_AIRCR_SYSRESETREQ_Msk);
__DSB(); /* Ensure completion of memory access */
while(1); /* wait until reset */
}

在上述函数中有几点要说明一下,一是数组的引用其取值只能是0(即第一个元素),这是因为在结构体定义中只定义了一个数组元素,且由于需要利用数组的地址连续性来对映CPU物理地址,所以也不能将其定义为一个普通变量;二是关键字“__INLINE”在头文件core_cm0.h中已做了宏定义“#define __INLINE __inline”,__inline是通知编译器其后面的函数为内联形式;三是中断源IRQn要与0x1F与一下,是为了屏蔽高27位的值,因为中断源的最大值只到31,所以只用了32位中的低5位(31的二进制是11111,十六进制是0x1F);四是在函数的参数中,由于引入了枚举类型,所以可以在调用函数的时候,在参数部分可直接使用枚举中的名称,这样就可以省去记忆32个中断源在32位寄存器中的对应位置,便于书写和阅读。例如,要开启端口0的外部中断,执行程序“NVIC_EnableIRQ(EINT0_IRQn)”即可。

上述就是LPC1114中的整个中断系统,即“内嵌套向量中断控制器”。可以看出,它控制着整个处理器32路中断源的使能与挂起等8个动作,功能非常强大。但做为外部中断的端口中断源却只有4个,即EINT0_IRQn、EINT1_IRQn、EINT2_IRQn、EINT3_IRQn四个。而每一个端口又对应有12个引脚(端口3为6个)又都可以产生外部中断,那怎么来判断是那个引脚上申请的中断呢?这就需要借助前面“通用输入/输出端口”部分介绍过的MIS寄存器了。在外部中断响应的服务程序内,判别MIS寄存器的各个位,值为1的位所对应的就是触发本次外部中断的引脚。

和所有的单片机一样,在中断响应后,程序指针会跳转到相应的中断向量入口处去执行中断服务程序,而在C语言中则是以特定形式的中断入口函数来呈现。比如EINT0_IRQn、EINT1_IRQn、EINT2_IRQn、EINT3_IRQn四个端口的外部中断入口函数分别如下:

void PIOINT0_IRQHandler(void)
{
端口0的中断服务程序部分
}
void PIOINT1_IRQHandler(void)
{
端口1的中断服务程序部分
}
void PIOINT2_IRQHandler(void)
{
端口2的中断服务程序部分
}
void PIOINT3_IRQHandler(void)
{
端口3的中断服务程序部分
}
上述函数的名称是不能改变的,它标志着特定的中断入口,除了四个外部中断以外的其它中断源,也有各自的中断入口函数,它们都位于起动文件“sta

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top