Hallo, Ich versuche Zeichen an das Hyperterminal zu senden. Dazu soll der Interrupt für "Zeichen gesendet" ausgenutzt werden. Leider wird der Interrupt nicht ausgelöst. Mein Programm sieht wie folgt aus: Ich suche den Feler jetzt schon seit 3 Tagen und ich komme einfach nicht drauf :-( .INCLUDE <m8def.inc> .def temp = R16 ; für Interrupt .def ZEICHEN = R17 ;------------------------------------------------------ ; Peripherie initialisieren ;------------------------------------------------------ .equ F_CPU = 7273800 ; Systemtakt in Hz .equ BAUD = 9600 ; Baudrate ; Berechnungen .equ UBRR_VAL = ((F_CPU+BAUD*8)/(BAUD*16)-1) ; clever runden .equ BAUD_REAL = (F_CPU/(16*(UBRR_VAL+1))) ; Reale Baudrate ;------------------------------------------------------ ; Start Adresse 0000 /Interruptvektoren ;------------------------------------------------------ .org 0x000 rjmp Init ; Interruptvektoren überspringen .org UTXCaddr ; UART Transmit Complete Interrupt rjmp serout ;------------------------------------------------------ ; INITIALIZE ;------------------------------------------------------ INIT: ;Stack Pointer setzen ldi temp,high(RAMEND) out SPH,temp ldi temp,low(RAMEND) out SPL,temp ; Baudrate einstellen ldi temp, HIGH(UBRR_VAL) out UBRRH, temp ldi temp, LOW(UBRR_VAL) out UBRRL, temp ; Frame-Format: 1 Stop-Bits, 8 Bit ldi temp, (1<<URSEL)|(0<<USBS)|(1<<UCSZ1)|(1<<UCSZ0) out UCSRC, temp sbi UCSRB,TXEN ; Sender aktivieren sbi UCSRB,TXCIE ; Interrupt für "senden fertig" aktivieren sei ; globale Interruptfreigabe sbi UCSRA,TXC ; Initialisierung des Interrupts ;------------------------------------------------------ ; HAUPTSCHLEIFE ;------------------------------------------------------ Hauptschleife: rjmp Hauptschleife ;------------------------------------------------------ ; Subroutinen / ISRs ;------------------------------------------------------ serout: lpm ; Erstes Byte des Strings nach R0 lesen mov ZEICHEN,R0 adiw ZL, 1 ; Adresse des Z-Pointers um 1 erhöhen tst R0 ; Inhalt von R0 auf Bull testen brbc 1,sprung_b ldi ZL, LOW(Daten*2) ; Adresse des ersten Strings in den ldi ZH, HIGH(Daten*2) ; Z-Pointer laden sprung_b: out UDR, ZEICHEN ; Zeichen auf UART ausgeben reti ;------------------------------------------------------ ; Datenbereich ;------------------------------------------------------ Daten: .db 0x12, 0x12 .db 0x20, 0x20 .db 0x63, 0x63 .db 0x58, 0x00
@ pacer (Gast) >Ich versuche Zeichen an das Hyperterminal zu senden. Dazu soll der >Interrupt für "Zeichen gesendet" ausgenutzt werden. Leider wird der >Interrupt nicht ausgelöst. >Mein Programm sieht wie folgt aus: >Ich suche den Feler jetzt schon seit 3 Tagen und ich komme einfach nicht >drauf :-( Ich glaube du hast einige wesentliche Dinge noch nicht verstanden. AVR-Tutorial: UART Interrupt > sei ; globale Interruptfreigabe Bis hier hin alles OK. > sbi UCSRA,TXC ; Initialisierung des Interrupts Was soll das? Dieser Befehl löscht ein anstehendes Interrupt-Bit. > ;------------------------------------------------------ > ; HAUPTSCHLEIFE > ;------------------------------------------------------ >Hauptschleife: >rjmp Hauptschleife Kannst du mir sagen, wo hier Zeichen gesendet werden? >serout: Du verwechselst die Funktionalität von UDRE und TXC Interrupt! MFG Falk
Danke für deine Hilfe Das Tutorial habe ich mir schon angeschaut, leider wird in den Beispielen der Interrupt nicht verwendet. Stimmt, das setzten des Bits löscht das Interruptflag. Hab ich mich wohl verlesen. Die Daten werden in der Interruptroutine ausgegeben, deswegen ist das Hauptprogramm leer. Nur muss ich zumindest einmal den Interrupt auslösen. Vielleicht könnte ich ja ein Leerzeichen senden wenn es losgehen soll, oder irgendetwas anderes?!
@ pacer (Gast) >Nur muss ich zumindest einmal den Interrupt auslösen. Vielleicht könnte >ich ja ein Leerzeichen senden wenn es losgehen soll, Das geht. MFG Falk
.equ F_CPU = 7273800 ; Systemtakt in Hz Da ist aber ein Zahlendreher drin....
Stimmt, so ganz klar ist mir der Unterschied zwischen UDRE und TXC nicht klar. Ich bin einfach davon ausgegangen, dass UDRE bedeutet, dass das Zeichen übermittelt wurde, unabhängig vom Status des Schieberegisters TXE bedeutet, dass das Zeichen übermittelt wurde und das Schieberegister kein neues Zeichen enthält.
Ups, stimmt, die Frequenz ist tatsächlisch falsch, hat aber bis jetzt trotzdem funktioniert ;-) ich werde das aber trotzdem verbessern, danke für den Tip
habe mein Programm wie folgt geändert: Die Null für die Initialisierung kommt an, nur ein Interrupt wird immer noch nicht ausgelöst. Ich hab keinen Plan was ich noch tun soll... ------------------------------------------------------------------- .include "C:\PROGRA~1\VMLAB\include\m8def.inc .def temp = R16 ; für Interrupt .def ZEICHEN = R17 ;------------------------------------------------------ ; Peripherie initialisieren ;------------------------------------------------------ .equ F_CPU = 7372800 ; Systemtakt in Hz .equ BAUD = 9600 ; Baudrate ; Berechnungen .equ UBRR_VAL = ((F_CPU+BAUD*8)/(BAUD*16)-1) ; clever runden .equ BAUD_REAL = (F_CPU/(16*(UBRR_VAL+1))) ; Reale Baudrate ;------------------------------------------------------ ; Start Adresse 0000 /Interruptvektoren ;------------------------------------------------------ .org 0x000 rjmp Init ; Interruptvektoren überspringen .org UTXCaddr ; UART Transmit Complete Interrupt rjmp serout ;------------------------------------------------------ ; INITIALIZE ;------------------------------------------------------ INIT: ;Stack Pointer setzen ldi temp,high(RAMEND) out SPH,temp ldi temp,low(RAMEND) out SPL,temp ; Baudrate einstellen ldi temp, HIGH(UBRR_VAL) out UBRRH, temp ldi temp, LOW(UBRR_VAL) out UBRRL, temp ; Frame-Format: 1 Stop-Bits, 8 Bit ldi temp, (1<<URSEL)|(0<<USBS)|(1<<UCSZ1)|(1<<UCSZ0) out UCSRC, temp sbi UCSRB,TXEN ; Sender aktivieren sbi UCSRB,TXCIE ; Interrupt für "senden fertig" aktivieren sei ; globale Interruptfreigabe ldi ZEICHEN, '0' out UDR, ZEICHEN ;Initialisierung ;------------------------------------------------------ ; HAUPTSCHLEIFE ;------------------------------------------------------ Hauptschleife: rjmp Hauptschleife ;------------------------------------------------------ ; Subroutinen / ISRs ;------------------------------------------------------ serout: lpm mov ZEICHEN,R0 adiw ZL, 1 tst R0 brbc 1,sprung_b ldi ZL, LOW(Daten*2) ldi ZH, HIGH(Daten*2) sprung_b: out UDR, ZEICHEN reti ;------------------------------------------------------ ; Datenbereich ;------------------------------------------------------ Daten: .db 0x12, 0x12 .db 0x20, 0x20 .db 0x63, 0x63 .db 0x58, 0x00
@ pacer (Gast) >habe mein Programm wie folgt geändert: >Die Null für die Initialisierung kommt an, nur ein Interrupt wird immer >noch nicht ausgelöst. >Ich hab keinen Plan was ich noch tun soll... U.a. SIMULIEREN! > ldi ZEICHEN, '0' > out UDR, ZEICHEN ;Initialisierung Hier fehlt eine Initialisierung des Z-Pointers. Der kann sonstwohin zeigen. > brbc 1,sprung_b Diesen Befehl nutz man praktisch NIE! Versuch mal lieber brne sprung_b Sollte zwar das gleiche sein, aber naja. MfG Falk
okay, funktioniert doch. Eigentlich ist das Programm aus verschiedenen Tutorials zusammengestrickt. Der Teil mit dem Befehl bcrc ist zB aus dem AVR-Tutorial. Den Z-Pointer brauche ich ja nur für den Datenbereich, bei einer Zuweisung muss ich ja nix tun. Müsste also korrekt sein. Simulieren tue ich mit VMLAB. Wollte aber noch mall fragen ob ich das jetzt mit UDRE und TXC richtig verstanden habe?! Gruß, pacer
@ pacer (Gast) >okay, funktioniert doch. E Und woran lags? >Wollte aber noch mall fragen ob ich das jetzt mit UDRE und TXC richtig >verstanden habe?! >>Ich bin einfach davon ausgegangen, dass UDRE bedeutet, dass das Zeichen >>übermittelt wurde, unabhängig vom Status des Schieberegisters Diese Formulierung ist nicht sehr glücklich. Übersetz doch einfach den Namen ins Deutsche UDRE, UART Data Register Empty. Das Datenregister des UARTs ist leer. D.h. es kann neue Daten aufnehmen. Und dabei geht es um das Zwischenregister, mit dem die Senderichtigung gepufferet wird, praktisch ein kleiner FIFO. >TXE bedeutet, dass das Zeichen übermittelt wurde und das Schieberegister >kein neues Zeichen enthält. Ja, diesen Interrupt nutzt man aber nur selten, z.B. bei Halbduplexkommunikation mit RS485, um den Tranceiver (Z.B. MAX485) von Senden auf Empfangen umzuschalten. MFG Falk
Hallo, ich schreibe zur Zeit ein Programm in Assembler für den ATMega162. Zur Simulation benutze ich das Programm VMLab. Bei der Simulation mit der seriellen Schnittstelle habe ich Probleme. Für den Interrupt nutze ich das Bit UDRIE1 im Register UCSR1B. Die Daten liegen im Ausgabepuffer im Datenbereich und werden in der Interruptroutine über einen Zeiger gelesen und in das Register UDR1 geschrieben. Sobald die Daten in den Ausgabepuffer geschrieben wurden wird das Bit UDRIE1 gesetzt. Es wird sofort ein Interrupt ausgelöst und die Daten über die serielle Schnittstelle versendet. Am Ende der Interruptroutine wird das Bit UDRIE1 gelöscht. Nachdem ein neuer Datenblock geschrieben wurde und das Bit UDRIE1 gesetzt wurde, wird kein Interrupt ausgelöst. Kann hier der Fehler bei VMLab liegen, da alle Flags richtig angezeigt werden? Gruß Manfred
@ Manfred (Gast) >Für den Interrupt nutze ich das Bit UDRIE1 im Register UCSR1B. >Die Daten liegen im Ausgabepuffer im Datenbereich und werden in der Was heisst "im Ausgangspuffer" ? Du meinst ein allgemeines Array. >Interruptroutine über einen Zeiger gelesen und in das Register UDR1 >geschrieben. >Sobald die Daten in den Ausgabepuffer geschrieben wurden wird das Bit >UDRIE1 gesetzt. >Es wird sofort ein Interrupt ausgelöst und die Daten >über die serielle Schnittstelle versendet. Am Ende der Interruptroutine >wird das Bit UDRIE1 gelöscht. Wozu das? UDIE bleibt im Normalfall solange gesetzt, bis das letzte Zeichen in UDR1 geschrieben wurde. >Nachdem ein neuer Datenblock geschrieben wurde und das Bit UDRIE1 >gesetzt wurde, wird kein Interrupt ausgelöst. >Kann hier der Fehler bei VMLab liegen, da alle Flags richtig angezeigt >werden? Ja, kann ein Fehler sein. MfG Falk
@Falk Die Daten, die über die serielle Schnittstelle gesendet werden sollen befinden sich als Block im internen RAM. Das letzte Zeichen ist null. In der Interruprroutine wird bei jedem Aufruf ein Zeichen gelesen und in das Register UDR1 geschrieben. Falls null gelsen wird, wird dieses Zeichen nicht in das Register UDR1 geschrieben, aber das Bit UDRIE1 gelöscht. Dieses Bit wird erst wieder gesetzt, nachdem ein neuer Block in das interne RAM geschrieben wurde. Da die erste Übertragung funktioniert und dann nicht mehr, vermute ich einen Fehler bei VMLab. Gruß Manfred
@ Manfred (Gast) Genau so meinte ich das. >Da die erste Übertragung funktioniert und dann nicht mehr, vermute ich >einen Fehler bei VMLab. Ja. Simulation ist nur die halbe Wahrheit. Probiers aus. MfG Falk
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.