Forum: Mikrocontroller und Digitale Elektronik USART Zeichenausgabe nach Reset


von Christian R. (crothe)


Lesenswert?

Hallo,

ich finde seit mehreren Stunden keine Lösung für folgendes Problem:

Beim initialisieren meiner USART beim ATMEGA2560 wird nach dem setzen 
von RXEN und TXEN des UCSR0B Registers ein Zeichen auf der Schnittstelle 
ausgegeben (meist 0xFC).
Dadurch kommen daran hängende Geräte mit dem ersten Kommando nach dem 
Einschalten nicht klar, da es ja ein führendes falsches Zeichen enthält.

So sieht die Initialisirung aus:
1
void uart0_init()
2
{
3
  
4
    //set baud rate
5
    UBRR0H = 0x00;
6
    UBRR0H = (uint8_t) (UBRR_BAUD0>>8);
7
    UBRR0L = (uint8_t) UBRR_BAUD0;
8
9
    //enable receiver and transmitter
10
    UCSR0B =0x00;
11
12
//return; return an dieser Stelle: kein Zeichen wird ausgegeben
13
14
    UCSR0B = (1<<RXEN0) | (1<<TXEN0);
15
16
//return; return an dieser Stelle: 0xFC wird ausgegeben
17
18
    //enable interrupts
19
    UCSR0B |= (1<<RXCIE0);
20
21
    //set frame format to 'async USART' and 8n1
22
    UCSR0C = 0x00;         //clear
23
    UCSR0C = (1<<UCSZ01) | (1<<UCSZ00);
24
25
}

Hat jemand von Euch einen Tip, wie man das unterbinden kann? Das 
Verhalten ist auf alle 4 USARTS reproduzierbar.

Gruß
Christian

von chris (Gast)


Lesenswert?

schon mal getauscht

Christian Rothe schrieb:
> //return; return an dieser Stelle: kein Zeichen wird ausgegeben
>
>     UCSR0B = (1<<RXEN0) | (1<<TXEN0);
>
> //return; return an dieser Stelle: 0xFC wird ausgegeben
>
>     //enable interrupts
>     UCSR0B |= (1<<RXCIE0);
>
>     //set frame format to 'async USART' and 8n1
>     UCSR0C = 0x00;         //clear
>     UCSR0C = (1<<UCSZ01) | (1<<UCSZ00);

setze doch doch erst die Formatlänge dann RXEN/TXEN enablen und danach 
RXCIE freigeben falls nicht schon mal ausprobiert

von uwe (Gast)


Lesenswert?

> Dadurch kommen daran hängende Geräte mit dem ersten Kommando nach dem
> Einschalten nicht klar, da es ja ein führendes falsches Zeichen enthält.
Müssen die aber, es kann immer mal wieder vorkommen, daß ein falsches 
Zeichen dazwischenfunkt. Trotzdem sollte man das mit dem Zeichen bei 
Reset verhindern. Aber auch ein falsches Zeichen darf dein System nicht 
stören, ansonsten Mülltonne.

von Christian R. (crothe)


Lesenswert?

Hallo Chris,

nein, es geht auch so nicht
1
    //set baud rate
2
    UBRR0H = 0x00;
3
    UBRR0H = (uint8_t) (UBRR_BAUD0>>8);
4
    UBRR0L = (uint8_t) UBRR_BAUD0;
5
6
    //set frame format to 'async USART' and 8n1
7
    UCSR0C = 0x00;         //clear
8
    UCSR0C = (1<<UCSZ01) | (1<<UCSZ00);
9
10
  //enable receiver and transmitter
11
  UCSR0B =0x00;
12
  UCSR0B = (1<<RXEN0) | (1<<TXEN0);
13
  //enable interrupts
14
  UCSR0B |= (1<<RXCIE0);

von Christian R. (crothe)


Lesenswert?

Hallo Uwe,

im Prinzip sehe ich das ebenso. Allerdings kann natürlich das nächste 
Gerät nicht unterscheiden, ob dieses Zeichen gewollt oder eben zufällig 
kam.
Für den nächsten Empfänger ist es halt das erste Zeichen vom neuen 
Kommando. Der Parser erkennt das Kommando dann halt nicht.

von Stefan S. (sschultewolter)


Lesenswert?

Beherzige die Vorschläge bzgl. dem Abfangen von falschen Informationen. 
"Da kann wird nichts anderes geschickt," ist keine Ausrede. Es ist immer 
mal möglich durch falsch gesetzte Parameter, dass an der UART 
Schnittstelle nur murks rauskommt.

von chris (Gast)


Lesenswert?

zur Not 0x00 ins UDREx schreiben bevor die TX/RX pins gesetzt werden und 
mal testen find das eigentlich ungewönhlich das beim Reset Zeichen 
gesendet werden passiert vielleicht im Programm irgendwas was wir gerade 
nicht sehen da es ja nicht der vollständige Code ist?aber warte mal wann 
tritt denn der Reset auf?? denn es kann ja sein das im UDRE noch ein 
Zeichenn ist und du genau dann den Reset machst obwohl der Vorgang noch 
nicht abgeschlossen ist

von Christian R. (crothe)


Lesenswert?

Hallo Stefan,

hast Du dazu noch einen Tip? Mir fehlt dazu gerade der richtige Ansatz 
denn:

Mein Gerät startet und sendet ein Kommando über den USART. Dieses ist 
(wegen des ersten Zeichens) falsch. Das Zielgerät ignoriert das Kommando 
und alles weitere hakt...

Einzige Lösung die mir Einfällt wäre nun zuerst ein unnötiges Kommando 
(ohne gewünschte Funktion) zu senden um die FIFOs und Kommandoparser zu 
bereinigen.

Gibt es da elegantere Lösungen?

von Peter II (Gast)


Lesenswert?

Christian Rothe schrieb:
> Gibt es da elegantere Lösungen?

und wenn reagiert das Gerät wieder? Musst du es reseten?

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Ich nehme mal an, dass während des Resets alle Pins in den hochohmigen 
Zustand gehen. Damit ist dann der Pegel von TX undefiniert. Das kann 
sich beim Empfänger durchaus als vermeintliches "Zeichen" bemerkbar 
machen.

Diese These wird dadurch unterstützt, dass dann ein 0xFC ankommt. Das 
sieht bei der Übertragung folgendermaßen aus:


    ___-----------
    S012345678

(S=Startbit)

Das heisst, der kurze Dip auf der Leitung ergibt durchaus ein "Zeichen".

Wahrscheinlich hilft ein Pullup-Widerstand auf der TX-Leitung.

von Stefan (Gast)


Lesenswert?

Das ist wahrscheinlich kein Zeichen, das gesendet wird, sondern ein 
Pinwackeln, das durch das Umschalten des Pins von I/O auf 
TXD-Pinfunktion entsteht.
Wie ist denn Dein Pin vor dem Einschalten des UARTs konfiguriert? 
Floatet der oder ist der terminiert?
Am Besten hängst Du mal ein Oszi an den TXD-Pin und schaust Dir das 
Signal beim Reset und beim Konfigurieren an.

Gruß, Stefan

von uwe (Gast)


Lesenswert?

> Gerät nicht unterscheiden, ob dieses Zeichen gewollt oder eben zufällig
> kam.
Muss es aber, sonst Mülltonne.
Ist das "nächste Gerät" von dir? Wenn ja anderes Protokoll 
implementieren, wenn nein dann "nächste Gerät">Mülltonne, neuses Gerät 
mit anständigem Protokoll.

von Karl H. (kbuchegg)


Lesenswert?

Ich könnte mir vorstellen, dass das eigentliche Problem ein ganz anderes 
ist.

Der Ruhepegel auf der Tx Leitung vom Mega ist bei UART Betrieb +5V.
Nur: Diesen Pegel hat die Leitung nach dem einschalten (bzw. nach einem 
Reset) nicht.
Erst nachdem die UART aktiviert wird, geht die Leitung auf +5V. Wodurch 
sich eine Flanke am Ausgang ergibt.
Und auf diese Flanke reagieren deine Geräte.

Fazit: wie schon gesagt. Ein Empfänger ohne entsprechende 
Fehlerbehandlung ist Murx. D.h. eigentlich ist dann das Protokoll Murx, 
wenn es nicht erlaubt, dieses Problem zu erkennen und derartig 
fehlerhafte Datensätze auszusortieren. So etwas muss ein Protokoll bzw. 
ein Empfänger abkönnen. Was macht denn der Empfänger, wenn mal das Kabel 
abfällt und von der Putzfrau im laufenden Betrieb neu angesteckt wird? 
Deswegen darf der Feueralarm nicht ausgelöst werden.

von Christian R. (crothe)


Lesenswert?

@Chris

vollständiger Code ist viele Dateien groß, aber der wird hier noch gar 
nicht ausgeführt. Ich habe eine leere Endlosschleife direkt nach der 
Initialisirung eingefügt.

Ich habe bereits versucht UDR0 vor der Initialisierung oder an beliebig 
anderen Stellen während der Initialisierung zu leeren (auszulesen bis 
das RXC Register kein Zeichen mehr meldet)  -  kein Erfolg

Der Reset kommt entweder beim Einschalten oder durch Betätigen des 
Reset-Tasters, also willkürlich.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Karl Heinz schrieb:
> Erst nachdem die UART aktiviert wird, geht die Leitung auf +5V. Wodurch
> sich eine Flanke am Ausgang ergibt.
> Und auf diese Flanke reagieren deine Geräte.

Das sehe ich genauso. Das "empfangene" Zeichen 0xFC spricht dafür, denn 
es besteht nur aus einem kurzen Drop mit der Bitlänge 3 (zusammen mit 
dem Start-Bit), also 3 Bits Low, Rest wieder High.

von spess53 (Gast)


Lesenswert?

Hi

>Mein Gerät startet und sendet ein Kommando über den USART. Dieses ist
>(wegen des ersten Zeichens) falsch. Das Zielgerät ignoriert das Kommando
>und alles weitere hakt...

Nur mal so: Die USART sendet nichts, wenn der Transmit-Puffer leer ist. 
Und das ist er nach einem Reset. Mir ist es in über 16 Jahren mit AVRs 
noch nicht vorgekommen, das die USART ein solches Eigenleben entwickelt. 
Was machst du mit dem Port vorher?

MfG Spess

von Christian R. (crothe)


Lesenswert?

Karl Heinz schrieb:
> Ich könnte mir vorstellen, dass das eigentliche Problem ein ganz anderes
> ist.
>
> Der Ruhepegel auf der Tx Leitung vom Mega ist bei UART Betrieb +5V.
> Nur: Diesen Pegel hat die Leitung nach dem einschalten (bzw. nach einem
> Reset) nicht.
> Erst nachdem die UART aktiviert wird, geht die Leitung auf +5V. Wodurch
> sich eine Flanke am Ausgang ergibt.
> Und auf diese Flanke reagieren deine Geräte.
>
> Fazit: wie schon gesagt. Ein Empfänger ohne entsprechende
> Fehlerbehandlung ist Murx. D.h. eigentlich ist dann das Protokoll Murx,
> wenn es nicht erlaubt, dieses Problem zu erkennen und derartig
> fehlerhafte Datensätze auszusortieren. So etwas muss ein Protokoll bzw.
> ein Empfänger abkönnen. Was macht denn der Empfänger, wenn mal das Kabel
> abfällt und von der Putzfrau im laufenden Betrieb neu angesteckt wird?
> Deswegen darf der Feueralarm nicht ausgelöst werden.

Ja, da hast Du recht.
Das folgende Gerät ignoriert das Kommando zwar ganz brav, ist dadurch 
auch nicht aus dem Tritt geraten, aber hat meine Moduseinstellung 
(erstes Kommando) halt nicht akzeptiert.
Da liegt das Übel nun also im reinen ASCII Protokoll, welches hier keine 
Überprüfung auf richtig verarbeitete gesendete Kommandos vornimmt.
Da ist natürlich eine Umfangreiche Modifikation in der Struktur nötig. 
Hoffte es wäre einfach lösbar durch Vermeidung dieses Zeichens.

Dann danke Dir für die Denkanstöße, Karl Heinz

Gruß
Christian

Es ist wohl wirklich nur

von Karl H. (kbuchegg)


Lesenswert?

Christian Rothe schrieb:

> Ja, da hast Du recht.
> Das folgende Gerät ignoriert das Kommando zwar ganz brav, ist dadurch
> auch nicht aus dem Tritt geraten, aber hat meine Moduseinstellung
> (erstes Kommando) halt nicht akzeptiert.

Ist das Protokoll so aufgebaut, dass es ein Endezeichen vorsieht? Bei 
ASCII ist das meistens ein \n.

Dann sende ihm als allererstes Zeichen ein \n, damit der Kommandobuffer 
im Empfänger geleert wird und quasi die Empfansmaschinerie im Empfänger 
auf Ausgangsstellung zurückgeht, egal was vorher passiert ist.

von Christian R. (crothe)


Lesenswert?

spess53 schrieb:
> Hi
>
>>Mein Gerät startet und sendet ein Kommando über den USART. Dieses ist
>>(wegen des ersten Zeichens) falsch. Das Zielgerät ignoriert das Kommando
>>und alles weitere hakt...
>
> Nur mal so: Die USART sendet nichts, wenn der Transmit-Puffer leer ist.
> Und das ist er nach einem Reset. Mir ist es in über 16 Jahren mit AVRs
> noch nicht vorgekommen, das die USART ein solches Eigenleben entwickelt.
> Was machst du mit dem Port vorher?
>
> MfG Spess

Hallo Spess

vorher wird lediglich der µC initialisiert. Sollte ich das vielleicht 
auf das notwendigste reduzieren?
1
void InitController(void)
2
{
3
  // Port Directions
4
  // 1=out; 0=in
5
  DDRA = 0b11111111;
6
  DDRB = 0b11111111;
7
  DDRC = 0b11111111;
8
  DDRD = 0b11111111;
9
  DDRE = 0b11111111;
10
  DDRF = 0b11111111;
11
  DDRG = 0b11111111;
12
  DDRH = 0b11111111;
13
  DDRJ = 0b11111111;
14
  DDRK = 0b11111111;
15
  DDRL = 0b11111111;
16
  
17
  // Pullups
18
  // 1=pull up; 0=no pull up
19
  PORTA = 0b00000000;    // 
20
  PORTB = 0b11111111;    // LEDs
21
  PORTC = 0b00000000;    // Dip switch
22
  PORTD = 0b00000000;    // USART1
23
  PORTE = 0b00000000;    // USART0
24
  PORTF = 0b00000000;    
25
  PORTG = 0b00000000;
26
  PORTH = 0b00000000;    // USART2
27
  PORTJ = 0b00000000;    // USART3
28
  PORTK = 0b00000000;
29
  PORTL = 0b00000000;
30
}

von Christian R. (crothe)


Lesenswert?

Karl Heinz schrieb:
> Christian Rothe schrieb:
>
>> Ja, da hast Du recht.
>> Das folgende Gerät ignoriert das Kommando zwar ganz brav, ist dadurch
>> auch nicht aus dem Tritt geraten, aber hat meine Moduseinstellung
>> (erstes Kommando) halt nicht akzeptiert.
>
> Ist das Protokoll so aufgebaut, dass es ein Endezeichen vorsieht? Bei
> ASCII ist das meistens ein \n.
>
> Dann sende ihm als allererstes Zeichen ein \n, damit der Kommandobuffer
> im Empfänger geleert wird und quasi die Empfansmaschinerie im Empfänger
> auf Ausgangsstellung zurückgeht, egal was vorher passiert ist.

Ja, \r\n beendet den Parser. So werde ich es machen.

Danke für die Ideen.

Gruß
Christian

von spess53 (Gast)


Lesenswert?

Hi

>vorher wird lediglich der µC initialisiert. Sollte ich das vielleicht
>auf das notwendigste reduzieren?

Ja. Da liegt der Fehler. Du setzt die PINs Ausgang und dann auf L. Lass 
einfach die USART PINs auf Ausgang. Mit TXE und RXE übernimmt die USART 
eh die Kontrolle über die Pins.

MfG Spess

von Karl H. (kbuchegg)


Lesenswert?

spess53 schrieb:

> Ja. Da liegt der Fehler. Du setzt die PINs Ausgang und dann auf L. Lass
> einfach die USART PINs auf Ausgang.

-> Eingang

Wenn es möglich ist würde ich allerdings trotzdem dem Empfänger erst mal 
einen Dummy-Kommando Abschluss schicken. Dann kann ich als Sender von 
gesicherten Verhältnissen ausgehen. Sicher ist sicher.

von Christian R. (crothe)


Lesenswert?

Karl Heinz schrieb:
> spess53 schrieb:
>
>> Ja. Da liegt der Fehler. Du setzt die PINs Ausgang und dann auf L. Lass
>> einfach die USART PINs auf Ausgang.
>
> -> Eingang
>
> Wenn es möglich ist würde ich allerdings trotzdem dem Empfänger erst mal
> einen Dummy-Kommando Abschluss schicken. Dann kann ich als Sender von
> gesicherten Verhältnissen ausgehen. Sicher ist sicher.

Perfekt !!!

Danke für die Hilfe, so geht es und ich fühle mich wohler :-)

von spess53 (Gast)


Lesenswert?

Hi

>-> Eingang

Klar.

MfG Spess

von Stefan (Gast)


Lesenswert?

... und die 3 Bits low-Time sind genau die Zeit zwischen 
InitController() und InitUart(). Auch eine Idee, die Laufzeit der 
Initialisierung zu messen ;-)

Gruß, Stefan

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.