Forum: Mikrocontroller und Digitale Elektronik AVR32 Senden über USB via UART


von Kossi (Gast)


Lesenswert?

Liebe Leser,
ich übertrage Daten über USB an einen Host-PC. Durch den AVR Treiber 
wird an diesem ja ein virtueller COM-Port für die Übertragung 
eingerichtet. Als µC nutze ich den Atmel 32UC3A1512.

Hierzu benutze ich die Funktion in "uart_usb_lib.h"
1
uart_usb_putchar( SENDEWERT );
Alleine dieser Aufruf bringt kein Erfolg.
Erst durch folgenden Code ist das Senden an den virtuellen COM-Port 
möglich. Ich lasse es mir per Terminalprogramm hterm am PC anzeigen.
1
if ( TRUE == uart_usb_tx_ready() )
2
{
3
uart_usb_putchar( SENDEWERT );
4
uart_usb_flush(); // nicht warten bis Sendebuffer voll, sondern sofort senden
5
}

Meine Frage: Wenn ich nun kontinuierlich jede ms ein Wert an den Host-PC 
schicken möchte, dann könnte ich dies ja in eine ISR (Interrupt Service 
Routine)"verpacken". Der µC fungiert in dieser Kommunikation wohl eher 
als Slave bzw. Device. Der PC wird doch sicherlich die Host Funktion 
übernehmen. Also initiiert der PC ja die Datenübertragung?! Der µC 
pushed nun nicht die Daten zum Host, sondern der Host fragt 
kontinuierlich den Sendebuffer der µC ab, oder!? Wenn diese Abfrage aber 
nur beispielsweise alle 2ms erfolgen würde, dann wäre das Senden über 
die ISR, die jede ms aufgerufen wird, nutzlos?!

Hintergrund ist:
Mir ist nämlich aufgefallen, dass wenn ich in einer ISR jede ms einen 
Wert an den Host-PC sende, kann ich die Anzahl der empfangenen Werte 
übers Terminalprogramm Hterm zählen lassen.
10min = 600s = 600.000ms
Folglich müsste ich in 10min 600.000 Werte empfangen.
Nun habe ich beim Start der Übertragung die Stoppuhr loslaufen lassen. 
Als Hterm mir anzeigte, dass ich den 600.000sten Wert empfangen habe, 
stoppte ich die Zeit auf der Stoppuhr. Es müsste eine Zeit von 10min auf 
der Uhr zu lesen sein. Dies war aber nicht der Fall, sie zeigte nämlich 
10:07 min an. Ich finde, dass 7 Sekunden doch schon eine gewaltige 
Abweichung sind.

von Potter S. (potter68)


Lesenswert?

Der Host polled regelmäßig den Slave, um zu sehen, ob neue Daten 
vorliegen. Aber dieses 'regelmäßig' hat eben eine gewisse Abweichung.

Wenn der Host nur alle 2 ms polled und Deine Interrupt-Routine alle ms 
aufgerufen wird, dann gibt die Funktion uart_usb_tx_ready() bei jedem 
zweiten Mal FALSE zurück.

Hast Du keinen Zugriff auf die Daten am PC? Werden die einfach so am 
Terminal ausgegeben und das wars?

von Kossi (Gast)


Lesenswert?

Wie gesagt ohne die if-Abfrage mit der Funktion uart_usb_tx_ready() 
funktioniert das Senden auch gar nicht.
Aber muss ich dann nun "genau diesen Zeitpunkt abpassen", wann 
uart_usb_tx_ready() TRUE ist, damit ich was senden kann?!

Kann sich jemand die 7 Sekunden Abweichung erklären, die ich im 1. Post 
beschrieben hatte?

Zurzeit lasse ich mir die Werte nur per Terminal anzeigen. Später 
erfolgt aber einer Weiterverarbeitung der Daten in MATLAB

von Potter S. (potter68)


Lesenswert?

uart_usb_tx_ready() gibt Dir TRUE zurück, sobald der 
Endpunkt-Datenpuffer frei ist. Es verhindert also das Überschreiben noch 
nicht gesendeter Daten.

Was ist eigentlich die Aufgabenstellung? Mir ist nicht ganz klar, was 
Dich an den 7 Sekunden stört. Wie gesagt, der USB ist für eine 
Zeitmessung ungeeignet, wegen der bereits erwähnten Ungenauigkeit.

Wenn du die Daten mit Matlab verarbeitest, dann hat das Ganze sowieso 
nichts mehr mit Echtzeit zu tun. Du könntest also hergehn und jedem 
Datensatz einen Zeitstempel spendieren, womit es dann auch keine Rolle 
mehr spielt, wann die Daten am PC ankomme

von Kossi (Gast)


Lesenswert?

Es sollen damit EKG-Daten übertragen werden. Ansich hast du 
Recht..Zeitstempel o.ä. und fertig. Ich dachte mir nur, wenn man in 
Matlab den EKG-Monitor ausgibt - also sprichwörtliche Herzkurve, dann 
erscheint es mir blöd, wenn dieser Monitor nach 10min um 7 Sekunden 
hinterherhängt.

Ich habe scherzenshalber mal ein paar Messungen aufgenommen:
Wenn die den Timer-Ladewert dementsprechend auflade, dass die ISR jede 
ms aufgerufen wird, in welcher die Daten gesendet werden, dann gibt es 
die 7 Sekunden "Verzögerung".
Schreibe ich in der gleichen ISR eine Schleife, sodass die Sendefunktion 
nur jedes 100. Mal aufgerufen wird - sprich 100ms, dann ist noch eine 
"Verzögerungszeit" von 3 Sekunden zu verbuchen.
Hingegen, wenn ich den Timer-Ladewert für den Aufruf der ISR 
dementsprechend anpasse, dass sie nur alle 100ms aufgerufen wird und nun 
alle 100ms gesendet wird, dann gibt es KEINE "Verzögerungszeit".

Aber eventuell ist es besser, das Senden in die Hauptprogrammschleife zu 
programmieren, sodass in der aufgerufenen ISR nur die Abtastung mittels 
ADC erfolgt. Dessen Werte sollen ja anschließend weitergesendet werden.

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.