Linux: serielle Schnittstelle programmieren um kontinuierlich zu senden

Im Unterforum Hardware, Betriebssysteme, Programmiersprachen - Beschreibung: Alles zu Software, Hardware, Windows, Linux, Programmiersprachen
Anfragen zu Modding, Games, Cracks, etc. unerwünscht.

Elektronik Forum Nicht eingeloggt       Einloggen       Registrieren




[Registrieren]      --     [FAQ]      --     [ Einen Link auf Ihrer Homepage zum Forum]      --     [ Themen kostenlos per RSS in ihre Homepage einbauen]      --     [Einloggen]

Suchen


Serverzeit: 19 4 2024  02:53:25      TV   VCR Aufnahme   TFT   CRT-Monitor   Netzteile   LED-FAQ   Osziloskop-Schirmbilder            


Elektronik- und Elektroforum Forum Index   >>   Hardware, Betriebssysteme, Programmiersprachen        Hardware, Betriebssysteme, Programmiersprachen : Alles zu Software, Hardware, Windows, Linux, Programmiersprachen
Anfragen zu Modding, Games, Cracks, etc. unerwünscht.


Autor
Linux: serielle Schnittstelle programmieren um kontinuierlich zu senden

    







BID = 781320

ffeichtinger

Schreibmaschine



Beiträge: 1050
Wohnort: Traunkirchen im Salzkammergut
 

  


Hallo

Es geht darum die serielle Schnittstelle unter Linux in C zu programmieren.

Ich habe mich bereits mit der termios-Struktur erfolgreich auseinandergesetzt. Die Schnittstelle öffnen, konfigurieren, lesen, schreiben geht also schon.

Nun möchte ich aber nicht einen vorher definierten Datensatz schreiben sondern kontinuierlich immer wieder die gleiche Sequenz ausgeben und zwar möglichst gleichmäßig. Ob die Zeichen direkt aufeinander folgen oder eine kurze (immer gleiche) Pause entsteht ist egal.

Das Ganze soll zum Testen der seriellen Schnittstelle dienen und ein Signal liefern, dass ich mit dem (analogen) Oszi erfassen kann.

Mit einem Mikrocontroller geht das ja ganz einfach. Ich muss nur warten, bis der UART das entsprechende Flag setzt, dass der Transmitter wieder frei ist und wieder senden. Diese Lösung scheidet hier leider aus.

Ich könnte natürlich auch einfach einen dummy-Datensatz erzeugen der groß genug ist, dass er die Schnittstelle eine Zeit lang blockiert. Aber solche Tricksereien interessieren mich jetzt nicht.


Es geht mir, wie so oft, darum eine saubere (schöne) Lösung zu finden und dabei etwas zu lernen.


Im Prinzip geht es ja nur um die zeitliche Steuerung. Ich bräuchte so was wie ein Signal von der Schnittstelle, dass mein Programm zum weiter senden auffordert. Ich habe mir auch schon den Befehl sleep angesehen, aber der geht minimal bis eine Sekunde herunter, was viel zu langsam ist.

mfg Fritz

_________________

BID = 781360

DonComi

Inventar



Beiträge: 8605
Wohnort: Amerika

 

  

Hallo Fritz,

so ganz schlau werde ich aus deinen Ausführungen leider nicht.
Du willst einen kontinuierlichen Datenstrom senden, oder wie?

Dann mach das doch einfach, dazu benötigst du nicht mal C, das geht auch mittels stty (Serielle Schnittstelle konfigurieren) und dann mit sagen wir mal

cat /dev/random > /dev/tty*


Wenn es unbedingt C sein muss, dann schau dir mal select() an. Alternativ kannst du auch den Puffer für den Deskriptor, der von open() zurückgeliefert wird, auf NULL setzen, dann läuft das ganze zeichenweise.

So ganz habe ich aber das Problem nicht verstanden, um dir umfangreich zu helfen, zumal die Lösungen alle auf höherer Ebene ansetzen, also nicht auf Registerebene der Hardware, was auch schwachsinnig wäre, wenn man das ganze z.B. mit einem USB-Adapter machen wollte. Als user geht das dann auch nicht mehr.

Edit:

Zitat :

ch bräuchte so was wie ein Signal von der Schnittstelle, dass mein Programm zum weiter senden auffordert.

Das brauchst du eben nicht, das erledigt alles der Treiber!
Du brauchst bloß kontinuierlich Daten in den Deskriptor schieben, also etwa so:

#include <unistd.h>

int tty = open(...);

char mydata[1024];
memset(mydata, 0xaa, sizeof mydata);

for(;;) {
 write(tty, mydata, sizeof mydata);
/*
 usleep(1000); /* eine Millisekunde schlafen */
 */
}



Das kann allerdings schon ein wenig belastend sein, und so kannst du das ein wenig mittels usleep bzw. nsleep ausbremsen.

Davon abgesehen kannst du dir wirklich auch Signale schicken lassen mittels Systemaufruf signal(), wenn der Treiber bereits für neue Daten ist. Dir schickt man dann ein SIGIO.
Oder du machst das mittels select() oder poll() oder setzt den Deskriptor auf blockieren, dann blockiert write() solange, bis die Daten raus sind. Es gibt da unter Linux mit entsprechenden Systemaufrufen viele Möglichkeiten .


_________________



[ Diese Nachricht wurde geändert von: DonComi am 16 Aug 2011 16:59 ]

BID = 781454

ffeichtinger

Schreibmaschine



Beiträge: 1050
Wohnort: Traunkirchen im Salzkammergut

Hallo

Ich hab inzwischen eine Lösung gefunden, die mir ganz gut gefällt, siehe Anhang. Allerdings ist das auch nicht perfekt, da es scheinbar relativ lange dauert bis das Abbruch-Signal bei meinem Programm ankommt.


Zitat :



Code :

for(;;) {


write(tty, mydata, sizeof mydata);

/*

usleep(1000); /* eine Millisekunde schlafen */

*/

}




Ja, aber wenn ich das so mache dann ist die Wartezeit entweder zu lang, was nach jedem Block eine Pause erzeugt, oder zu kurz, was dazu führt, dass der Schreibpuffer irgendwann überlaufen wird.

Es geht eben wie gesagt darum an der Schnittstelle ein Signal zu erhalten, dass mit dem Oszilloskop erfassbar, also periodisch ist. Ich muss also immer das gleiche Byte immer wieder senden, wobei die Pause dazwischen immer die gleiche sein soll. Einfach auf Verdacht warten, bis die Schnittstelle wieder bereit ist geht eben nicht.

mfg Fritz


_________________

BID = 781457

DonComi

Inventar



Beiträge: 8605
Wohnort: Amerika


Zitat :

was dazu führt, dass der Schreibpuffer irgendwann überlaufen wird.

Wenn ich mich recht erinnere, wird es keinen Pufferüberlauf erzeugen, wenn du Daten ohne Ende reinschiebst.
Sobald die Daten zu schnell kommen, wird write() irgendwann blockieren, bis weitere Daten gesendet werden können. Insofern würde ich alles, was den Prozess/Thread einschlafen lässt, komplett weglassen, also einfach nur

while(sending) {
 ret = write(fd, data, size);
 if(ret ...) ...
}


Ich habe das auch eben mal probiert mit

strace dmesg > /dev/ttyUSB0

Wobei ttyUSB0 auf 9600 Baud konfiguriert ist. write() blockiert solange, bis wieder Platz im Transmitbuffer ist.


Wesentlich genauer wirst du es nicht hinbekommen, da kein Echtzeitsystem zugrundeliegt.
Wenn es auf die Mikrosekunde genau sein soll, dann entweder die Hälfte des Treibers selbst implementieren oder was anderes überlegen.

_________________

BID = 781460

ffeichtinger

Schreibmaschine



Beiträge: 1050
Wohnort: Traunkirchen im Salzkammergut


Zitat :

Wesentlich genauer wirst du es nicht hinbekommen, da kein Echtzeitsystem zugrundeliegt.


Ja, das denke ich auch. So wie es jetzt ist scheint es aber gut zu funktionieren. Eine Pause zwischen den Blöcken merkt man nicht.

Trotzdem vielen Dank. Du hast mir wieder viele wertvolle Linux-Befehle genannt, die ich mir sicher noch genauer ansehen werde.

mfg Fritz

_________________


Zurück zur Seite 0 im Unterforum          Vorheriges Thema Nächstes Thema 


Zum Ersatzteileshop


Bezeichnungen von Produkten, Abbildungen und Logos , die in diesem Forum oder im Shop verwendet werden, sind Eigentum des entsprechenden Herstellers oder Besitzers. Diese dienen lediglich zur Identifikation!
Impressum       Datenschutz       Copyright © Baldur Brock Fernsehtechnik und Versand Ersatzteile in Heilbronn Deutschland       

gerechnet auf die letzten 30 Tage haben wir 24 Beiträge im Durchschnitt pro Tag       heute wurden bisher 0 Beiträge verfasst
© x sparkkelsputz        Besucher : 180923973   Heute : 465    Gestern : 8415    Online : 671        19.4.2024    2:53
1 Besucher in den letzten 60 Sekunden        alle 60.00 Sekunden ein neuer Besucher ---- logout ----viewtopic ---- logout ----
xcvb ycvb
0.0652561187744