ATmega128 External Interrupt Problem

OP #5584219
Lesenswert?

Hallo,

ich habe vor Kurzem mit Assembler angefangen und bin nun bei Interrupts 
angelangt.
Dazu habe ich ein kurzes Beispielprogramm geschrieben, nur funktioniert 
es nicht so wie ich es mir vorstelle.

Ich habe PORTA als Output und PE6 als Input für den Interrupt 
eingestellt. Eigentlich wollte ich, dass PORTA bei jedem Interrupt eins 
hochzählt.
Stattdessen leuchtet PORTA die ganze Zeit, nur beim Interrupt wird das 
Muster 0x55 angezeigt. Mehr oder weniger das Gegenteil von dem was ich 
wollte.

Ich probiere jetzt schon seit Stunden herum und habe auch schon im 
Internet gesucht, aber finde den Fehler leider nicht.
Ich benutze einen Atmega128 auf einem BIGAVR6.

Vielleicht kann mir jemand helfen, bin schon total verzweifelt.
1
.NOLIST
2
.INCLUDE "m128def.inc"
3
.LIST
4

5
.equ    temp, 0x10
6

7
.text
8
.org    0x00
9
    jmp    init
10
.org    INT6addr*2
11
    jmp    int6
12

13
.text
14

15
init:
16
    ldi    temp, lo8(RAMEND)
17
    out    SPL, temp
18
    ldi    temp, hi8(RAMEND)
19
    out    SPH, temp
20

21
    ldi    temp, 0x00
22
    out    DDRE, temp  
23
    out   PORTE, temp
24
  
25
    ldi    temp, 0xff
26
    out    DDRA, temp  
27
  
28
    ldi    temp, 1<<PE6  
29
    out    PORTE, temp
30

31
    lds    temp, EICRB
32
    ori    temp, 1<<ISC61
33
    sts    EICRB, temp
34

35
    in     temp, EIMSK
36
    ori    temp, 1<<INT6
37
    out    EIMSK, temp  
38
  
39
    ldi    temp, 0x55
40
    out    PORTA, temp
41

42
    sei              
43

44
    ldi    temp, 1<<SE
45
    out    MCUCR, temp
46

47
main:  
48
    sleep
49
    rjmp   main
50
  
51
int6:
52
    in     temp, PORTA
53
    dec    temp  
54
    out    PORTA, temp  
55
    reti
Gast #5584277
Lesenswert?

Stefan F. schrieb:
> .org    INT6addr*2

In so einem Fall sieht man sich die Herkunft des Symbols an, es muss ja 
irgendwo definiert worden sein, also öffnet man die zugehörige *.inc und 
findet dort:

> .equ INT6addr = $00e

Da hat doch tatsächlich jemand berücksichtigt, dass es bei diesem 
Controllertyp mehr Speicher für die IVT braucht. Mit mal 2 definierst Du 
einen anderen Interrupt und wo der richtige stehen sollte, ist's leer, 
bzw. fordert den Controller zum Reset auf.

Stefan F. schrieb:
> Dirk schrieb:
>> .org nt6addr *1
>> probiert?
>
> Ja, brachte leider nichts.

Falscher Controller eingestellt?
OP #5584306
Lesenswert?

MWS schrieb:
> Stefan F. schrieb:
>> .org    INT6addr*2
>
> In so einem Fall sieht man sich die Herkunft des Symbols an, es muss ja
> irgendwo definiert worden sein, also öffnet man die zugehörige *.inc und
> findet dort:
>
>> .equ INT6addr = $00e
>
> Da hat doch tatsächlich jemand berücksichtigt, dass es bei diesem
> Controllertyp mehr Speicher für die IVT braucht. Mit mal 2 definierst Du
> einen anderen Interrupt und wo der richtige stehen sollte, ist's leer,
> bzw. fordert den Controller zum Reset auf.

Ok, klingt einleuchtend. Danke schonmal.
Aber aus irgendeinem Grund funktioniert es nicht. Wenn ich den Button an 
PE6 drücke ändert sich leider nichts.

> Stefan F. schrieb:
>> Dirk schrieb:
>>> .org nt6addr *1
>>> probiert?
>>
>> Ja, brachte leider nichts.
>
> Falscher Controller eingestellt?

Habe es gerade noch mal kontrolliert, ist auch der Richtige.
Gast #5584310
Lesenswert?

SEI steht übrigens falsch, besonders da temp auch in der ISR Verwendung 
findet. Nimm an dass EIFR.INTF6 zu diesem Zeitpunkt gesetzt ist, dann 
sollte der Controller unmittelbar nach SEI den Int6-Vektor ausführen.
Macht er das, dann wäre alles noch gut.

Wenn er jedoch noch ldi temp, 1<<SE abarbeitet und erst dann den Vektor 
anspringt, dann wird temp zerstört und mit dem Inhalt des PORTA geladen.

Dieser Inhalt setzt nicht mehr MCUCR.SE, sondern macht irgendwas anderes 
recht Lustiges.

Stefan F. schrieb:
> sei
> ldi    temp, 1<<SE

> int6:
> in     temp, PORTA

Sowas vermeidet man, indem man a) INTF6 vor Freigabe der Interrupts 
löscht, b) Konfigurationssequenzen atomar macht (CLI/SEI) oder c) SEI 
erst dann schreibt, wenn man mit der Konfiguration durch ist. Auch a, b 
und c zusammen ist nicht verkehrt.
(Firma: Vescomp) #5584336
Lesenswert?

Stefan F. schrieb:
> Aber aus irgendeinem Grund funktioniert es nicht. Wenn ich den Button an
> PE6 drücke ändert sich leider nichts.

 Dann lese doch in einem Loop mit PINE.6 was dein uC am Pin sieht und
 zeige es mit LED an PORTA (LED=ON / Pin = 1). Oder umgekehrt, egal.

 Wenn die LED nicht auf Button reagiert, stimmt irgendetwas mit Pull-Up
 bzw. Eingang nicht.
 Wenn die LED reagiert, stimmt irgendetwas mit deinem INT nicht.

 So schwer ?

 P.S.
 Bedenke aber, dass 0xFF von uC als NOP gesehen wird.
Beitrag #5584533 wurde von einem Moderator gelöscht.
Gast #5584911
Lesenswert?

Marc V. schrieb:

>  Bedenke aber, dass 0xFF von uC als NOP gesehen wird.
das könnte zumindest die Belanglosigkeit *1/*2 in dem frühem Stadium 
erklären wenn, bzw. da mangels Alternativen, $ffff (eigentlich UOP) als 
NOP ($0000) gesehen wird und interessante Folgen (bei allen ints 
passiert das gleiche, obwohl es funktioniert hat) verursachen.

Noch ein Bedenkungsvorschlag:
falls sich der Bezeichner EICRB als minderwertig (<$40) herausstellen 
sollte bspw. als $3a  Wert, dann  wäre
out    DDRA, temp; $1a sts $1a+$20,temp
und
sts    EICRB, temp;$3a out $1a,temp
äquivalent und
out   EICRB, temp;$3a
für den mutmaßlichen Plan geeigneter
OP #5586049
Lesenswert?

Dirk B. schrieb:
> Marc V. schrieb:
>
>>  Bedenke aber, dass 0xFF von uC als NOP gesehen wird.
> das könnte zumindest die Belanglosigkeit *1/*2 in dem frühem Stadium
> erklären wenn, bzw. da mangels Alternativen, $ffff (eigentlich UOP) als
> NOP ($0000) gesehen wird und interessante Folgen (bei allen ints
> passiert das gleiche, obwohl es funktioniert hat) verursachen.
>
> Noch ein Bedenkungsvorschlag:
> falls sich der Bezeichner EICRB als minderwertig (<$40) herausstellen
> sollte bspw. als $3a  Wert, dann  wäre
> out    DDRA, temp; $1a sts $1a+$20,temp
> und
> sts    EICRB, temp;$3a out $1a,temp
> äquivalent und
> out   EICRB, temp;$3a
> für den mutmaßlichen Plan geeigneter


Danke für euren Input. Dadurch hab ich den Fehler gefunden.

Statt
1
lds    temp, EICR
2
ori    temp, 1<<ISC61
3
sts    EICRB, temp

gehört nämlich.
1
in    temp, EICR
2
ori    temp, 1<<ISC61
3
out    EICRB, temp

Wieder was gelernt.
Danke nochmal allen die mir geholfen haben.
Gast #5586170
Lesenswert?

Dass das der ursprüngliche Fehler gewesen sein soll, kann ich nicht 
glauben. Wie Dirk B. schrieb, wird mit
1
lds    temp, EICRB
2
ori    temp, 1<<ISC61
3
sts    EICRB, temp
DDRA verändert, da dieses jedoch bereits auf 0xFF steht, bewirkt das 
ori gar nichts. Und dass EICRB nicht beschrieben wird, heißt 
lediglich, dass INT6 nicht durch 'falling edge', sondern durch 'low 
level' getriggert wird. Statt einige Male durch das Prellen wird also 
vielfach, solange der Taster gedrückt ist, getriggert, wie ließe sich 
damit die Aussage

> Stattdessen leuchtet PORTA die ganze Zeit, nur beim Interrupt
> wird das Muster 0x55 angezeigt.

erklären?
Gast #5586206
Lesenswert?

Hallo,

wenn man mal endlich den kompletten Code mit allen Zeilen sehen könnte.
Dann noch das Makefile dazu und jeder könnte gegen testen.

Wir verwenden solch zwei Macros für das Lesen und Setzen der Register, 
dann spart man sich das nachsehen für jeden AVR µC in der 
Registerbeschreibung.
1
.macro xIn
2
.if @1<64
3
in    @0,@1
4
.else
5
lds    @0,@1
6
.endif
7
.endmacro
8

9
.macro xOut
10
.if @0<64
11
out    @0,@1
12
.else
13
sts    @0,@1
14
.endif
15
.endmacro
Gast #5586218
Lesenswert?

... was sich speziell beim ATmega128 empfiehlt, denn hier ist die 
Zuordnung doch etwas wirr, so liegt z.B., wie gesehen, EICRB mit 0x3A im 
I/O-Bereich, EICRA hingegen ist mit 0x6A 'memory mapped'.
Gast #5586302
Lesenswert?

S. Landolt schrieb:
> Dass das der ursprüngliche Fehler gewesen sein soll, kann ich nicht
> glauben.
bislang sind 3 bekannt:
1)INT6addr*2: wg. NOP Lesung von UOP wohl praktisch folgenlos
2)praktisch Level statt Flanke (aktuell bzw. aktuell nicht mehr)
3) SEI zum unglücklichen Zeitpunkt. Getriggert könnte MCUCR ca. mit 
$55-1 initialisiert werden und das MCUCR hat auch 
Interruptvectorselect...für 'ne abschließende Erklärung noch zu knapp, 
aber evtl. interrupt via bootloadervector --> Nop/UOP-Slide-->reset .org 
0 (aus vector_table_0)
vom Gefühl dürfte das Muster $55 nicht konstant angezeigt worden sein, 
sondern nur sichtbar. Vielleicht fehlt noch Vcc o.ä. Kleinigkeiten, was 
auch schwer erklärbare Fehler/Funktionieren verursachen kann.

>...hier ist die Zuordnung doch etwas wirr
nette Verharmlosung: praktisch sind Bezeichner die ihre Funktion/Zweck 
(Vereinfachung kontrollierter Programmierung) nicht erfüllen ein 
heftiger Naming-Bug, allerdings hätte die Behebung für (A)SM bspw. 
EICRA_m EICRB DDRA DDRF_m Bugs für (B)asic,(C),Pascal verursacht und der 
von Karl vorgestellte mini-compiler kann den BUG für die erste Sprache 
ASM des ABC zumindest etwas verharmlosen ;-
Kompatibilität geht manchmal sehr spezielle Wege...

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren