Forum: Mikrocontroller und Digitale Elektronik UART Buffer vergrößern


von Jürgen P. (juergenp)


Lesenswert?

Hallo,
ich will GPS Daten mit anderen Sensordaten auf einem ATMega bündeln, 
formatieren und ausgeben. Die Übertragung vom GPS (NMEA Datensätze) ist 
ja aber viel größer aus der UART Zwischenspeicher, daher geht da einiges 
verloren während ich andere Schnittstellen auslese.
Es gibt doch bestimmt ein IC, das UART mit einigen kb zwischenspeichert 
und das per Hardware Flag an den µC meldet um dann ausgelesen zu werden?
Gruß,
J

von Stephan B. (matrixstorm)


Lesenswert?

Hallo.

Bitte mehr Details!

Welchen Controller verwendest du, welche Programmiersprache - und ggf. 
auch Code.
Was meinst du mit UART-Puffer? Normalerweise ist der doch nur 1 Byte 
gross. Einen Ringpuffer als "Bottom-Half" zum UART-Interrupt muestest du 
selbst implementieren/von Libraries verwenden. Hast du?


MfG Stephan

von Georg G. (df2au)


Lesenswert?

Jürgen Papadopolis schrieb:
> Es gibt doch bestimmt ein IC

Das Problem wird üblicherweise per Software gelöst (Ringpuffer).

von Karl H. (kbuchegg)


Lesenswert?

Jürgen Papadopolis schrieb:
> Hallo,
> ich will GPS Daten mit anderen Sensordaten auf einem ATMega bündeln,
> formatieren und ausgeben. Die Übertragung vom GPS (NMEA Datensätze) ist
> ja aber viel größer aus der UART Zwischenspeicher, daher geht da einiges
> verloren während ich andere Schnittstellen auslese.
> Es gibt doch bestimmt ein IC, das UART mit einigen kb zwischenspeichert
> und das per Hardware Flag an den µC meldet um dann ausgelesen zu werden?

Dann hast du dein Programm schlecht aufgebaut.
Ein gut aufgebautes Programm hat selbst einen Zwischenspeicher, indem es 
die Zeichen von der UART zwischenlagert. Die UART buffert ein paar 
Zeichen in Hardware, damit das Programm nicht allzu kritisch ist, aber 
dann übernimmt das Programm, indem es möglichst schnell, so wie Zeit 
ist, diesen Hardwarebuffer ausleert und seinerseits die Zeichen in einem 
größeren Buffer zwischenlagert. Das kann auch bedeuten, dass die Abfrage 
von anderen Sensoren mal kurz durch einen Interrupt unterbrochen wird, 
indem der Hardware-Buffer der UART ausgeleert und in den Programmbuffer 
übertragen wird, ehe die Sensorauswertung weiter geht.

: Bearbeitet durch User
von Jürgen P. (juergenp)


Lesenswert?

Man, seit ihr schnell!
Ok, mehr Details:
Ich lese einen Sensor mit zwei Hz aus und einen weiteren mit zehn Hz. 
Das ganze derzeit in der Arduino Umgebung mit einem ATmega 328, um zu 
sehen, was machbar ist.
Aber in dem Moment, in dem das GPS sendet, kann ich keine Befehle mehr 
vom PC empfangen, da diese auch länger sind, als der µC buffert. Oder 
verstehe ich das falsch?

von Karl H. (kbuchegg)


Lesenswert?

Jürgen Papadopolis schrieb:

> vom PC empfangen, da diese auch länger sind, als der µC buffert. Oder
> verstehe ich das falsch?

Das einzige was ich verstehe ist, dass da wieder mal mit wenig Wissen, 
wie man Programme aufbaut, die scheinbar mehrere Dinge gleichzeitig 
machen, an ein Problem rangeht.

Ein altes indianisches Sprichwort sagt:
Es reicht nicht, mit dem Wunsch Fische zu fangen an den Fluss zu gehen. 
Man muss auch ein Netz mitbringen.
Soll heißen: Es reicht nicht, etwas programmieren zu wollen. Man muss es 
auch mal lernen und können.


Der Hauptpunkt ist der Übergang von sequentieller Arbeitsweise hin zu 
eventbasiertem Arbeiten. Das ist der Knackpunkt in der Programmierung 
von µC, die sich um mehrere Dinge gleichzeitig kümmern müssen.

: Bearbeitet durch User
von Peter D. (peda)


Lesenswert?

Jürgen Papadopolis schrieb:
> Es gibt doch bestimmt ein IC, das UART mit einigen kb zwischenspeichert
> und das per Hardware Flag an den µC meldet um dann ausgelesen zu werden?

Warum ein extra IC?
Dein AVR hat doch RAM. Also einfach nen Interrupthandler aufsetzen, der 
die Bytes erstmal in den RAM schreibt (FIFO). Dann kannst Du sie in 
aller Ruhe später auswerten. Und wärend dessen dürfen auch schon die 
nächsten Bytes eintrudeln, nichts geht verloren.

Erst wenn die Auswertung im Mittel länger dauert, als neue Daten 
eintrudeln, geht es schief.

von Jürgen P. (juergenp)


Lesenswert?

Der Dateneingang überschneidet sich aber. Ich kann doch nur einen 
Eingang auslesen, währenddessen gehen die anderen Daten verloren.
Danke Karl Heinz übrigens...

von Justus S. (jussa)


Lesenswert?

überleg dir doch bitte mal, wieviele Taktzyklen dein µC macht, während 
ein Byte reintröpfelt...

von spess53 (Gast)


Lesenswert?

Hi

>Der Dateneingang überschneidet sich aber. Ich kann doch nur einen
>Eingang auslesen, währenddessen gehen die anderen Daten verloren.
>Danke Karl Heinz übrigens...

Der ATMega328 hat doch nur eine UART. Wo kommt der zweite 'Eingang' her?

MfG Spess

von Jürgen P. (juergenp)


Lesenswert?

Für die Arduino IDE gibt es eine Lib die die digitalen Pins als 
sogenannte SoftwareSerials nutzen kann. Dazu nehme ich Pins 2 und 3 
jeweils als Rx Pin, da die noch Interrupts haben. Bei Baudrate 4800 kein 
Problem

von Karl H. (kbuchegg)


Lesenswert?

Ich werde da jetzt sicher einige Syntaxfehler einbauen, aber ich will da 
jetzt nicht alles nachschlagen, da ich alle Arduino Details auch nicht 
im Kopf habe und ich jetzt auch nicht darauf aus bin, da ein komplettes 
Beispiel aus dem nichts zu zaubern. Es geht um die prinzipielle 
Vorgehensweise, und selbst das nur in Form eines möglichen Schemas.
1
void loop()
2
{
3
  if( serial1.available() )
4
    buffer1[bufIndex++] = serial1.read();
5
6
  if( serial2.available() )
7
    buffer2[bufIndex++] = serial2.read();
8
9
  if( buffer1 enthält eine vollständige Übertragung )
10
    auswerten und bufIndex auf 0 zurücksetzen
11
12
  if( sequenceNr == 0 )
13
    lese Sensor1 aus
14
15
  else if( sequenceNr == 1 )
16
    lese Sensor2 aus
17
18
  else if( sequenceNr == 2 )
19
    lese Sensor3 aus
20
21
  sequenceNr++;
22
  if( sequenceNr == 3 )
23
    sequenceNr = 0;
24
}

mit jedem Aufruf von loop passiert ein bischen was anders. Auf jeden 
Fall werden die UARTs abgefragt, ob ein Zeichen da ist, und wenn ja wird 
es geholt und in den Buffer zwischengespeichert. Von den Sensoren wird 
zum Beispiel bei jedem Durchlauf durch loop() ein anderer Sensor 
abgefragt.
Ziel ist es, dass der µC nie durch übermässiges Hintereinanderausführen 
von einzelnen Funktionen lahmgelegt wird, sondern immer nur ein kleines 
bischen was gemacht wird. Das allerdings bei jedem Durchlauf durch loop. 
Und da diese Durchläufe durch loop() viele tausend male pro Sekunde 
erfolgen, scheint es so, als ob der µC mehr oder weniger alles 
gleichzeitig macht, obwohl er es in kleinen Happen hintereinander 
ausführt.

Und noch was: delay ist streng verboten! (ausser ganz kurze Delay bei 
der Abfrage der Sensoren. Im µs Bereich.)

von Jürgen P. (juergenp)


Lesenswert?

Ok, vielen Dank soweit.
Ich werde das mal testen, hatte nur Angst, dass da was verloren gehen 
müsste. Komme halt aus der Hardware Ecke, daher verlöte ich lieber was, 
als was zu Programmieren ;-)

von Falk B. (falk)


Lesenswert?

Siehe Multitasking

von Reinhard Kern (Gast)


Lesenswert?

Jürgen Papadopolis schrieb:
> Dazu nehme ich Pins 2 und 3
> jeweils als Rx Pin, da die noch Interrupts haben.

Also immerhin hast du schon mal was von Interrupts gehört. Bei seriellen 
Schnittstellen schreibt man sich üblicherweise eine ISR (Interrupt 
Service Routine), die bei Eingang eines Byte (!) aufgerufen wird und das 
Byte in einem softwarebasierten Puffer ablegt, das geht in wenigen 
Taktzyklen (selbstverständlich gibt es da auch nichts zu warten, der 
Interrupt besagt ja, dass ein Byte da ist). Erst wenn eine Message 
komplett ist, z.B. wenn ein CR eingegangen ist, wird das Hauptprogramm 
per Flag benachrichtigt und holt die Message aus dem Puffer. Damit das 
nicht kritisch ist, benutzt man z.B. abwechselnd 2 Puffer oder einen 
Ringpuffer.

Auf die Art kann ein halbwegs schneller Prozessor auf einer ganzen Menge 
Schnittstellen gleichzeitig empfangen.

Gruss Reinhard

PS viele UARTs haben einen eingebauten Puffer, aber üblicherweise nur 15 
Zeichen. Das hilft dir also nicht weiter.

von Karl H. (kbuchegg)


Lesenswert?

@ Rainhard

Das ist am Arduino alles schon vorgefertigt.
http://arduino.cc/de/Reference/SoftwareSerial

Die Serielle (egal ob Hard oder Software) hat einen 64 Byte Buffer und 
ist Interrupt getrieben. d.h. da braucht er sich erst mal keine Sorgen 
zu machen. Solange seine loop() nicht exzessiv trödelt, verliert er 
nichts.

Wenn er natürlich in einer for-Schleife mittels delay eine LED 20 
Sekunden lang blinken lässt, dann kriegt er ein Problem. Leider bewegen 
wir uns allerdings bei Arduino Programmierern oft auf diesem Niveau. Und 
genau das muss man abstellen.

: Bearbeitet durch User
von Falk B. (falk)


Lesenswert?

@ Karl Heinz (kbuchegg) (Moderator)

>Wenn er natürlich in einer for-Schleife mittels delay eine LED 20
>Sekunden lang blinken lässt, dann kriegt er ein Problem. Leider bewegen
>wir uns allerdings bei Arduino Programmierern oft auf diesem Niveau.

Ist Arduino das neue BASCOM?

duckundwech ;-)

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.