首页

胳膊打断教程

任何微控制器的主要目的都是接受来自输入设备的输入,并相应地驱动输出。因此,一次将有几个设备连接到一个微控制器。此外,在微控制器中有许多内部组件,如定时器、计数器等,需要处理器的注意。

由于所有的设备不能在任何时候都获得处理器的注意,“中断”的概念就出现了。一个中断,顾名思义,中断微控制器正在做的任何事情,并吸引它的注意力来执行一个特殊的任务。下图描述了中断所涉及的过程。

中断发生

在中断事件中,中断源(如定时器、计数器等)向处理器发送一个特殊的请求,称为中断请求(IRQ),以运行一段特殊的代码。这种特殊代码或函数被称为中断服务例程(ISR)。

从上图中可以看出,CPU执行它的正常代码集,直到发生IRQ。当接收到IRQ信号时,CPU停止执行常规代码,开始执行ISR。一旦ISR的执行被CPU完成,它就会返回到正常代码的执行。

矢量中断控制器(VIC)处理LPC214x系列单片机中的中断。它可以采取多达32中断请求。LPC2148微控制器中的中断可分为快速中断请求(FIQ)、矢量中断请求(IRQ)和非矢量中断请求。LPC214x中的所有中断都有一个可编程设置,即中断的优先级可以动态设置。

在这三类请求中,FIQ请求的优先级最高,矢量IRQ请求的优先级中等,非矢量IRQ请求的优先级最低。

当我们讨论“矢量”和“非矢量”IRQ请求时,我们实际上是在讨论ISR的地址。对于矢量IRQ请求,CPU知道ISR。一个叫做中断矢量表(IVT)的特殊表包含了所有关于矢量IRQ的信息。这些信息可以是关于中断的来源,IRQ请求的ISR地址等。

因此,每个矢量IRQ都有自己唯一的ISR地址。在32个可能的中断请求中,有16个中断请求可以定义为矢量IRQ。在这16个插槽中,可以分配LPC2148中可用的22个中断中的任何一个。在16个vector IRQ槽位中,槽位0的优先级最高,槽位16的优先级最低。

在非矢量IRQ的情况下,正如它的名字所表明的那样,CPU不知道中断的来源或中断的ISR地址。在这种情况下,必须为CPU提供一个默认的ISR地址。对于处理非矢量IRQ请求,在LPC2148中有一个叫做“VICDefVectAddr”的特殊寄存器。默认ISR的地址必须由用户在这个寄存器中给出,以便处理非矢量IRQ请求。

请注意所有的非矢量IRQ请求都有相同的ISR地址,ISR地址在VICDefVectAddr寄存器中定义。

LPC2148中的中断相关寄存器

有许多寄存器与矢量中断控制器(VIC)相对应。这些寄存器要么用于配置中断,要么用于读取中断状态。关于所有与VIC相关的寄存器,要记住的重要一点是,在所有VIC寄存器中,每个比特都与一个特定的中断源相关联。位0与与看门狗定时器相对应的中断相关联,在所有VIC相关寄存器中都是相同的。

下表显示了LPC2148中22个中断源的列表以及它们在VIC寄存器中对应的位位置。

位# 22 21 20. 19 18 17 16 15 14 13 12 11
硬中断请求优先级别 USB AD1 生化需氧量 I2C1 AD0 EINT3 EINT2 EINT1 EINT0 清债信托公司 锁相环 SPI1 / SSP
位# 10 9 8 7 6 5 4 3. 2 1 0
硬中断请求优先级别 SPI0 I2C0 脉宽调制 UART1 UART0 TIMER1 TIMER0 ARMCore1 ARMCore0 N/A WDT

下面是LPC214x系列mcu中与中断相关联的寄存器列表和描述。在所有可用的维也纳国际中心登记册中,这里提到的登记册只是少数几个重要的登记册,也是开始了解维也纳国际中心的最佳登记册。

  • 软件中断寄存器(VICSoftInt):软件中断寄存器(Software Interrupt Register)用于在外部源屏蔽之前,用软件即代码手动生成中断。当VICSoftInt寄存器中的一个位设置为1时,即使没有任何外部源,也会触发相应的中断。
  • 软件中断清除寄存器(VICSoftIntClear):软件中断清除寄存器用于清除软件中断寄存器设置的位。当一个位在这个寄存器中被设置为1时,相应的位在软件中断寄存器中被清除,因此释放强制中断。
  • 中断使能寄存器(VICIntEnable)中断启用寄存器是用来启用中断的,这些中断之后可能会导致FIQ或IRQ。当位设置为1时,相应的中断被启用。由于这是一个读/写寄存器,当这个寄存器被读时,“1”表示外部中断请求或软件中断被启用。
  • Interrupt Enable Clear Register (VICIntEnClear)功能:中断使能清除寄存器用于清除中断使能清除寄存器设置的位,即用于禁用中断。当一个位设置为“1”时,寄存器允许软件清除中断使能寄存器中相应的位,从而禁用该特定请求的中断。
  • 中断选择寄存器(VICIntSelect)中断选择寄存器(Interrupt Select Register)用于将32个中断分类为FIQ或IRQ。当这个寄存器中的一个位被设置为“0”时,相应的中断(如上表所示)将作为一个IRQ。类似地,当某位设置为“1”时,相应的中断作为FIQ。
  • IRQ状态寄存器(VICIRQStatus)中断状态寄存器(Interrupt Status Register)用于读取启用并声明为IRQ的中断的状态。矢量和非矢量的IRQ都被读出。当一个比特被读为“1”时,相应的中断被启用,并被定义为IRQ。
  • FIQ状态寄存器(VICFIQStatus):这个寄存器类似于IRQ状态寄存器(VICIRQStatus),除了它读取被启用并定义为FIQ的中断的状态。
  • 病媒控制登记册(VICVectCntl0 - VICVectCntl15)矢量控制寄存器用于分配插槽给不同的中断源,这些中断源被分类为IRQ。有16个矢量控制寄存器,每个寄存器控制16个矢量IRQ插槽中的一个。优先级最高的是VICVectCntl0 (Slot 0),优先级最低的是VICVectCntl15 (Slot 15)。矢量控制寄存器(位0 -位4)的前5位包含中断请求的数字。5th位(第5位)用于启用矢量IRQ插槽。下面的表格是用来显示中断源和它们对应的十进制格式的源号。
中断源 源数
在十进制
WDT 0
N/A 1
ARMCore0 2
ARMCore1 3.
TIMER0 4
TIMER1 5
UART0 6
UART1 7
脉宽调制 8
I2C0 9
SPI0 10
SPI1 11

中断源 源数
在十进制
锁相环 12
清债信托公司 13
EINT0 14
EINT1 15
EINT2 16
EINT3 17
ADC0 18
I2C1 19
生化需氧量 20.
ADC1 21
USB 22

例如,如果我们想将Slot 0分配给Timer0 IRQ,那么矢量控制寄存器必须声明如下:

VICVectCntl0 = 0x20 | 4;

请注意:当一个矢量IRQ在任何VICVectCntl0 - 15寄存器中被禁用时,它将不会禁用实际的中断,但矢量IRQ被更改为非矢量IRQ。

  • 矢量地址寄存器(VICVectAddr0 - VICVectAddr15):矢量地址寄存器用于保存16个矢量IRQ插槽的ISR地址。如果Slot 0 (VICVectCntl0)被分配给TIMER0 IRQ,那么中断功能的地址必须分配给VICVectAddr0。
  • 默认矢量地址寄存器(vicdefvecaddr):默认向量地址寄存器保存非向量irq的ISR地址。当非矢量IRQ发生时,这个地址充当默认的或通用的ISR地址。
  • 矢量地址寄存器:这是一个不同的单一寄存器,不能与矢量地址寄存器(VICVectAddr0 - VICVectAddr15)混淆。它是一个读/写寄存器,当从这个寄存器读取数据时,它返回ISR地址。向寄存器写入一个值向VIC表明当前中断的执行已经结束。因此,这个寄存器在ISR的末尾用一个哑值来表示执行的结束。

在LPC2148中配置中断

现在我们已经看到了与VIC相关联的不同寄存器的列表和功能,我们将看到如何配置中断和定义各自的isr。首先,我们将看到如何正确地定义ISR函数,以便编译器理解它是一个ISR,但不是一个常规函数。

在Keil IDE中,我们可以用两种方式定义ISR,在这两种情况下,我们都需要使用关键字" __irq "。

//定义ISR的第一种方法

__irq void userISR (void)

/////////

//或以下方式定义ISR

userISR (Void) __irq

///////

定义ISR之后,现在我们将设置中断。例如,考虑我们想要分配TIMER0 IRQ和对应的ISR到Slot 0。为此,我们需要遵循三个步骤。

  • 启用TIMER0 IRQ(使用VICIntEnable寄存器)
  • 分配Slot 0到TIMER0 IRQ(使用一个VICVectCntl0 - 15寄存器)
  • 分配ISR地址(使用一个VICVectAddr0 - 15寄存器)

基于以上步骤,必须进行以下分配来设置中断。

VICIntEnable | = (1<<4);

VICVectCntl0 = 0x20 | 4;

VICVectAddr0 =(无符号)userISR;

LPC2148中使用中断的示例程序

现在,我们将看到一个在LPC2148单片机中使用中断的示例程序。我们将使用定时器来产生延迟和定时器中断来闪烁led。

# include < lpc214x.h >

#定义了0 xffffffff;

int z = 0;

/*定时器函数的函数定义

无效计时器(空白)

T0CTCR = 0 x00;

T0PR = 60000 - 1;

T0TCR = 0 x02;

T0MR0 = 1000 - 1;

T0mcr = (1<<0) | (1<<1);

/*延迟函数的函数定义

Void delay (int d)

T0TCR = 0 x02;

T0TCR = 0 x01;

while (T0TC < d);

T0TCR = 0 x00;

/*中断的ISR

__irq void timerISR

长int val;

val = T0IR;

如果(z = = 0)

IOSET1 =领导;

其他的

IOCLR1 =领导;

z = ~ z;

T0IR = val;

VICVectAddr = 0 x00;

/*中断函数的函数定义

无效中断(空白)

VICIntSelect = 0 x00;

VICIntEnable | = (1 < < 4);

VICVectCntl0 = 0x20 | 4;

VICVectAddr0 =(无符号)timerISR;// ISR指针

int main ()

PINSEL2 = 0 x00;

IODIR1 =领导;

/*使能PLL块并设置CCLK和PCLK到60 MHz */

PLL0CON = 0 x01;

PLL0CFG = 0 x24;

PLL0FEED = 0 xaa;

PLL0FEED = 0 x55;

而(!(PLL0STAT & 0 x00000400));

PLL0CON = 0 x03;

PLL0FEED = 0 xaa;

PLL0FEED = 0 x55;

VPBDIV = 0 x01;

/*调用Timer函数*/

计时器();

/*调用中断函数*/

中断();

/*开启定时器*/

T0TCR = 0 x01;

(1);

2反应

留下一个回复

你的电邮地址不会被公布。

Electronicshub图标
Baidu
map