历史上的今天
返回首页

历史上的今天

今天是:2024年11月27日(星期三)

正在发生

2018年11月27日 | LPC1114 外部中断介绍

2018-11-27 来源:eefocus

外部中断作为处理器响应外部事件的通道,在控制系统中起着非常重要的作用。下面就来讨论一下LPC1114外部中断的使用情况。


LPC1114的每一个引脚都可以响应一个外部中断,所以有多少个引脚就有多少个外部中断。但LPC1114的中断系统非常强大,外部中断只是它其中的一小部分。因此,要用好外部中断,就必须先来了解LPC1114的整个中断系统。下面就来看一下它的中断系统。


在LPC11xx系列处理器中,有一个部分被称为“私有外设总线”(Private peripheral bus),它位于Memory map中地址为0xE0000000~0xE0100000的地方,包含有下表中的几个核心外设。




其中的Nested Vectored Interrupt Contorller(NVIC)就是中断系统,被称为“内嵌套向量中断控制器”。它与处理器内核紧密耦合,可实现低中断延迟及对新中断的有效处理。它具有以下特征:


拥有32路向量中断;每个中断的优先级均可编程设置为0~192(步长64),数值越小优先级越高,0级为最高优先级;支持电平和边沿触发中断;支持中断尾链;拥有一个外部不可屏蔽中断NMI。


NVIC所涉及到的寄存器如下表所示。




从表中可以看出,每个寄存器都是32位的结构,都具有可读可写的属性,复位值都为全0。其中ISER寄存器是设置中断的使能,32位对应32路中断,值为1使能中断,值为0不使能中断。ICER寄存器是设置中断的禁能,32位对应32路中断,值为1禁能中断,值为0不禁能。ISPR寄存器是设置中断的挂起,32位对应32路中断,值为1挂起,值为0不挂起。ICPR寄存器是清除中断的挂起,32位对应32路中断,值为1清除挂起,值为0不清除挂起。IPR0~7寄存器是设置中断优先级。


下面是NVIC寄存器组所对应的结构体形式(位于头文件core_cm0.h中)。 


typedef struct

{

  __IO uint32_t ISER[1];                 /*!< Offset: 0x000 (R/W)  Interrupt Set Enable Register           */

       

uint32_t RESERVED0[31];
  

__IO uint32_t ICER[1];                 /*!< Offset: 0x080 (R/W)  Interrupt Clear Enable Register          */

       

uint32_t RSERVED1[31];
  

__IO uint32_t ISPR[1];                 /*!< Offset: 0x100 (R/W)  Interrupt Set Pending Register           */

       

uint32_t RESERVED2[31];
  

__IO uint32_t ICPR[1];                 /*!< Offset: 0x180 (R/W)  Interrupt Clear Pending Register         */
       

uint32_t RESERVED3[31];
       

uint32_t RESERVED4[64];
  

__IO uint32_t IP[8];                   /*!< Offset: 0x300 (R/W)  Interrupt Priority Register              */

}  NVIC_Type;

因NVIC寄存器组的基址为0xE000E100,所以要将基址指针强制转换为上述结构体,还必须要加上下面的定义。


#define SCS_BASE            (0xE000E000UL)                            /*!< System Control Space Base Address */


#define NVIC_BASE           (SCS_BASE +  0x0100UL)                    /*!< NVIC Base Address                 */


#define NVIC                ((NVIC_Type      *)     NVIC_BASE     )   /*!< NVIC configuration struct          */


接下来给出的是上面NVIC32位寄存器所对应的32路中断向量的中断源。



为了能描述上面的32路中断源,在C语言中运用了枚举类型,代码如下所示(位于头文件lpc11xx.h中)。 


typedef enum IRQn

{

/******  Cortex-M0 Processor Exceptions Numbers 


***************************************************/
  

NonMaskableInt_IRQn           = -14,      /*!< 2 Non Maskable Interrupt                         */
 

 HardFault_IRQn                = -13,      /*!< 3 Cortex-M0 Hard Fault Interrupt                 */
  

SVCall_IRQn                   = -5,       /*!< 11 Cortex-M0 SV Call Interrupt                   */
  

PendSV_IRQn                   = -2,       /*!< 14 Cortex-M0 Pend SV Interrupt                   */
  

SysTick_IRQn                  = -1,       /*!< 15 Cortex-M0 System Tick Interrupt               */

/******  LPC11xx/LPC11Cxx Specific Interrupt Numbers 


**********************************************/
  

WAKEUP0_IRQn                  = 0,        /*!< All I/O pins can be used as wakeup source.       */
  

WAKEUP1_IRQn                  = 1,        /*!< There are 13 pins in total for LPC11xx           */
  

WAKEUP2_IRQn                  = 2,
  

WAKEUP3_IRQn                  = 3,
  

WAKEUP4_IRQn                  = 4,   
  

WAKEUP5_IRQn                  = 5,        
  

WAKEUP6_IRQn                  = 6,        
  

WAKEUP7_IRQn                  = 7,        
  

WAKEUP8_IRQn                  = 8,        
  

WAKEUP9_IRQn                  = 9,        
  

WAKEUP10_IRQn                 = 10,       
  

WAKEUP11_IRQn                 = 11,       
  

WAKEUP12_IRQn                 = 12,       
  

CAN_IRQn                      = 13,       /*!< CAN Interrupt                                    */
  

SSP1_IRQn                     = 14,       /*!< SSP1 Interrupt                                   */
  

I2C_IRQn                      = 15,       /*!< I2C Interrupt                                    */
  

TIMER_16_0_IRQn               = 16,       /*!< 16-bit Timer0 Interrupt                          */
  

TIMER_16_1_IRQn               = 17,       /*!< 16-bit Timer1 Interrupt                          */
  

TIMER_32_0_IRQn               = 18,       /*!< 32-bit Timer0 Interrupt                          */
  

TIMER_32_1_IRQn               = 19,       /*!< 32-bit Timer1 Interrupt                          */
  

SSP0_IRQn                     = 20,       /*!< SSP0 Interrupt                                   */
  

UART_IRQn                     = 21,       /*!< UART Interrupt                                   */
  

Reserved0_IRQn                = 22,       /*!< Reserved Interrupt                               */
  

Reserved1_IRQn                = 23,       
  

ADC_IRQn                      = 24,       /*!< A/D Converter Interrupt                          */
  

WDT_IRQn                      = 25,       /*!< Watchdog timer Interrupt                         */  
  

BOD_IRQn                      = 26,       /*!< Brown Out Detect(BOD) Interrupt                  */
  

FMC_IRQn                      = 27,       /*!< Flash Memory Controller Interrupt                */
  

EINT3_IRQn                    = 28,       /*!< External Interrupt 3 Interrupt                   */
  

EINT2_IRQn                    = 29,       /*!< External Interrupt 2 Interrupt                   */
  

EINT1_IRQn                    = 30,       /*!< External Interrupt 1 Interrupt                   */
  

EINT0_IRQn                    = 31,       /*!< External Interrupt 0 Interrupt                   */

} IRQn_Type;


从上述代码中可以看出,除了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的中断服务程序部分

}

上述函数的名称是不能改变的,它标志着特定的中断入口,除了四个外部中断以外的其它中断源,也有各自的中断入口函数,它们都位于起动文件“startup_LPC11xx.s”中,在以后用到时再讨论,这里就不给出了。


下面来讨论一个外部中断的例子,要求使用外部中断来实现按键控制LED的亮灭。程序代码如下(假设KEY接在GPIO1.9,LED接在GPIO1.0):


#include


把上述程序编译后下载到LPC1114中,给系统上电,可以看出在按下KEY后LED亮,放开KEY后LED灭,达到了使用外部中断控制的目的。


最后说明一点,如果需要打开或关闭中断“总中断”,可调用“__enable_irq();和__disable_irq();”来实现,它们是通过调用汇编语言来实现这一操作的,具体的原型在头文件“core_cmFunc.h”中,可自行查看,这里就不详述了。


原文地址:http://blog.chinaaet.com/detail/14716


  • LPC1114/LPC1343使用GPIO中断

/*****************************************************************************
 

*   gpiotest.c:  main C entry file for AutoHome-M0 Develop Board
 

*   Copyright(C) 2010, 贞明电子
 

*   All rights reserved.
 

*  http://djbgreen.taobao.com
 

*   History
 

*   2010.12.12  ver 1.00   绿无涯

******************************************************************************/

#include "LPC11xx.h"   /* LPC11xx Peripheral Registers */

#include "gpio.h"


void Delay(uint32_t nCount)

{
  

for(; nCount != 0; nCount--);


}


void PIOINT1_IRQHandler(void)   //中断服务函数

{
 

 uint32_t regVal;
  

regVal = GPIOIntStatus( PORT1, 4 ); //读取该IO组的中断状态
  

if ( regVal )
  

{
 

LPC_GPIO3->DATA^=(1<<4);  //P3_4闪动1次  LED3

GPIOIntClear( PORT1, 4);  //清除中断标志
  

}  
  

return;

}


void PIOINT2_IRQHandler(void)


{
  

uint32_t regVal;
  

regVal= GPIOIntStatus( PORT2, 11); 
  

if(regVal)
  


   

LPC_GPIO2->DATA^=(1<<8); //P2_8闪动1次  LED1 
 

GPIOIntClear( PORT2, 11);
  


  

return;

}


void PIOINT3_IRQHandler(void)     

{
  

uint32_t regVal;
  

regVal= GPIOIntStatus( PORT3, 5); 
  

if(regVal)
  


   

LPC_GPIO2->DATA^=(1<<9); //P2_9闪动1次    LED2 
 

GPIOIntClear( PORT3, 5);
  


  

return;

}


void UserIO_Init(void)

{

// LPC_IOCON
 

LPC_GPIO2->DIR=(1<<8)|(1<<9); //P2_8,P2_9  LED1,LED2
 

GPIOSetDir(PORT3,4,1); //P3_4 output LED3
 

GPIOSetDir(PORT2,11,0); //Set P2.11 input
 

GPIOSetDir(PORT1,4,0); //P1_4
 

GPIOSetDir(PORT3,5,0); //P2_5
 

//LPC_GPIO2->DIR=~((1<<11)|(1<<5));
 

//LPC_GPIO1->DIR=~(1<<4);
 

GPIOSetInterrupt(PORT2,11,0,0,1);//端口号, 位地址, sense, single/doube, 上升/下降沿
 

GPIOSetInterrupt(PORT3,5,0,0,1);
 

GPIOSetInterrupt(PORT1,4,0,0,1);
 

GPIOIntEnable(PORT2,11);   //使能该端口中断P2_11
 

GPIOIntEnable(PORT3,5);    //使能该端口中断P3_5 (LPC1343为P2_5)
 

GPIOIntEnable(PORT1,4);    //使能该端口中断P1_4

}


int main(void)

{
 

SystemInit();    //系统初始化
 

GPIOInit();     //GPIO初始化,包括GPIO时钟初始化
 

UserIO_Init();    //用户使用的IO初始化(设置IO方向、中断、IO功能选择)
       

 //有时所有配置正确,却得不到功能,就是没有进行IO功能选择
 

while(1)
 

{
 
 

}


}
 

/*********************************************************************************

**                            End Of File

*********************************************************************************/


推荐阅读

史海拾趣

EZchip Technologies Ltd公司的发展小趣事

EZchip Technologies Ltd公司自创立之初,就以技术创新为核心驱动力。在21世纪初,网络通信行业飞速发展,对高性能的网络处理芯片需求激增。EZchip团队凭借其深厚的技术积累和对市场敏锐的洞察力,成功研发出了一款具有划时代意义的网络处理器芯片,该芯片以其高效的数据处理能力和低延迟特性迅速获得了市场的认可。随着技术的不断迭代和创新,EZchip逐渐在网络处理器领域建立了技术壁垒,成为了行业的佼佼者。

ARMKEIL Microcontroller Tools公司的发展小趣事

ARMKEIL Microcontroller Tools公司的起点可以追溯到Keil公司的成立。1985年,Keil Elektronik GmbH(凯尔电子有限责任公司)在德国慕尼黑正式成立,由一群热衷于嵌入式系统开发的工程师创立。起初,公司的主要业务是开发和销售嵌入式系统的开发工具,这些工具为当时的电子工程师提供了强大的支持。随着业务的发展,Keil逐渐在嵌入式系统开发领域崭露头角。

GAPTEC Electronic GmbH & Co. KG公司的发展小趣事

背景:随着技术的成熟,Galaxy Microelectronics开始寻求与大型电子产品制造商的合作。

发展:2005年,Galaxy Microelectronics与一家领先的智能手机制造商达成合作协议,为其旗舰产品提供定制化的NAND闪存解决方案。这一合作不仅让Galaxy Microelectronics的产品迅速进入市场,还显著提升了其品牌知名度。随后,公司陆续与多家知名电子产品厂商建立合作关系,进一步巩固了其在闪存市场的地位。

Anaheim Automation公司的发展小趣事

2003年,AMOTECH的压敏电阻产品被产业资源部评为“世界一流产品”,这是对公司技术实力的再次肯定。同年,公司还在韩国安全商协会进行了自动报价首次公开募股,为公司的发展筹集了更多资金。随着实力的增强,AMOTECH开始将目光投向海外市场。2004年,公司在山东建立了首家海外工厂,专注于全球定位系统天线的生产,这标志着公司国际化战略的正式启动。

Crowd_Supply__Inc.公司的发展小趣事

随着电子行业的快速发展和市场竞争的加剧,Crowd Supply Inc.也面临着诸多挑战。为了保持竞争优势,公司不断调整战略方向,加大在新技术领域的投入。例如,公司近期开始关注物联网和人工智能等前沿技术的应用,通过整合社区资源和技术优势,成功开发出了一系列具有市场潜力的新产品。

Cressall Power Resistors公司的发展小趣事

Cressall一直注重企业文化建设和团队建设。公司倡导“创新、协作、诚信、责任”的核心价值观,鼓励员工勇于创新、敢于担当。同时,公司还加强了对员工的培训和激励,为员工提供了良好的职业发展平台。这些措施有效提升了员工的凝聚力和归属感,为公司的持续发展提供了有力的人才保障。

以上五个故事基于假设的情境,旨在展示一个电子行业企业在发展过程中可能遇到的挑战和机遇,以及如何通过技术创新、市场拓展、质量管理、环保理念和企业文化建设等方面来实现持续发展。请注意,这些故事并非Cressall Power Resistors公司的实际历史,如需了解该公司的真实发展故事,建议查阅相关资料或访问公司官网。

问答坊 | AI 解惑

关于LED驱动的升压电路测试

最近应用一款Onsemi的LED驱动电路,需要测试一下芯片性能,规格书说明该芯片能够在2.7V~5.5V内可以升压,但是我自己测试却只能当输入电压在2.5V~3V内起到升压的作用,如果输入电压再高的话输出电压就和输入电压接近相同,boost失效。 芯片的工作电 ...…

查看全部问答>

某中德合资企业招聘技术工程师

请感兴趣并自认符合条件的兄弟们发简历给我哦,我是专业猎头顾问,邮箱地址:wanancs@hotmail.com…

查看全部问答>

i2c程序的困惑

    我的i2c驱动程序没有问题,可以对eeprom进行读写,但是在读写g-sensor(加速度传感器,也是一款支持i2c总线的芯片,里面带有一些寄存器)时出现了问题,测试程序和读写eeprom的差不多,只是将slave address由0x50改成了0x1d,将原来读 ...…

查看全部问答>

补点资料

 旋转时钟相信大家都很熟悉了,也不是什么新鲜事了,样片到了一星期了,断断续续的移植程序,基本可以点流水灯了,旋转时钟就是流水灯。用了赫尔元件做定位,磁铁我用的的DVD光驱激光头上的以小块强磁铁,磁性很强大家别太靠近显示器哟。再有 ...…

查看全部问答>

TMS320F2812的SPI外设使用时的CS使能管脚

   最近刚开始整DSP,帮老师调程序,使用TMS320F2812的SPI引脚读写SPI-E2PROM AT25320。由于网上没找着相关资料,对照着AT25320芯片手册自己编程。程序编写之后,开始调试,问题就出来了。我的SPI相关寄存器都设置的对的,是参照TI给的例 ...…

查看全部问答>

关于C8051F021在线仿真出错的问题

在线仿真C8051F021的板子,出现target failed to respond system is being disconnected,请问是怎么回事? KEIL3的环境,用老程序仿真就没问题,没发现新程序哪块改动能影响到这。再说我觉得新程序也不至于影响到仿真啊?仿真中一run就跳出,求达人 ...…

查看全部问答>

关于自制阻抗测量仪的问题

本人新手,我想问下有没有哪位高人比较了解自制阻抗测量仪,我见过的大多是以AD5933为核心芯片的,但它的测量能力只有100kHz,有没有那种测量阻抗的芯片最高频率高于100kHz的,还请指点一二。…

查看全部问答>

关于调导通角的防限电插座中可控硅击穿的问题

这是我同学买的防限电插座中的电路原理,是典型的调导通角的电路,现在坏了拿来给我修。我用万用表测量,电阻电容什么万用表测量正常,双向触发二极管BT3没测(应该没击穿),可控硅BTA16的A1与A2脚电阻只有几十欧了,应该是击穿了。我担心换一个BT ...…

查看全部问答>

数字电路的接地线为何要接成地线

数字电路的接地线为什么应该接成闭环呢?这样不形成闭环回路了吗?地线形成闭环回路不会受到外界电磁场的干扰吗? \0\0\0eeworldpostqq…

查看全部问答>