mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik ATmega128 External Interrupt Problem


Autor: Stefan F. (stefan_h1)
Datum:

Bewertung
0 lesenswert
nicht 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.
.NOLIST
.INCLUDE "m128def.inc"
.LIST

.equ    temp, 0x10

.text
.org    0x00
    jmp    init
.org    INT6addr*2
    jmp    int6

.text

init:
    ldi    temp, lo8(RAMEND)
    out    SPL, temp
    ldi    temp, hi8(RAMEND)
    out    SPH, temp

    ldi    temp, 0x00
    out    DDRE, temp  
    out   PORTE, temp
  
    ldi    temp, 0xff
    out    DDRA, temp  
  
    ldi    temp, 1<<PE6  
    out    PORTE, temp

    lds    temp, EICRB
    ori    temp, 1<<ISC61
    sts    EICRB, temp

    in     temp, EIMSK
    ori    temp, 1<<INT6
    out    EIMSK, temp  
  
    ldi    temp, 0x55
    out    PORTA, temp

    sei              

    ldi    temp, 1<<SE
    out    MCUCR, temp

main:  
    sleep
    rjmp   main
  
int6:
    in     temp, PORTA
    dec    temp  
    out    PORTA, temp  
    reti

Autor: Dirk (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
.org nt6addr *1
probiert?

Autor: Falk B. (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hatten wir das nicht eben erst?

Beitrag "AVR External Interrupt Hilfe"

Autor: Dirk (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
fast. aber die Verwendung von Bezeichneten kann auch schiefgehen

Autor: Stefan F. (stefan_h1)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dirk schrieb:
> .org nt6addr *1
> probiert?

Ja, brachte leider nichts. Dann hab ich nur das Muster 0x55 am PORTA und 
der Interrupt wurde nie ausgeführt.

Autor: Jörg W. (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
M103C-Fuse abgeschaltet?

Ansonsten rennt dein Stack in irgendwelche IO-Register rein.

Autor: Stefan F. (stefan_h1)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hhh

Jörg W. schrieb:
> M103C-Fuse abgeschaltet?
>
> Ansonsten rennt dein Stack in irgendwelche IO-Register rein.

Ja, ist deaktiviert. Vielleicht liegt es aber generell an irgendwelchen 
Fuse-Bits?

Autor: MWS (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Stefan F. (stefan_h1)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: MWS (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Marc V. (Firma: Vescomp) (logarithmus)
Datum:

Bewertung
0 lesenswert
nicht 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.

: Bearbeitet durch User
Autor: S. Landolt (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> ... bin nun bei Interrupts angelangt.

Das heißt, dass zuvor (auf diesem uC) der Aufruf (und die Rückkehr aus) 
einer normalen Subroutine funktioniert hat?

Beitrag #5584533 wurde vom Autor gelöscht.
Autor: Dirk B. (dirkb)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Stefan F. (stefan_h1)
Datum:

Bewertung
0 lesenswert
nicht 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
lds    temp, EICR
ori    temp, 1<<ISC61
sts    EICRB, temp

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

Wieder was gelernt.
Danke nochmal allen die mir geholfen haben.

Autor: S. Landolt (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dass das der ursprüngliche Fehler gewesen sein soll, kann ich nicht 
glauben. Wie Dirk B. schrieb, wird mit
lds    temp, EICRB
ori    temp, 1<<ISC61
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?

Autor: Karl M. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.
.macro xIn
.if @1<64
in    @0,@1
.else
lds    @0,@1
.endif
.endmacro

.macro xOut
.if @0<64
out    @0,@1
.else
sts    @0,@1
.endif
.endmacro

Autor: S. Landolt (Gast)
Datum:

Bewertung
1 lesenswert
nicht 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'.

Autor: Dirk B. (dirkb)
Datum:

Bewertung
0 lesenswert
nicht 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

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.