www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik uart interrupt löst doppelt aus


Autor: ralph (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hi!

habe das problem, dass ich bei einem atmega8 bei empfang eines signals
an der uart der atmega ein bestimmtes signal ausgeben soll.

ich habe das auch soweit alles hinbekommen. der atmega sendet mein
signal und ich habe das mit einem interrupt umgesetzt. habe dafür den
usart, rx interrupt genommen.

mein problem ist nur, dass er bei mir die interruptrooutine zweimal
durchläuft. das heisst er sendet mein signal zweimal hintereinander.

ich vermute jetzt, dass es daran liegt, dass er den interrupt zweimal
auslöst, da am eingang das signal zwei byte lang ist. kann das sein???
wenn ja, wie kann ich das machen, dass er den zweiten nicht ausführt??

danke schon einmal für eure hilfe.

Autor: hebel23 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi Ralph,

ohne Dein Programm zu kennen ist das etwas schwierig zu beurteilen. Ich
vermute mal, dass Du nach dem Empfang von einem Zeichen gleich wieder
aus der Interruptroutine rausgehst. Wenn Du zwei Zeichen empfängst
kommt natürlich dann der Interrupt auch 2x.

Gruß Andreas

Autor: ralph (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ok, hier wäre das programm!!!!

.include "m8def.inc"

.def temp = r16
.def save = r15
.equ CLOCK = 4000000
.equ BAUD = 37000
.equ UBRRVAL = CLOCK/(BAUD*16)-1

.org 0x000
    rjmp main0
    reti
    reti
    reti
    reti
    reti
    reti
    reti
    reti
    reti
    reti
    rjmp int_rxc
    reti
    reti
    reti
    reti
    reti
    reti
    reti

main0:
  ; Stackpointer initialisieren
        ldi temp, LOW(RAMEND)
        out SPL, temp
        ldi temp, HIGH(RAMEND)
        out SPH, temp

        ; Baudrate einstellen
        ldi temp, LOW(UBRRVAL)
        out UBRRL, temp
        ldi temp, HIGH(UBRRVAL)
        out UBRRH, temp

        ; Frame-Format: 8 Bit
        ldi temp, (1<<URSEL)|(3<<UCSZ0)
        out UCSRC, temp
weiter:
  sbi UCSRB,TXEN                    ; TX aktivieren
        sbi UCSRB, RXCIE
  sbi UCSRB, RXEN

  sei

loop:   rjmp loop


; =============================
;   Warteschleifen-Generator
;     800 Zyklen:
; -----------------------------
; warte 798 Zyklen:
zeit:
      ldi  R17, $03
WGLOOP0:  ldi  R18, $84
WGLOOP1:  dec  R18
          brne WGLOOP1
          dec  R17
          brne WGLOOP0
          ret


serout:
        sbis UCSRA,UDRE
        rjmp serout
        out UDR, temp
  ret                               ; zurück zum Hauptprogramm


int_rxc:
        cli
  in save, SREG
        rcall zeit
        rcall zeit
  rcall zeit
  rcall zeit
  rcall zeit
  rcall zeit
        ldi temp, 8
        rcall serout                      ; Unterprogramm aufrufen
  rcall zeit
  ldi temp, 0
        rcall serout
  rcall zeit                        ; Unterprogramm aufrufen
  ldi temp, 0
        rcall serout
  rcall zeit                    ; ...
        ldi temp, 0
        rcall serout
  rcall zeit
        ldi temp, 17
        rcall serout
  rcall zeit
  in temp, UDR
  out portd, temp
  out SREG, save
  reti


so sieht das programm aus!!!!
aber ich verstehe nicht wieso er das zu sendende signal zweimal
schickt. macht für mich keinen sinn und ich suche auch schon ein paar
tage nach dem doofen fehler!!!!

Autor: Michael (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
SREG wird jetzt gerettet: schön.

Was ist 'Signal am rx-input' ? Vermutlich ein Impuls, der länger ist
als ein zu empfangendes Byte (abhängig von der Baudrate). Verschiedene
UARTs reagieren unterschiedlich darauf und setzen Fehlerflags.
1. Nur ein Byte wird gewertet
2. Bytes werden gewertet, bis der FIFO voll ist (2 Byte beim ATmega)
3. Bytes werden fortlaufend empfangen

Bei Dir vermute ich den Fall 2. Ob Deine Schaltung so überhaupt
funktionieren kann sei dahingestellt. Du könntest die Fehlerflags
bewerten und warten, bis ein Byte fehlerfrei empfangen wurde. Wenn Dein
Impuls konstant länger als ein und kürzer als zwei Bytes ist, kannst Du
am Ende Deiner Routine auch einfach das FIFO löschen:
noch einmal 'in temp,UDR'.

Wenn es denn so ist, wie vermutet.

Autor: ralph (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@michael

du bist ein genie!!!! ich könnt dich küssen.
super vielen dank! du hast das problem echt erkannt.

ich habe 'in temp,UDR' am ende meiner routine noch einmal eingefügt
und siehe da er schickt mir das signal nur noch einmal!!!!

klasse, nochmal vielen dank. das hät ich wohl nie allein
herausgefunden....

Autor: Michael (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
...
Oh, bitte nicht !

Da hast Du Glück, Dein Programm ist sehr riskant programmiert. Das 2.
Lesen von UDR klappt nur, da zuvor viel Zeit vertüddelt wurde; das CLI
am Anfang ist auch gewagt.

Besser wäre es, zunächst den Status vom UART zu bewerten, dann UDR zu
lesen und dann zu sehen, ob mehr Bytes zu erwarten sind oder auch
nicht. Erst dann sollte CLI kommen.

Viel Spaß.

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.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

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