ich versuche mich gerade im Simulator an einem ATMega4809, da ich plane, den Arduino Nano Every für ein Projekt zu verwenden.
Mit den ATMega-Controllern bin ich ganz gut vertraut, aber beim 4809er schaffe ich es nicht, den externen Interrupt korrekt zu programmieren.
; --- main.asm ---
1
#define Value R16
2
#define Status R17
3
#define HighByte R18
4
#define LowByte R19
5
6
.cseg
7
.org 0x0000 rjmp reset
8
.org 0x000C rjmp setPointAcquisition_Triggered
9
10
reset:
11
ldi HighByte, HIGH(RAMEND)
12
out CPU_SPH, HighByte
13
ldi LowByte, LOW(RAMEND)
14
out CPU_SPL, LowByte
15
16
rcall setPointAcquisition_Initialize
17
18
sei
19
20
main:
21
jmp main
22
23
.include "m4809def.inc"
24
.include "setPointAcquisition.asm"
; --- setPointAcquisition.asm ---
1
.include "m4809def.inc"
2
3
.equ SetPointInputPort = PORTA_PIN0CTRL
4
.equ SetPointInputPin = 0x1
5
6
setPointAcquisition_Initialize:
7
lds Value, SetPointInputPort
8
sbr Value, SetPointInputPin
9
sts SetPointInputPort, Value
10
11
ret
12
13
setPointAcquisition_Triggered:
14
push Value
15
lds Status, CPU_SREG_offset
16
17
sts CPU_SREG_offset, Status
18
pop Value
19
20
reti
Ich möchte PortA0 als externen Interrupt programmieren, um einen Sollwert zu erfassen (PWM Signal). Wenn ich im Simulator das entsprechende Pin0 auf HIGH setze, springt der Programmzähler korrekt in die ISR hinein und der Controller arbeitet diese ab. Nach dem der Programmzähler die ISR verlassen hat, springt er sofort wieder hinein - obwohl ich nur auf die Flanken triggere.
Gibt es bei diesem Controller irgendwelche Besonderheiten, was den externen Interrupt betrifft?
du musst das Interrupt Flag zurücksetzen. Das machen die neuen Controller zu 99,9% nicht mehr automatisch. Also ohne Manual lesen pauschal selbst zurücksetzen.
habe das mal übersetzt in direkte Register... das funktioniert mit echten Every Board. Kabelbrücke zwischen PB0 und PD3, dann takten beide Ausgänge syncron mit "both edges". Solltest du in Assembler übersetzen können. :-)
1
#include<avr/interrupt.h>
2
#include<util/delay.h>
3
4
// PB0 - Arduino Pin 9
5
// PE2 - Arduino Pin 13
6
// PD3 - Arduino Pin 14
7
8
#define F_CPU 3333333UL
9
10
intmain(void)
11
{
12
VPORTB.DIR&=PIN0_bm;// Input
13
PORTB_PIN0CTRL=0;//
14
PORTB_PIN0CTRL|=PORT_PULLUPEN_bm;//
15
PORTB_PIN0CTRL|=0x01;// Interrupt enabled with sense on both edges
Lässt sich der Nano Every mit AVR Studio direkt
flashen?
Nein, du kannst aber mit AVR Dude arbeiten, dass funktioniert, ist aber nicht komfortabel. Alternativ, die UPDI Schnittstelle auf dem Board anlöten/kontaktieren und den Mega4809 direkt ansprechen.
AVR Dude installieren und der Path-Variable zufügen, schauen an welchem COM-Port sich der Every anmeldet und dann noch den Pfad zum Hex-File anpassen. Fuses nach bedarf, in diesem Code wird der interne OSC von 16MHz auf 20MHz geschraubt. Achtung, der COM-Port muss 3x geändert werden, ich habe mich noch nicht damit beschäftigt, eine Art #define dafür zu machen.
lds Value, PORTA_INTFLAGS
cbr Value, 0x01
sts PORTA_INTFLAGS, Value
einfach
ldi Value,0x01
out PORTA_INTFLAGS,Value
Die Sequenz des ganz oben lädt alle Flags, löscht dann das 0-te und schreibt zurück. Damit werden alle gesetzten Flags resettet außer dem eigentlich gewünschten.
wegen Interrupt Flag zurücksetzen. Nichts von Hand irgendwie manipulieren. Einfach an die gewünschte Bitposition sturr "1" reinschreiben. Mehr muss nicht beachtet oder gemacht werden.
1
Bits 7:0 – INT[7:0] Pin Interrupt Flag
2
Pin interrupt flag n is cleared by writing a ‘1’ to it.
3
Pin interrupt flag n is set when the change or state of pin n (Pxn) matches the pin's Input/Sense Configuration (ISC)
4
in PORTx.PINnCTRL.
5
Writing a ‘0’ to bit n in this bit field has no effect.
6
Writing a ‘1’ to bit n in this bit field will clear Pin interrupt flag n.
Wie vorher braucht man für UPDI auch nur einen USB/seriell-Umsetzer
(z.B. CP2102) und eine Diode oder Widerstand.
Alles richtig. Es ging mir zu zeigen das man in AS einen eigenen Menüeintrag erstellen kann um die Kommandozeile zu hinterlegen. Für fertige Arduino xyz Boards wird nur ein USB Kabel benötigt. Beim Every ist der UPDI Übersetzer auf dem Board. Wie bei den MC Curiosity Boards.
wegen Interrupt Flag zurücksetzen. Nichts von Hand irgendwie
manipulieren. Einfach an die gewünschte Bitposition sturr "1"
reinschreiben. Mehr muss nicht beachtet oder gemacht werden.
1
> Bits 7:0 – INT[7:0] Pin Interrupt Flag
2
> Pin interrupt flag n is cleared by writing a ‘1’ to it.
3
> Pin interrupt flag n is set when the change or state of pin n (Pxn)
4
> matches the pin's Input/Sense Configuration (ISC)
5
> in PORTx.PINnCTRL.
6
> Writing a ‘0’ to bit n in this bit field has no effect.
7
> Writing a ‘1’ to bit n in this bit field will clear Pin interrupt flag
8
> n.
9
>
Willkommen im Club, oder "Man lernt nur durch Wiederholung". Steht alles schon oben.
Die Frage ist, ob der TO das auch liest.
Ja, war leider nicht ganz korrekt, weil damit evtl. weitere Flags gelöscht werden; korrekt ist das direkte, einfache Setzen des Bits im Register (also ohne vorheriges Lesen), wie von Wilhelm M. vorgestellt.
Nochmal zum 'cbr' (wie auch 'sbr'): das ist kein richtiger Befehl, sondern genaugenommen ein Artefakt des Assemblers - erkennbar im 'AVR® Instruction Set Manual', denn dort wird hierfür kein Maschinencode gezeigt.
Und stiftet nur Verwirrung, falls man sich an 'sbi' oder 'cbi' orientiert.
Nochmal zum 'cbr' (wie auch 'sbr'): das ist kein richtiger Befehl,
sondern genaugenommen ein Artefakt des Assemblers -
erkennbar im 'AVR® Instruction Set Manual', denn dort wird hierfür kein >Maschinencode gezeigt.
Wieso kein Maschinencode. Bei mir steht da
16-bit Opcode: 1001 1000 AAAA Abbb
Finden Sie nicht auch, nach näherer Betrachtung, dass Ihr Beitrag zum Thema etwas dürftig ausgefallen ist?
Und da gleich zu Beginn offensichtlich war, dass es hier um Assembler geht, frage ich mich, weshalb Sie sich bis hier unten, durch dreißig Beiträge, "gequält" haben.