Hallo,
ich bin dabei mich auf dem ATMega48 mit der UART Schnittstelle zu
befassen (in Assembler).
Das funktioniert soweit wie erwartet und ich kann Zeichen an das
Terminalprogramm auf dem PC senden.
Mir fällt jedoch auf, dass das Deaktivieren und erneute Aktivieren des
UART nicht transparent für ein permanent lauschendes Terminalprogramm
von statten geht.
Das Problem, das auftritt, ist dass nach Aus- und wieder Einschalten des
TX ein zusätzliches Zeichen vom Terminalprogramm empfangen wird. In den
angehängten Screenshots ist das gut zu sehen. Da ist der Pegel auf der
TX Leitung zu sehen und der Text der am Terminal empfangen wird.
Hier mal der funktionierende Fall und der Problemfall als Pseudocode:
Das folgende funktioniert einwandfrei:
Initialisierung UART
Begin:
Warte auf Tastendruck
Aktiviere TX
SendByte "H"
SendByte "A"
SendByte "L"
SendByte "L"
SendByte "O"
Jmp Begin
Der folgende Code sendet nach der TX-Aus-/Einschaltsequenz vor dem
ersten regulären Zeichen ein "_" an das Terminalprogramm.
Initialisierung UART
Begin:
Warte auf Tastendruck
Aktiviere TX
SendByte "H"
SendByte "A"
SendByte "L"
SendByte "L"
SendByte "O"
Deaktiviere TX
Jmp Begin
Ist es normal, dass der UART beim Aus-/Einschalten kurzfristig
undefinierte Pegel am RX anliegen hat?
Hier noch die drei echten Codeschnippsel der UART-Routinen (auf das
wichtigste reduziert und mit aufgelösten Konstanten):
AktiviereTX:
lds r17, UCSR0B ; TX und TXCIE aktivieren
or r17, 0b01001000 ; or: [ ]RXCIEn [x]TXCIEn [ ]UDRIEn
[ ]RXENn [x]TXENn [ ]UCSZn2 [ ]RXB8n [ ]TXB8n
sts UCSR0B, r17
DeaktiviereTX:
lds r17, UCSR0A ; Wartet auf USART Data Register
Empty
sbrs r17, UDRE0
rjmp DeaktiviereTX
lds r17, UCSR0B ; TX und TXCIE deaktivieren
and r17, 0b10110111 ; and: [x]RXCIEn [ ]TXCIEn
[x]UDRIEn [x]RXENn [ ]TXENn [x]UCSZn2 [x]RXB8n [x]TXB8n
sts UCSR0B, r17
SendByte:
Wait:
lds r17, UCSR0A ; Wartet auf USART Data Register
Empty...
sbrs r17, UDRE0
rjmp Wait
ldi r16, 'H'
sts UDR0, r16
Daher nochmal meine Frage: Ist das Verhalten normal oder ist das eher
ein Programmfehler?
Gruß Markus
Markus schrieb: > Hier noch die drei echten Codeschnippsel der UART-Routinen (auf das > wichtigste reduziert und mit aufgelösten Konstanten): Das sind die falschen echten Codezeilen. Interessieren tut hier die Portkonfiguration.
Hallo Markus, hänge an Uart TXD und RXD je einen externen Pullup-Widerstand. so 1k-10kΩ sollten ausreichen.
Hallo Detlef,
ich versuche das mal aus den verschiedenen Includes zusammenzuschreiben:
.equ FCPU = 20000000 ; CPU Taktfrequenz
.equ UH_BAUDRATE = 9600 ; Baudrate (das Frameformat beträgt
fest 8N1)
.equ UH_UBRR_VAL = ((FCPU + UH_BAUDRATE * 8) / (UH_BAUDRATE * 16) - 1)
.equ UH_BAUD_REAL = (FCPU / (16 * (UH_UBRR_VAL + 1))) ;
Reale Baudrate
.equ UH_BAUD_ERR = ((UH_BAUD_REAL * 1000) / UH_BAUDRATE - 1000) ;
Fehler in Promille
.equ UH_UCSR0A_INIT = 0b00000000 ; USART Control and Status Register
n A
; [ ]RXCn [x]TXCn [ ]UDREn [ ]FEn [
]DORn [ ]UPEn [ ]U2Xn [ ]MPCMn
; U2Xn: Double the USART
Transmission Speed (bei asynchron = 0)
.equ UH_UCSR0B_INIT = 0b00000000 ; USART Control and Status Register
n B
; [x]RXCIEn [x]TXCIEn [x]UDRIEn
[x]RXENn [x]TXENn [ ]UCSZn2 [ ]RXB8n [ ]TXB8n
; RXENn: Receiver Enable
; TXENn: Transmitter Enable
; UDRIEn: Data Register Empty
Interrupt Enable
; RXCIEn: RX Complete Interrupt
Enable
; TXCIEn: TX Complete Interrupt
Enable
.equ UH_UCSR0B_RXTX_ON = 0b11011000 ; Parameter-Bitmasken für
UH_De/Activate
.equ UH_UCSR0B_RX_ON = 0b10010000
.equ UH_UCSR0B_TX_ON = 0b01001000
.equ UH_UCSR0B_RXTX_OFF = 0b00100111
.equ UH_UCSR0B_RX_OFF = 0b01101111
.equ UH_UCSR0B_TX_OFF = 0b10110111
.equ UH_UCSR0B_UDRIE_ON = 0b00100000
.equ UH_UCSR0B_UDRIE_OFF = 0b11011111
.equ UH_UCSR0C_INIT = 0b00000110 ; USART Control and Status Register
n C
; [ ]UMSELn1 [ ]UMSELn0 [ ]UPMn1 [
]UPMn0 [ ]USBSn [ ]UCSZn1 [ ]UCSZn0 [ ]UCPOLn
; UMSELn0/1: 0:0 = Asynchron
Mode
; UPMn0/1: 0:0 = keine Parity
; USBSn: 0 = kein Stoppbit
; UCSZn0/1/2: 0:1:1 = 8 Datenbits
; UCPOLn: Clock Polarity (bei
asynchron = 0)
UART_INIT:
push r16 ; Arbeitsregister auf Stack sichern
ldi r16, HIGH(UH_UBRR_VAL) ; Baudrate setzen
sts UBRR0H, r16
ldi r16, LOW(UH_UBRR_VAL)
sts UBRR0L, r16
ldi r16, UH_UCSR0A_INIT ; Control und Status Register A, B
und C setzen
sts UCSR0A, r16
ldi r16, UH_UCSR0B_INIT
sts UCSR0B, r16
ldi r16, UH_UCSR0C_INIT
sts UCSR0C, r16
pop r16 ; Arbeitsregister restaurieren
Gruß Markus
Hallo Uwe, habe das mit dem Pullup gerade auf dem Steckbrett getestet. Das hilft leider nicht. Der peak ist noch immer da und erzeugt ein 0-Byte.
Och Mann, das ist doch Grütze! Zu das Zeug wo DDRD und PORTD beschrieben werden. Uwe S. schrieb: > Hallo Markus, > > hänge an Uart TXD und RXD je einen externen Pullup-Widerstand. > > so 1k-10kΩ sollten ausreichen. Vielleicht geht das, aber nur wenn Port D1 ein Eingang ist. Das ist aber eher unwarscheinlich beim TXD.
Markus schrieb: > Ist es normal, dass der UART beim Aus-/Einschalten kurzfristig > undefinierte Pegel am RX anliegen hat? Warum schaltest du den überhaupt aus? Machst du am Abend beim Auto oder beim Moped auch jedesmal den Tank leer und füllst ihn am nächsten Morgen wieder auf?
Hallo, Deaktivieren von TxD muss den Pin TxD auf Hi-Pegel lassen. Lo ergibt irgendwelche Zeichen oder Break. Was soll das Deaktivieren überhaupt? Ist nichts zu senden, bewegt sich an TxD auch nichts. Georg
Lothar Miller schrieb: > Warum schaltest du den überhaupt aus? Machst du am Abend beim Auto > oder beim Moped auch jedesmal den Tank leer und füllst ihn am nächsten > Morgen wieder auf Das mit dem leer machen übernehmen in manchen Gegenden andere, man muss dann nur noch morgens auffüllen, hat also nur die halbe Arbeit ;)
@Detlef:
Da ich für Inputs (Taster) nur PROTC nutze, wird auch nur dieser von mir
konfiguriert.
.equ PORTC_DDRC = 0b00001001 ; DDRC (Richtungsregister,
1=Output, 0=Input)
.equ PORTC_PORTC = 0b00000000 ; Alle Bits an PORTC0 ausschalten
ldi Tmp, PORTC_DDRC ; DDRC (Richtungsregister) setzen
out DDRC, Tmp
ldi Tmp, PORTC_PORTC ; Bits und Pullup-Widerstände
setzen
out PORTC, Tmp
@Alle anderen:
Hmm, nun wenn das Abschalten des TX nicht Usus ist, dann ist das ja in
Ordnung. Ich kenne den genauen workflow dazu nicht.
Denkbar wäre aber, wenn eine Schaltung nur zeitweise über UART
kommuniziert. Da würde ich von der logischen Überlegung her (und weil
ich 'nen ordentlicher Mensch bin ;-) ) das TX Modul abschalten, wenn es
nicht gebraucht wird. Mein Beispiel im ersten post ist ein
Extrembeispiel das gebe ich zu, da nach einem Wort der TX sofort wieder
dicht gemacht wird.
Das Verhalten mit dem "_" ist für mich aber auch kein Showstopper, ich
wollte halt nur wissen, ob das normal ist oder ob ich etwas übersehen
habe.
Manch einer ist ja auch schon mit dem TXC0-Bit auf die Nase gefallen,
welches nur gelöscht wird, wenn die zugehörigen Interrupts aktiviert
sind. Sendet man ohne aktivierte Interrupts, dann muss das Flag manuell
gelöscht werden. Andernfalls funktioniert die Abfrage, ob das frame
komplett übertragen wurde nicht korrekt. -> "This flag bit is set when
the entire frame in the Transmit Shift Register has been shifted out and
there are no new data currently present in the transmit buffer (UDRn).
The TXCn Flag bit is automatically cleared when a transmit complete
interrupt is executed, or it can be cleared by writing a one to its bit
location."
Irgendeine ähnliche, fiese Kleinigkeit in diese Richtung hatte ich für
meinen Fall in Verdacht.
Markus schrieb: > Da würde ich von der logischen Überlegung her (und weil > ich 'nen ordentlicher Mensch bin ;-) ) das TX Modul abschalten Wenn es denn deine Nerven beruhigt, kannst du das ja machen, aber dann eben so, dass der Pin konstant Hi ist. Georg
Ach so! Das heißt ich muss den vorher regulär als Output mit High Pegel programmieren?
Markus schrieb: > Ach so! Das heißt ich muss den vorher regulär als Output mit High > Pegel > programmieren? Genau. ;)
Das mit dem High-Pegel habe ich gerade umgesetzt. Was soll ich sagen? Geht ab wie Sahne! :-) Besten Dank. Herr Ober, je ein Bier bitte an die beiden Herren dort drüben (Uwe und Detlef)
Markus schrieb: > Herr Ober, je ein Bier bitte an die beiden Herren dort drüben (Uwe und > Detlef) Wie jetzt... die Beiden sollen sich ein Bier teilen ? ;)
Markus schrieb: > Denkbar wäre aber, wenn eine Schaltung nur zeitweise über UART > kommuniziert. Da würde ich von der logischen Überlegung her (und weil > ich 'nen ordentlicher Mensch bin ;-) ) das TX Modul abschalten, wenn es > nicht gebraucht wird. Diese Vorgehensweise ist umständlich, wenn du den Pin zwischendurch nicht für was anderes brauchst. So ähnlich wie wenn du die Lötstation die du zu Weihnachten bekommen hast, nach und vor jeder Benutzung bis hin zum Geschenkband ein- und wieder auspackst... Du kannst das TX Modul eines AVR gar nicht einzeln abschalten. Du schaltest nur den Pintreiber um.
Lothar Miller schrieb: > Du kannst das TX Modul eines AVR gar nicht einzeln abschalten. Du > schaltest nur den Pintreiber um. Natürlich kann man es abschalten. Kapitel 10.9.2 "PRR – Power reduction register" Kapitel 30.3 "Supply current of I/O modules"
Okay, ich denke anhand des Lötstationen-Beispiels habe ich verstanden, dass ich TX/RX nicht immer wieder abschalten brauche. :-) Wieder was gelernt. Besten Dank nochmal an alle, das ging echt schnell. Gruß Markus
Detlef Kunz schrieb: > Lothar Miller schrieb: >> Du kannst das TX Modul eines AVR gar nicht einzeln abschalten. > Natürlich kann man es abschalten. Natürlich kannst du nur den gesamten UART abschalten. Nur TX allein geht nicht...
Lothar Miller schrieb: > Detlef Kunz schrieb: >> Lothar Miller schrieb: >>> Du kannst das TX Modul eines AVR gar nicht einzeln abschalten. >> Natürlich kann man es abschalten. > Natürlich kannst du nur den gesamten UART abschalten. Nur TX allein > geht nicht... Stimmt!
Hi >Natürlich kannst du nur den gesamten UART abschalten. Nur TX allein >geht nicht... Wozu sind dann wohl RXEN0 und TXEN0 da? MfG Spess
Hi
>Zum Umschalten der Pintreiber
Und wo ist das Bit zum Ein/Ausschalten der U(S)ART?
MfG Spess
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.



