7

我目前正在处理 lpc2378 上的一些 ARM 汇编程序,但是我编写了一个循环来控制炉子的温度;我相信我需要实现某种中断处理来完成我的项目。

当应用程序运行时,它进入一个循环,等待 Button_1 输入,然后循环继续并经过各个阶段,但无法等待 Button_2 输入以使应用程序运行。

所以这里有几个问题,中断处理程序究竟是如何工作的?以及如何将它实现到我的应用程序中。

这是我的 Button_1 代码:

;=========================================================================
; Wait for BUT1 to be pressed
;=========================================================================
WaitBUT1
  STMFD r13!,{r0,r5,r14}   ; Push r0, r5 and LR

WaitForBUT1Pressed
    ldr r0, = IO0PIN            ; Address of FIO0PIN register 
    ldr r1, [r0]                ; Read FIO0PIN in to r1
    ands r1, r1, # B1_MASK      ; Mask out BUT1
    beq BUT1Pressed             ; Exit LED toggle loop if button is pressed
    B WaitForBUT1Pressed
BUT1Pressed

  LDMFD r13!,{r0,r5,r14}   ; Pop r0, r5 and LR
  mov pc, r14              ; Put link register back into PC

和我的 Button_2 代码:

;=========================================================================
; Wait for BUT2 to be pressed
;=========================================================================
WaitBUT2
  STMFD r13!,{r0,r5,r14}   ; Push r0, r5 and LR

WaitForBUT2Pressed
    ldr r0, = IO0PIN            ; Address of FIO0PIN register 
    ldr r1, [r0]                ; Read FIO0PIN in to r1
    ands r1, r1, # B2_MASK      ; Mask out BUT1
    beq BUT2Pressed             ; Exit LED toggle loop if button is pressed
    B WaitForBUT2Pressed
BUT2Pressed

  LDMFD r13!,{r0,r5,r14}   ; Pop r0, r5 and LR
  mov pc, r14              ; Put link register back into PC

还有我的炉子控制回路:

LoopStart

   BL WaitBUT1 ; wait until button 1 is pressed
   BL heaterOn ; turn heater on
   BL systemLedOn ; turn system LED on
   BL readTemp ; Check ADC for temp
   BL checkTemp ; Count down, check ADC for temp
   CMP r3, #5 ; Compare timer with delay
   BGT errorVal
   SUBS r4, r2, r7  ;Performs r7 = r4 - r2 and sets condition register
   BEQ LoopStart ; if equal nothing to do
   BGT overTemp ; r7 < 0 case
   BL errorLedOn
   BL heaterOn
   BL FanOff
   B LoopStart

overTemp
   BL errorLedOn
   BL heaterOff
   BL FanOn
   B LoopStart


   BL WaitBUT2
   BL FanOff
   BL errorLedOff
   BL systemLedOff
   BL heaterOff

       B LoopStart

提前致谢。

4

2 回答 2

12

如果您还没有它,您需要获取 ARM ARM(ARM 架构参考手册)。过去只有一个,但现在有这么多内核,他们不得不将其拆分为不同的架构。 http://infocenter.arm.com 左侧是 ARM 架构,然后是参考手册,然后是 ARMv5,是的,我知道你有一个 ARMv4 (ARM7TDMI)。ARMv5 手册是过去的手册。

它将涵盖异常向量等。

您可能已经知道,在启动时,地址 0x00000000 处的指令被执行。对于中断,调用地址 0x00000018 处的指令。

.globl _start
_start:
    b   reset     ;@ 0x00000000 reset
    b   handler   ;@ 0x00000004 undefined instruction
    b   handler   ;@ 0x00000008 software interrupt swi
    b   handler   ;@ 0x0000000C prefetch abort
    b   handler   ;@ 0x00000010 data abort
    b   handler   ;@ 0x00000014 dont know
    b    irq_handler   ;@ 0x00000018 irq
    b   handler   ;@ 0x000000

从 ARM ARM,您还应该看到寄存器被分组,特别是 r13 堆栈指针,在中断模式下有一个单独的堆栈指针。因此,在启动时,当您设置正常堆栈时,您还想为中断堆栈设置一些空间。

reset:
;@//mov r0, #(PSR_IRQ_MODE|PSR_FIQ_DIS|PSR_IRQ_DIS)
mov r0,#0xD2
msr cpsr_c, r0
ldr sp, =0xD600C000

;@//mov r0, #(PSR_SVC_MODE|PSR_FIQ_DIS|PSR_IRQ_DIS)
mov r0,#0xD3
msr cpsr_c, r0
ldr sp, =0xD600B000

在某些时候,您需要在 cpsr 中启用中断。您可能会一直等待,直到您启用了任何外围设备(芯片中,内核外部)中的任何中断。

;@ SVC MODE, IRQ ENABLED, FIQ DIS
mov r0,#0x53
msr cpsr_c, r0

您需要阅读 lpc 部分的手册以了解如何启用中断,以及如何在中断发生时清除中断。

您需要在中断处理程序中做的第一件事(您分支到地址 0x18 的代码)是保留堆栈上的共享(非存储)寄存器,这样您就不会弄乱它们。如果您在返回被中断的代码时不这样做,则寄存器将发生变化,并且该代码可能无法正常工作。由于您的项目似乎在 ASM 中,因此您可以在应用程序中使用一些寄存器并仅为 isr 保留一些寄存器,而不必设置堆栈。如果要在处理程序中的任何位置使用 bl,则需要将 lr 保存在堆栈中。

在某些时候,您的处理程序需要清除外围设备中的中断,以便在下一次中断之前不会再次触发,为此必须阅读 lpc 手册。是的,当我说 lpc 时,我的意思是 NXP 以前是飞利浦……

最后一件事是,如果你按下 lr,弹出它,如果你按下了其他寄存器,则弹出它们,然后使用这个确切的指令,手臂将返回并将模式切换回被中断的模式(切换到使用那些银行寄存器)。

subs pc,lr,#4

请注意,您可能还需要获取特定内核的 TRM(技术参考手册)(在您的情况下为 ARM7TDMI-S),通常使用 ARM 是一个好主意。在信息中心页面上,左侧转到 ARM7 处理器,不是架构下的 ARMv7,而是较低的,它有 ARM11、ARM9、ARM7。

按钮在弹跳时可能会因中断而变得混乱,并在 I/O 引脚上产生许多边沿。查看您的其他帖子,我看不出您需要在哪里打断。除非另有必要,否则您通常应避免中断。他们一般都很乱。当然,有些设计是您无法避免使用的。还有一些事件驱动的设计,你的所有代码都是中断处理程序,应用程序中除了启动代码和无限循环(或某种睡眠)之外什么都没有。

您可以使用中断来消除抖动,例如,如果您设置定时器中断并对中断中的按钮的 I/O 引脚进行采样,您可以避免大量的抖动,但您也有可能错过按钮按下的风险. 仅仅因为按钮 I/O 引脚连续两次被断言为两次中断,而不是两次按下,所以您在某处更改了状态变量,当按钮被释放时,您更改了状态变量。该状态变量的边缘变化对应用程序很感兴趣。当按钮从未按下变为按下时,做一些事情,如果它从按下变为未按下,则不做任何事情,等待它从未按下变为按下为例。

您还可以使用相同的定时器中断来启动或采样 adc。

由于您还没有解决这里也提到的其他问题,所以我不会靠近中断。先弄清楚这个问题,然后再决定是否有需要中断的功能。就像对 adc 的偶数/常规采样一样。

这应该足以让你开始。如果您确实尝试了中断,请勿将它们作为此应用程序的一部分进行尝试,请创建一个完全独立的应用程序,例如 LED 闪光灯。在中断处理程序中更改 LED 的状态,和/或更改处理程序中的全局变量或寄存器,并让前台监视并因此更改 LED。始终将您的问题/学习练习分成单独的部分,解决这些问题,然后将它们粘合在一起,添加一件,测试,添加一件,测试。

于 2012-05-18T07:03:39.280 回答
1

在这种情况下,似乎不需要中断处理程序,您可以简单地在主循环中轮询按钮 2,而不是使用“等待”功能。将此添加到循环的末尾:

ldr r1, [r0]                ; Read FIO0PIN in to r1
ands r1, r1, # B2_MASK      ; Mask out BUT1
beq STOP

其中 STOP 是执行安全关闭熔炉的目标(即不会让它无限期地运行)。

请注意,您的循环包括等待 button1 - 肯定应该在之前 LoopStart?否则,控制循环将在每次迭代时等待按钮按下而不执行任何控制动作——如果最后一个动作是heaterOn!

除此之外,注意在 ARM-Cortex 内核之前(LPX2378 是一个 ARM7TDMI-S 内核),ARM 内核只定义了两个中断源 IRQ 和 FIQ,大多数部分在 ARM 内核外部都有一个单独的中断控制器,而这个中断控制器是特定于供应商的。因此,要确定您如何处理例如 GPIO 中断,您需要参考设备的参考手册而不是 ARM 文档。

基于 ARM Cortex-M 的设备正在迅速取代 ARM7 设备,使用这样的设备可能会更好。特别是中断处理更加直接、灵活和高效。请参阅这篇文章,了解 Cortex-M 如何在 ARM7 上进行改进。

于 2012-05-19T09:24:29.010 回答