我目前正在使用lpc2378上的一些ARM Assembler,我写了一个循环来控制炉子的温度;我相信我需要实现某种中断处理来完成我的项目。
当应用程序运行时,它进入循环,等待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
提前致谢。
答案 0 :(得分:11)
如果您还没有,则需要获取ARM ARM(ARM架构参考手册)。过去只有一个,但现在有很多核心,他们不得不将它拆分为不同的架构。 {@ 3}}左侧是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我的意思是恩智浦以前的飞利浦...
最后一件事是如果你按下lr,弹出它,然后弹出其他寄存器,如果你按下它们,然后使用这个确切的指令,手臂将返回并将模式切换回被中断的模式(切换到使用那些存储的寄存器)。
subs pc,lr,#4
注意您可能还需要,对于ARM来说,获取特定内核的TRM(Techincal Reference Manual)通常是一个好主意,在您的情况下是ARM7TDMI-S。在信息中心页面上,左侧是ARM7处理器,而不是架构下的ARMv7,而是ARM11,ARM9,ARM7的较低位置。
按钮可能会因中断而混乱,因为它们反弹并在I / O引脚上产生许多边沿。看看你的另一篇文章,我看不到你需要中断的地方。除非另有必要,否则通常应避免中断。他们一般都很乱。当然,有些设计你不能避免使用它们。并且存在事件驱动的设计,其中所有代码都是中断处理程序,应用程序中没有任何内容,但启动代码和无限循环(或某种类型的睡眠)。
你可以使用中断进行去抖动,例如,如果你设置了一个定时器中断并为中断中的按钮采样I / O引脚,你可以避免相当多的弹跳,但你也有可能丢失按下按钮。只是因为按钮I / O引脚被断言连续两次中断,而不是两次按下,你在某处更改状态变量,当释放按钮时,你改变状态变量。该状态变量的边缘变化是应用程序感兴趣的。当按钮从未按下状态变为按下状态时,执行某些操作,如果从按下按下到未按下状态,则不执行任何操作,等待它从未按下状态更改为按下按下状态。
您也可以使用相同的计时器中断来启动或采样adc。
由于你还没有解决你在这里提到的其他问题,我不会接近中断。首先解决问题,然后确定是否存在需要中断的功能。就像adc的偶数/定期采样一样。
这应该足以让你开始。如果您尝试中断,请不要尝试将它们作为此应用程序的一部分,创建一个完全独立的应用程序,例如LED闪光灯。更改中断处理程序中的led状态,和/或更改处理程序中的全局变量或寄存器,并为其指定forground并更改led作为结果。总是将你的问题/学习练习分成单独的部分,然后解决它们然后将它们粘在一起添加一块,测试,添加一块,测试。
答案 1 :(得分: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的信息,请参阅this article。