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.
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
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!!!!
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.
@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....
... 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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.