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


von ralph (Gast)


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.

von hebel23 (Gast)


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

von ralph (Gast)


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!!!!

von Michael (Gast)


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.

von ralph (Gast)


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....

von Michael (Gast)


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ß.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.