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.