PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : serielle schnittstelle? ich habe keine ahnung



farell
15-05-2002, 14:35
Hallo zusammen.
Ich habe die Aufgabe bekommenunter Linux ein Programm zu schreiben welches Daten von der Seriellen Schnittstelle liest und die ASCII-Werte die es empfängt in einer Datei sichert.
Mein Problem ist das ich mich mit Linux eigentlich gar nicht auskenne.
Ich habe ein Programm im Netz gefunden welches eine Verbindung zu Seriellen Port aufbaut.
Es schlägt jedoch immer fehl! Muss ich vielleicht ein Gerät an den Port anschließen damit das klappt oder ist das Programm falsch?
Oder gibt es unter Linux ein paar einfache Befahle die man in ein Skript stecken kann?
Ich hoffe mir kann jemand helfen.


Anbei der Code des Programms:
------------------------------------------------------------------------
#include <stdio.h> /* Standard input/output definitions */
#include <string.h> /* String function definitions */
#include <unistd.h> /* UNIX standard function definitions */
#include <fcntl.h> /* File control definitions */
#include <errno.h> /* Error number definitions */
#include <termios.h> /* POSIX terminal control definitions */

int fd; /* File descriptor for the port */


int open_port(void) {
// * 'open_port()' - Open serial port 1.
// * Returns the file descriptor on success or -1 on error.


fd = open("/dev/ttyS0", O_RDWR | O_NOCTTY | O_NDELAY);
if (fd == -1) {
/*
* Could not open the port.
*/
perror("\nopen_port: Unable to open /dev/ttyS1 - \n\n");
}
else {
fcntl(fd, F_SETFL, 0);
}

return (fd);
}

void close_port() {
close(fd);
}


void main() {

if (open_port() != -1) {
printf("\nVerbindung zum Port wurde hergestellt");
close_port();
printf("\n\nVerbindung wurde getrennt\n");
}
else {
printf("\n\nFehler... Verbindung konnte nicht hergestellt werden\n");
}
}
------------------------------------------------------------------------

anda_skoa
15-05-2002, 17:11
Wie sieht den die Fehlermeldung aus?

Vielleicht hast du keine Rechte auf dem von dir gewählten Device.

Das Programm funktioniert bei mir und es hängt nichts an der seriellen Schnittstelle.

Ciao,
_

P.S.:
in der Fehlermeldung im Programm steht ttyS1 statt ttyS0

farell
15-05-2002, 17:32
Hi anda_skoa.
Das mit den Rechten wars wohl. Als root klappts.

Vielen Dank

anda_skoa
16-05-2002, 09:08
Meistens ist der Besitzer der devices root und eine bestimmte Gruppe.

Füge deinen User zu dieser Gruppe hinzu.

Als root sollte man nur das nötigste laufen lassen.

Ciao,
_

farell
16-05-2002, 10:23
Die Rechte für die Devices sehen wie folgt aus:
crw-rw-r-- 1 root uucp 4, 64 Jul 29 2000 /dev/ttyS0
crw-rw-r-- 1 root uucp 4, 65 Jul 29 2000 /dev/ttyS1

Wie ist das dann wenn mein user in der Gruppe in der er sich befindet (develope) bleiben muss, kann ich denn meinen user in zwei verschiedenen Gruppen haben, also den user zur Gruppe uucp hinzufügen?
Oder kann man einfach die Gruppe der Devices ändern (in develope)?

farell
16-05-2002, 11:18
Nun dann hätte ich noch eine Frage.

Ich hab den Quellcode wie unten beschrieben verändert.

Die Aufgabe lautete: solange ein Programm gestartet wird und bis es beendet wird (im unteren fall 'q' drücken), soll es alle ankommenden Daten auf der seriellen Schnittstelle ausgeben.

Wenn ich das Programm so starte erhalte ich (bei keinem Angeschlossenem Gerät) folgende Ausgabe.
---------------------------------------------------------------------------

Die Verbindung wurde erfolgreich hergestelle
P@~¢
---------------------------------------------------------------------------


Das ist der aktuelle Quellcode (wobei ich glaub das in main() der fehler liegt):
---------------------------------------------------------------------------
#include <stdio.h> /* Standard input/output definitions */
#include <string.h> /* String function definitions */
#include <unistd.h> /* UNIX standard function definitions */
#include <fcntl.h> /* File control definitions */
#include <errno.h> /* Error number definitions */
#include <termios.h> /* POSIX terminal control definitions */

int fd; /* File descriptor for the port */


int open_port(void) {
// * 'open_port()' - Open serial port 1.
// * Returns the file descriptor on success or -1 on error.

fd = open("/dev/ttyS1", O_RDWR | O_NOCTTY | O_NDELAY);
if (fd == -1) {
/* Could not open the port.*/
perror("\nopen_port: Unable to open /dev/ttyS1 - ");
}
else {
printf("\nDie Verbindung wurde erfolgreich hergestelle");
}
return (fd);
}

void close_port() {
close(fd);
}


void main() {

int status;
char retval;
char buffer[100];

status=open_port();
if (status != -1) {

fcntl(status, F_SETFL, FNDELAY);

while(retval!='q'){

/* - kann das so funktionieren? - */
read(status, buffer, 1);
printf("\n%s", buffer);

retval=getchar();
}

close_port();
printf("\n\nVerbindung wurde getrennt\n");
}
}
---------------------------------------------------------------------------

Röme
16-05-2002, 11:31
Ein user hat immer eine Hauptgruppe, darüber hinaus kann er aber weiteren Gruppen angehören.
Diese Gruppe kannst du als root folgendermassen eintragen:

usermod -G uucp dein_user

Nach dem -G können auch mehrere Gruppen durch Kommas separiert angegeben werden.
Alternativ kannst Du Deinen user auch in /etc/group bei der Gruppe uucp eintragen.

Gruss
Röme

farell
16-05-2002, 13:10
Danke für den Tipp Röme.

Ich hab das deinen Anweisungen entsprechend meinen User in die uucp-Gruppe angehängt. Er steht nun auch in der Datei /etc/group hinter uucp mein Name. Aber wenn ich das Skript ausführe kommt trozdem noch die Meldung:
open_port: Unable to open /dev/ttyS1 - : Keine Berechtigung

Kann es sein das ich noch weitere Berechtigungen benötige? Oder muss ich vielleicht irgenteinen Dienst neu starten?

anda_skoa
16-05-2002, 13:15
Der Buffer ist nicht Nullterminiert, was die Vorraussetzung für de benutzen des %s Parameters in printf ist.

Da du ja immer nur ein Zeichen liest, würde %c genügen.

Allgemeiner geht das so:



ssize_t size;

size = read(status, buffer, 99);
if (size > 0)
{
buffer[size] = '\0';
printf("\n%s", buffer);
}


Übrigens, wenn du Code posten möchtest, dann kannst du den code Tag benutzen:
[ code ] und [ /code ] (ohne den Leerzeichen)


Ciao,
_

farell
16-05-2002, 14:52
Eins versteh ich hier noch nicht, was passiert in der Zeile


ssize_t size;


Wenn ich das Programm ausführe so sieht das schon ziemlich gut aus.
Es scheint als das es auf ein Signal wartet.

Zum ausprobieren hab ich auf einem anderen Rechner (Win98) den HyperTerminal gestartet und über den (25. pol) COM2 ein Kabel mit dem Linux Rechner verbunden.

Als ich eine .txt Datei kopieren wollte kam aber nichts an. Wohingegen wenn ich in der Shell "man tail > /dev/ttyS1" eingebe passiert da auf dem Win98 Rechner so einiges (komische ascii zeichen), allerdings wird der Befehl nicht beendet, da muss ich mit STRG+C abbrechen.


Die Zeile "retval=getchar();" hab ich rausgenommen, da das Programm sowieso immer laufen soll und man es dann auch mit kill beenden kannn.
Anbei die aktuelle Version der Main Funktion:


void main() {
int status;
char retval;
char buffer[100];
ssize_t size;

status=open_port();
if (status != -1) {
fcntl(status, F_SETFL, FNDELAY);

while(retval!=-1){

size = read(status, buffer, 99);
if (size > 0)
{
buffer[size] = '\0';
printf("\n%s", buffer);
}
}

close_port();
printf("\n\nVerbindung wurde getrennt\n");
}
}

PS: Das mit dem Codetag is ja cool

anda_skoa
16-05-2002, 19:41
ssize_t size;


Legt eine Variable size vom Typ ssize_t an.
Das ist laut man Page von read deren Rückgabewert.

Vielleicht machst du das while so:


size = 1;
while (size > 0)


Laut manpage von read ist size < 0 wenn ein Fehler auftritt und == 0, wenn die Datei aus ist.

Übrigens ist in meiner Version der manpage von fcntl bei F_SETFL nur O_APPEND, O_NONBLOCK und O_ASYNC erlaubt.

Ciao,
_