UART String empfangen

Gast #3783814
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...
#3784618
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...
Gast #3784947
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.
Gast #3784955
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.
#3784976
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.
Angehängte Dateien:
Gast #3784989
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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren