Forum: Mikrocontroller und Digitale Elektronik UART String empfangen


von Jan R. (Gast)


Lesenswert?

Hi,

der Democode hier aus dem Dorum funktioniert nicht?

1
/* Zeichen empfangen */
2
uint8_t uart_getc(void)
3
{
4
    while (!(UCSRA & (1<<RXC)))   // warten bis Zeichen verfuegbar
5
        ;
6
    return UDR;                   // Zeichen aus UDR an Aufrufer zurueckgeben
7
}
8
 
9
void uart_gets( char* Buffer, uint8_t MaxLen )
10
{
11
  uint8_t NextChar;
12
  uint8_t StringLen = 0;
13
 
14
  NextChar = uart_getc();         // Warte auf und empfange das nächste Zeichen
15
 
16
                                  // Sammle solange Zeichen, bis:
17
                                  // * entweder das String Ende Zeichen kam
18
                                  // * oder das aufnehmende Array voll ist
19
  while( NextChar != '\n' && StringLen < MaxLen - 1 ) {
20
    *Buffer++ = NextChar;
21
    StringLen++;
22
    NextChar = uart_getc();
23
  }
24
 
25
                                  // Noch ein '\0' anhängen um einen Standard
26
                                  // C-String daraus zu machen
27
  *Buffer = '\0';
28
}


Das liegt glaube ich daran, dass hier ein fehler ist.
1
NextChar = uart_getc();         // Warte auf und empfange das nächste Zeichen
2
 
3
                                  // Sammle solange Zeichen, bis:
4
                                  // * entweder das String Ende Zeichen kam
5
                                  // * oder das aufnehmende Array voll ist
6
  while( NextChar != '\n' && StringLen < MaxLen - 1 ) {
7
    *Buffer++ = NextChar;
8
    StringLen++;
9
    NextChar = uart_getc();
10
  }
11
 
12
                                  // Noch ein '\0' anhängen um einen Standard
13
                                  // C-String daraus zu machen
14
  *Buffer = '\0';

Denn so wird Buffer[0] nie beschrieben, da das Array buffer schon 
inkrementiert wird, bevor NextChar hereingeschriebwn wurde.
Genauso überrschreibt '\0' das letzte zeichen. Weil nichtmehr 
inkrementiert wird..

Jetzt gibt es aber ein Problem dieser Code funktioniert auch 
nicht(mehr).
1
 while( NextChar != '\n' && StringLen < MaxLen - 1 ) {
2
    *Buffer= NextChar;
3
Buffer++;
4
    StringLen++;
5
    NextChar = uart_getc();
6
  }

Warum funktioniert das nichtmehr? Warum hat das Beispiel aus dem AVR-GCC 
Tutorial einmal funktioniert? Wuerde früher wenn man den Befeh,
 *Buffer++ = NextChar; genommen hat das inkrement der Adresse erst im 
nächten Programmdurchlauf ünernommen. Sodass die Speicherstelle 0 i. 
Array doch genutzt wurde? Warum funktioniert meine Version nichtmehr. 
hat es bis jetzt immer.. Ich bin ein wenig verwirrt... Vielleicht weiß 
ja jemand weiter...

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Jan R. schrieb:
> Denn so wird Buffer[0] nie beschrieben, da das Array buffer schon
> inkrementiert wird, bevor NextChar hereingeschriebwn wurde.

 Nein.
     *Buffer++ = NextChar;
 Das ist post-increment, deswegen stehen pluszeichen hinter Buffer.
 Und:
>     *Buffer= NextChar;
>      Buffer++;
 ist genau dasselbe.

von Bernhard F. (bernhard_fr)


Lesenswert?

Kurze Zwischenfrage:

Was heißt "funktioniert nicht".

Bleibt das Programm irgendwo in einer Funktion hängen?
Gibt "uart_gets" einen String zurück der nahe an dem Erwarteten ist?
Gibt "uart_getc" überhaupt etwas zurück?
Wurde die UART richtig initialisiert?

Ein bisschen mehr input wäre hilfreich, denn auf den ersten Blick hab 
ich spontan keinen Fehler gefunden...

von Jan R. (Gast)


Lesenswert?

Bei einem 16Mhz Quarz, bekomme ich ja nicht genau die Richtige Baudrate 
hin. Kann man an einen AVR einen extra Baudratenquarz anschließen, von 
welchen ich noch welche habe (1,8432Mhz).

von Wolfgang (Gast)


Lesenswert?

Jan R. schrieb:
> Bei einem 16Mhz Quarz, bekomme ich ja nicht genau die Richtige Baudrate
> hin.

Wozu willst du die unbedingt genau hin bekommen. Es reicht doch, wenn 
der Empfänger bei nomineller Baudrate halbwegs die Mitte abtastet, wobei 
du dir anhand deiner Signalverzerrungen auf der Strecke jetzt überlegen 
kannst, was "halbwegs" in Prozent der Baudrate bedeutet.

von Mike (Gast)


Lesenswert?

Jan R. schrieb:
> Kann man an einen AVR einen extra Baudratenquarz anschließen

Das kommt sicher drauf an, welchen AVR du meinst. Das sollte aber aus 
der Pinbelegung im Datenblatt deines Controllers hervorgehen und im 
Abschnitt USART unter "Clock Generation" beschrieben sein.
Ich kenne alelrdings keinen.

von Bernhard F. (bernhard_fr)


Angehängte Dateien:

Lesenswert?

O.K. jetzt mal bitte etwas konkreter:

welcher AVR ?

welche Baudrate?

Und als Bild nochmal die Tabelle aus dem Datenblatt...
Quelle: 
http://www.atmel.com/Images/Atmel-2549-8-bit-AVR-Microcontroller-ATmega640-1280-1281-2560-2561_datasheet.pdf

Gerade bei den "niedrigeren" Baudraten sind die Abweichungen gering...
Aus meiner Sicht ist es den Aufwand nicht Wert.

Ich habe eine ganze Weile aufgrund einer suboptimalen Berechnung meinen 
AVR eine ganze Weile bei 16 MHZ und 28800 Baud mit dem Wert 33 statt 34 
betrieben (Abweichung von über 1%), und die UART hat wunderbar 
funktioniert.

von Wolfgang (Gast)


Lesenswert?

Bernhard F. schrieb:
> 16 MHZ und 28800 Baud mit dem Wert 33 statt 34 betrieben (Abweichung
> von über 1%), und die UART hat wunderbar funktioniert.

So erstaunlich ist das nicht. Bei einem Fehler des Clock Generators von 
1% ist der Abtastzeitpunkt auf dem letzen Bit gerade mal 10% der 
Bitlänge aus der Mitte verschoben. Wenn die Übertragungsstrecke nicht 
ganz übel die Flanken verschleift und dann noch am Empfänger mit 
ungünstiger Schwelle ausgewertet wird, macht das überhaupt nichts.

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.