Archiv verlassen und diese Seite im Standarddesign anzeigen : Serielle Schnittstelle
Serielle Schnittstelle in C ansprechen
Ich hab schon sämtliche Foren durchstöbert bis ich dieses hier gefunden hab, ich muss nämlich ein programm schreiben, welches Serielle Schnittstellen behandelt, es muss Character versenden können und lesen. Mein Problem ich hab schon einiges zu windoof gefunden aber nix für linux.
Kann mir da wer helfen? Ich schätz mal es ist nicht viel wenn man weiß wie. Ich kann zwar C aber nur das grundlegenste und beim RS 232 ansteuern steig ich aus. Optiomum wäre wenn mir wer die Fus schreiben oder sagen würd wo ich die find für unix.
Hab wirklich schon alles probiert und gelesen, und hoffe hier kompetente Leute zu finden die das meistern können. Muss es aber ohne Sockes machen, das ist der nächste schaß. :confused:
Hallo,
Sockets brauchst du mal keine.
open,read,write,close
reichen dafür.
Zum Einstellen der Schnittstelle:
man termios.
Wenns dann mal soweit ist kann man dann noch
select oder poll mit reinbringen.
Sollte erstmal reichen fürs erste.
Wenn du mal soweit bist kann man ja mal im Detail helfen
jetzt noch Code dafür schreiben ist mir zuviel.
gruß
The Ripper
10-04-2003, 17:24
Noch ein Tip: Die seriellen Schnittstellen sind unter Linux über die Gerätedateien /dev/ttyS0 und /dev/ttyS1 ansprechbar ;)
anda_skoa
10-04-2003, 17:57
Du solltest auch einige älterer Beiträge hier auf mrunix.de finden können.
Eventuell musst du nach serial oder so suchen.
Ciao,
_
vielen dank für die antworten bis jetzt
hab schon gesucht, hilft mir aber nicht wirklich weiter.
wie kann ich zwei serielle interfaces koordinieren?
hoffe, dass mir jemand, wenn er zeit hat, mir etwas mit code schreibt, weil ich mir absolut nix vorstellen kann, kann wirklich nur das grundlegenste auch das handling mit unix so maschinen nahe ist auch nicht meins, muss es aber machen, leider. brauch daher weiter eure hilfe
mfg
DanDanger
12-04-2003, 01:30
Hallo,
folgende Link's sollten Dir sicherlich weiterhelfen :
1) http://www.linuxdoc.org/HOWTO/Serial-Programming-HOWTO/
2) http://www.lvr.com/parport.htm
Im Grunde genommen behandelt Linux (AFAIK alle UNIXe) die Serielle Schnitstelle wie eine (Text-)Datei.
Wenn du also die 1. Serielle Schnitstelle (COM1) unter Linux ansprechen willst, kannst Du das in C/C++ einfach mit open(/dev/ttyS0) machen.
Wenn das Device einmal geöffnet ist, kannst Du dann wie in einem Text-File Daten 'reinschreiben (z.B. Character Senden) und auch wieder auslesen.
MfG
DanDanger
das hilft mir schon einiges weiter, aber wie schaff ich es dass ich zwei programme synchronisiere? weil wenn einer langsamer ist kommt er mit dem lesen oder schreiben nicht nach und löscht so einiges?
The Ripper
12-04-2003, 11:22
Das sog. "Flow Control" kannst du mit der Funktion tcsetattr() aktivieren. Es gibt 2 Arten davon: Hardware-seitig (RTS/CTS) und Software-Seitig (XON/XOFF), entscheide dich für eines und suche einfach in der Manpage nach dem Begriff in der Klammer.
aha und was ist einfacher zu realisiern? bzw was ist effizienter?
anda_skoa
12-04-2003, 12:51
Leichter und effizienter ist Hardwarflsskontrolle.
Leichter, weil sich die Software nicht darum kümmern muss, effizienter, weil es eben die Hardware selber macht.
Ciao,
_
axeljaeger
12-04-2003, 17:57
Nun, bei Hardwareflowcontroll brauchst du meines Wissens nach mehr Adern, nämlich CTS, DTR usw. Bei Software kann man wohl mit drei Adern auskommen
anda_skoa
12-04-2003, 18:28
Ja, aber im Fall von PC-zu-PC Verbindung hat man eigentlich immer eine Leitung, die Hardwarehandshake erlaubt.
Btw, ich glaube softwaregesteuerte serielle Verbindung braucht sogar nur zwei Adern.
Ciao,
_
verwirrts mich nicht mit eure adern, was ist das einfachere? will eine simple verbindung zwischen zwei pcs machen die sich gegenseitig abwechselnd zeichen senden
anda_skoa
13-04-2003, 10:04
Original geschrieben von seal
verwirrts mich nicht mit eure adern, was ist das einfachere? will eine simple verbindung zwischen zwei pcs machen die sich gegenseitig abwechselnd zeichen senden
Wie gesagt, wenn du nicht ein Spezialkabel verwendest, sondern ein übliches Nullmodemkabel, dann HW Flusskontrolle.
Ciao,
_
ja will es mit 0-modem-kabel machen!
hat von euch schon wer ein programm mit serielle schnittstelle gemacht? weil am leichtesten tu ich mich, wenn ich aus Code lernen kann.
DanDanger
15-04-2003, 17:27
Hallo,
ich greife das Thema hier nochmal auf, weil ich da ein kleines "Sprachen-Problem" habe.
Ich habe ein kleines DOS QBasic Programm, das mit :
OPEN "COM2:9600,N,8,1,CS,DS" FOR RANDOM AS #1
die 2. Serielle Schnittstelle (also "/dev/ttyS1") öffnet, mit den Werten :
9600 BAUD, Kein Stopp-Bit, 8Bits, gerade Pariatät, kein Handshake.
Mit :
PRINT #1, CHR$(outbyte);
wird ein Character (hier: "outbyte" genannt) an die Schnittstelle gesendet.
Ich möchte dieses kleine Proggi nun gerne in C/C++ nach Linux Portieren,
weiss aber nicht so genau wie, da mir die o.g. Link's nicht wirklich weiterhelfen (da geht's meist nur um PC <-> PC oder PC <-> MODEM Kommunikation).
Bin für jeden Tipp dankbar :-)
Neugierige Grüsse
DanDanger
DanDanger
15-04-2003, 21:51
Hi,
ich hab den Port nun mit dem Code aus dem Serial-HOWTO (z.B. von http://www.easysw.com/~mike/serial/serial.html )öffnen können,
aber mein Problem ist, dass mein Compiler (gcc) die Befehle
"read()"und "write()" nicht kennt :
Er gibt immer "Implicit declaration of Funktion : int read(...) ... " aus.
Folgende Dateien habe ich includiert :
#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 */
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/signal.h>
#define _POSIX_SOURCE 1
using namespace std ;
Ich Compiliere das Zeug mit : "gcc -o serialIO serialIO.c"
Meine Frage : Muss ich dem Compiler noch irgendwelche Linker-Flags mit übergeben,
oder Warum kennt er read() und write() nicht (sollten eigentlich in termios.h definiert sein) ???
Neugierige Grüsse
DanDanger
anda_skoa
15-04-2003, 22:03
Hmm read und write sind ansich in unistd.h deklariert.
Nimm mal das using namespace weg, das braucht man bei C nicht.
Ciao,
_
DanDanger
16-04-2003, 14:07
Hi,
du hast recht, ohne das "using namespace std" läuft's.
1 Frage hab ich aber noch :
1) Das QBasic Proggi redet über : PRINT #1, CHR$(outbyte); mit meinem Device.
Dabei bedeutet :
- #1 => Der geöffnete COM-Port
- CHR$(outbyte) => Nicht die integer-Zahl "outbyte" (z.B. 23) wird gesendet, sondern der entsprechende ASCII-Wert (CHR$() Wandelt das übergebdne Zeichen in seinen ASCII-Wert um).
- ; => Das Semikolon bedeutet, dass kein Zeilenumbruch stattfindet.
Meine Frage(n) :
- Gibt es so eine Funktion wie CHR$() auch unter C, oder muss ich mir die selber schreiben (z.B. durch eine lookup-Tabelle) ?
- Wie Sende ich Daten mit 'write()' an meine Schnittstelle, ohne Zeilenumbruch (Line-Break) - Zeichen ??
Neugierige Grüsse
DanDanger
PS: Hier ist mein Code, den ich bis jetzt benutze :
port.h :
#ifndef __INC_port_h__
#define __INC_port_h__
int OpenAdrPort (char* sPortNumber);
int WriteAdrPort(char* psOutput);
int ReadAdrPort(char* psResponse, int iMax);
void CloseAdrPort();
#endif /* __INC_port_h__ */
und natürlich die port.c :
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <string.h>
#include <errno.h>
#include "port.h"
static int fd = 0;
// opens the serial port
// return code:
// > 0 = fd for the port
// -1 = open failed
int OpenAdrPort(char* sPortNumber)
{
char sPortName[64];
printf("in OpenAdrPort port#=%s\n", sPortNumber);
sprintf(sPortName, "/dev/ttyS%s", sPortNumber);
printf("sPortName=%s\n", sPortName);
// make sure port is closed
CloseAdrPort(fd);
fd = open(sPortName, O_RDWR | O_NOCTTY | O_NDELAY);
if (fd < 0)
{
printf("open error %d %s\n", errno, strerror(errno));
}
else
{
struct termios my_termios;
printf("fd is %d\n", fd);
tcgetattr(fd, &my_termios);
// NOTE: you may want to save the port attributes
// here so that you can restore them later
printf("old cflag=%08x\n", my_termios.c_cflag);
printf("old oflag=%08x\n", my_termios.c_oflag);
printf("old iflag=%08x\n", my_termios.c_iflag);
printf("old lflag=%08x\n", my_termios.c_lflag);
printf("old line=%02x\n", my_termios.c_line);
tcflush(fd, TCIFLUSH);
my_termios.c_cflag = B9600 | CS8 |CREAD | CLOCAL | HUPCL;
cfsetospeed(&my_termios, B9600);
tcsetattr(fd, TCSANOW, &my_termios);
printf("new cflag=%08x\n", my_termios.c_cflag);
printf("new oflag=%08x\n", my_termios.c_oflag);
printf("new iflag=%08x\n", my_termios.c_iflag);
printf("new lflag=%08x\n", my_termios.c_lflag);
printf("new line=%02x\n", my_termios.c_line);
} // end if
return fd;
} // end OpenAdrPort
// writes zero terminated string to the serial port
// return code:
// >= 0 = number of characters written
// -1 = write failed
int WriteAdrPort(char* psOutput)
{
int iOut;
if (fd < 1)
{
printf(" port is not open\n");
return -1;
} // end if
iOut = write(fd, psOutput, strlen(psOutput));
if (iOut < 0)
{
printf("write error %d %s\n", errno, strerror(errno));
}
else
{
printf("wrote %d chars: %s\n", iOut, psOutput);
} // end if
return iOut;
} // end WriteAdrPort
// read string from the serial port
// return code:
// >= 0 = number of characters read
// -1 = read failed
int ReadAdrPort(char* psResponse, int iMax)
{
int iIn;
printf("in ReadAdrPort iMax=%d\n", iMax);
if (fd < 1)
{
printf(" port is not open\n");
return -1;
} // end if
strncpy (psResponse, "N/A", iMax<4?iMax:4);
iIn = read(fd, psResponse, iMax-1);
if (iIn < 0)
{
if (errno == EAGAIN)
{
return 0; // assume that command generated no response
}
else
{
printf("read error %d %s\n", errno, strerror(errno));
} // end if
}
else
{
psResponse[iIn<iMax?iIn:iMax] = '\0';
printf("read %d chars: %s\n", iIn, psResponse);
} // end if
return iIn;
} // end ReadAdrPort
// closes the serial port
void CloseAdrPort()
{
// you may want to restore the saved port attributes
if (fd > 0)
{
close(fd);
} // end if
} // end CloseAdrPort
Mit OpenAdrPort("1") wird der Port geöffnet,
und mit WriteAdrPort(WERT) wird ein Wert auf den Port geschrieben.
Nur, wie schon gesagt : Wie kriege ich das Line-Break da heraus ???
Gruss
DanDanger
anda_skoa
16-04-2003, 14:24
Original geschrieben von DanDanger
Meine Frage(n) :
- Gibt es so eine Funktion wie CHR$() auch unter C, oder muss ich mir die selber schreiben (z.B. durch eine lookup-Tabelle) ?
brauchst du nicht.
Wenn du einem char einen Wert zuweist, dann ist das immer der ASCII Wert.
- Wie Sende ich Daten mit 'write()' an meine Schnittstelle, ohne Zeilenumbruch (Line-Break) - Zeichen ??
write schreibt nie ein newline, das schreibt nur Bytepuffer.
fprintf schreibt auch nur dann ein newline, wenn man eines angibt.
Mit OpenAdrPort("1") wird der Port geöffnet,
Wäre ja auch mit einem int Parameter gegangen :)
Also OpenAdrPort(int) und dann mit sprintf Format %d
und mit WriteAdrPort(WERT) wird ein Wert auf den Port geschrieben.
Nur, wie schon gesagt : Wie kriege ich das Line-Break da heraus ???
Liegt vielleicht daran, wie du den String erstellst.
Wenn du nur ein Byte schreiben willst, nimm statt char* nur char und statt strlne sizeof(char)
Ciao,
_
DanDanger
16-04-2003, 16:30
Hi,
die Probleme mit dem Line-Break habe ich mittlerweile gelöst :cool:
Das einzige Problem ist noch die Umwandlung von integer-Werten in ihre ASCII-Form.
Der ASCII-Wert von der Zahl 64 ist z.B. das @-Zeichen.
Ich brauche nun eine Funktion, der ich einen int-Wert uebergebe, und die mir dnn das entsprechnende Zeichem im ASCII-Code zurückliefert.
Gibt's sowas schon in den STDL's ?????
Wenn du einem char einen Wert zuweist, dann ist das immer der ASCII Wert.
Wie soll dass den gehen.
Bei :
char c = 64 ;
printf("ASCII-Wert : %s \n", c ) ;
Gibt's ja (zu recht) immer casting-Fehler.
Was mache ich da Falsch ??
Neugierige Grüsse
DanDanger
also so würd ich das machen, das sollt gehen normalerweise
char c = 64;
printf("ASCII-Wert : %c \n", c ) ;
andere bitte, wenn dein programm rennt kannst ma das geben? weil ich hab soviel schon gelesen und ich blick mich nicht durch mit der RS 232.
mfg seal
anda_skoa
16-04-2003, 19:00
Original geschrieben von DanDanger
Der ASCII-Wert von der Zahl 64 ist z.B. das @-Zeichen.
Ich brauche nun eine Funktion, der ich einen int-Wert uebergebe, und die mir dnn das entsprechnende Zeichem im ASCII-Code zurückliefert.
Gibt's sowas schon in den STDL's ?????
Ja, nennt man Zuweisungsoperator.
char c = 64 ;
Siehst du?
Schon ein Zeichen mit ASCII Wert 64 fertig.
printf("ASCII-Wert : %s \n", c ) ;
Gibt's ja (zu recht) immer casting-Fehler.
Was mache ich da Falsch ??
Du versuchst das Zeichen als String zu behandeln. Ein Zeichen ist nun mal kein String.
Ciao,
_
DanDanger
16-04-2003, 21:08
Hallo,
das Programm läuft :-) :-) :D :D :D
DANKE an alle, die geholfen haben.
Damit alle was davon haben :
Hier kommen nun die Quellcodes, die allen RS232-geplagten helfen sollten :
Hier gibt's den Quellcode zu 2 Programmen, eins für PC <-> PC und PC<-> MODEM Kommunikation, und eins für "Rohes" Daten-Senden und empfangen von UART zu UART (Universal Asynchronous Receiver and Transmitter).
Programm 1 :
PC <-> PC Kommunikation über RS232 (Terminal-Programm).
Hier sollte ein gekreuztes (Null-Modem)-Kabel von PC zu PC verwendet werden :
/ * A serial port test program */
#include <termios.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/signal.h>
#include <sys/types.h>
#define BAUDRATE B38400
#define MODEMDEVICE "/dev/ttyS1"
#define _POSIX_SOURCE 1 //POSIX compliant source
#define FALSE 0
#define TRUE 1
volatile int STOP=FALSE;
void signal_handler_IO (int status); //definition of signal handler
int wait_flag=TRUE; //TRUE while no signal received
char devicename[80];
long Baud_Rate = 38400; // default Baud Rate (110 through 38400)
long BAUD; // derived baud rate from command line
long DATABITS;
long STOPBITS;
long PARITYON;
long PARITY;
int Data_Bits = 8; // Number of data bits
int Stop_Bits = 1; // Number of stop bits
int Parity = 0; // Parity as follows:
// 00 = NONE, 01 = Odd, 02 = Even, 03 = Mark, 04 = Space
int Format = 4;
FILE *input;
FILE *output;
int status;
main(int Parm_Count, char *Parms[])
{
char version[80] = " POSIX compliant Communications test program version 1.00 4-25-1999\r\n";
char version1[80] = " Copyright(C) Mark Zehner/Peter Baumann 1999\r\n";
char version2[80] = " This code is based on a DOS based test program by Mark Zehner and a Serial\r\n";
char version3[80] = " Programming POSIX howto by Peter Baumann, integrated by Mark Zehner\r\n";
char version4[80] = " This program allows you to send characters out the specified port by typing\r\n";
char version5[80] = " on the keyboard. Characters typed will be echoed to the console, and \r\n";
char version6[80] = " characters received will be echoed to the console.\r\n";
char version7[80] = " The setup parameters for the device name, receive data format, baud rate\r\n";
char version8[80] = " and other serial port parameters must be entered on the command line \r\n";
char version9[80] = " To see how to do this, just type the name of this program. \r\n";
char version10[80] = " This program is free software; you can redistribute it and/or modify it\r\n";
char version11[80] = " under the terms of the GNU General Public License as published by the \r\n";
char version12[80] = " Free Software Foundation, version 2.\r\n";
char version13[80] = " This program comes with ABSOLUTELY NO WARRANTY.\r\n";
char instr[100] ="\r\nOn the command you must include six items in the following order, they are:\r\n";
char instr1[80] =" 1. The device name Ex: ttyS0 for com1, ttyS1 for com2, etc\r\n";
char instr2[80] =" 2. Baud Rate Ex: 38400 \r\n";
char instr3[80] =" 3. Number of Data Bits Ex: 8 \r\n";
char instr4[80] =" 4. Number of Stop Bits Ex: 0 or 1\r\n";
char instr5[80] =" 5. Parity Ex: 0=none, 1=odd, 2=even\r\n";
char instr6[80] =" 6. Format of data received: 1=hex, 2=dec, 3=hex/asc, 4=dec/asc, 5=asc\r\n";
char instr7[80] =" Example command line: com ttyS0 38400 8 0 0 4 \r\n";
char Param_strings[7][80];
char message[90];
int fd, tty, c, res, i, error;
char In1, Key;
struct termios oldtio, newtio; //place for old and new port settings for serial port
struct termios oldkey, newkey; //place tor old and new port settings for keyboard teletype
struct sigaction saio; //definition of signal action
char buf[255]; //buffer for where data is put
input = fopen("/dev/tty", "r"); //open the terminal keyboard
output = fopen("/dev/tty", "w"); //open the terminal screen
if (!input || !output)
{
fprintf(stderr, "Unable to open /dev/tty\n");
exit(1);
}
error=0;
fputs(version,output); //display the program introduction
fputs(version1,output);
fputs(version2,output);
fputs(version3,output);
fputs(version4,output);
fputs(version5,output);
fputs(version6,output);
fputs(version7,output);
fputs(version8,output);
fputs(version9,output);
fputs(version10,output);
fputs(version11,output);
fputs(version12,output);
fputs(version13,output);
//read the parameters from the command line
if (Parm_Count==7) //if there are the right number of parameters on the command line
{
for (i=1; i<Parm_Count; i++) // for all wild search parameters
{
strcpy(Param_strings[i-1],Parms[i]);
}
i=sscanf(Param_strings[0],"%s",devicename);
if (i != 1) error=1;
i=sscanf(Param_strings[1],"%li",&Baud_Rate);
if (i != 1) error=1;
i=sscanf(Param_strings[2],"%i",&Data_Bits);
if (i != 1) error=1;
i=sscanf(Param_strings[3],"%i",&Stop_Bits);
if (i != 1) error=1;
i=sscanf(Param_strings[4],"%i",&Parity);
if (i != 1) error=1;
i=sscanf(Param_strings[5],"%i",&Format);
if (i != 1) error=1;
sprintf(message,"Device=%s, Baud=%li\r\n",devicename, Baud_Rate); //output the received setup parameters
fputs(message,output);
sprintf(message,"Data Bits=%i Stop Bits=%i Parity=%i Format=%i\r\n",Data_Bits, Stop_Bits, Parity, Format);
fputs(message,output);
} //end of if param_count==7
if ((Parm_Count==7) && (error==0)) //if the command line entrys were correct
{ //run the program
tty = open("/dev/tty", O_RDWR | O_NOCTTY | O_NONBLOCK); //set the user console port up
tcgetattr(tty,&oldkey); // save current port settings //so commands are interpreted right for this program
// set new port settings for non-canonical input processing //must be NOCTTY
newkey.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD;
newkey.c_iflag = IGNPAR;
newkey.c_oflag = 0;
newkey.c_lflag = 0; //ICANON;
newkey.c_cc[VMIN]=1;
newkey.c_cc[VTIME]=0;
tcflush(tty, TCIFLUSH);
tcsetattr(tty,TCSANOW,&newkey);
switch (Baud_Rate)
{
case 38400:
default:
BAUD = B38400;
break;
case 19200:
BAUD = B19200;
break;
case 9600:
BAUD = B9600;
break;
case 4800:
BAUD = B4800;
break;
case 2400:
BAUD = B2400;
break;
case 1800:
BAUD = B1800;
break;
case 1200:
BAUD = B1200;
break;
case 600:
BAUD = B600;
break;
case 300:
BAUD = B300;
break;
case 200:
BAUD = B200;
break;
case 150:
BAUD = B150;
break;
case 134:
BAUD = B134;
break;
case 110:
BAUD = B110;
break;
case 75:
BAUD = B75;
break;
case 50:
BAUD = B50;
break;
} //end of switch baud_rate
switch (Data_Bits)
{
case 8:
default:
DATABITS = CS8;
break;
case 7:
DATABITS = CS7;
break;
case 6:
DATABITS = CS6;
break;
case 5:
DATABITS = CS5;
break;
} //end of switch data_bits
switch (Stop_Bits)
{
case 1:
default:
STOPBITS = 0;
break;
case 2:
STOPBITS = CSTOPB;
break;
} //end of switch stop bits
switch (Parity)
{
case 0:
default: //none
PARITYON = 0;
PARITY = 0;
break;
case 1: //odd
PARITYON = PARENB;
PARITY = PARODD;
break;
case 2: //even
PARITYON = PARENB;
PARITY = 0;
break;
} //end of switch parity
//open the device(com port) to be non-blocking (read will return immediately)
fd = open(devicename, O_RDWR | O_NOCTTY | O_NONBLOCK);
if (fd < 0)
{
perror(devicename);
exit(-1);
}
//install the serial handler before making the device asynchronous
saio.sa_handler = signal_handler_IO;
sigemptyset(&saio.sa_mask); //saio.sa_mask = 0;
saio.sa_flags = 0;
saio.sa_restorer = NULL;
sigaction(SIGIO,&saio,NULL);
// allow the process to receive SIGIO
fcntl(fd, F_SETOWN, getpid());
// Make the file descriptor asynchronous (the manual page says only
// O_APPEND and O_NONBLOCK, will work with F_SETFL...)
fcntl(fd, F_SETFL, FASYNC);
tcgetattr(fd,&oldtio); // save current port settings
// set new port settings for canonical input processing
newtio.c_cflag = BAUD | CRTSCTS | DATABITS | STOPBITS | PARITYON | PARITY | CLOCAL | CREAD;
newtio.c_iflag = IGNPAR;
newtio.c_oflag = 0;
newtio.c_lflag = 0; //ICANON;
newtio.c_cc[VMIN]=1;
newtio.c_cc[VTIME]=0;
tcflush(fd, TCIFLUSH);
tcsetattr(fd,TCSANOW,&newtio);
// loop while waiting for input. normally we would do something useful here
while (STOP==FALSE)
{
status = fread(&Key,1,1,input);
if (status==1) //if a key was hit
{
switch (Key)
{ /* branch to appropiate key handler */
case 0x1b: /* Esc */
STOP=TRUE;
break;
default:
fputc((int) Key,output);
// sprintf(message,"%x ",Key); //debug
// fputs(message,output);
write(fd,&Key,1); //write 1 byte to the port
break;
} //end of switch key
} //end if a key was hit
// after receiving SIGIO, wait_flag = FALSE, input is available and can be read
if (wait_flag==FALSE) //if input is available
{
res = read(fd,buf,255);
if (resɬ)
{
for (i=0; i<res; i++) //for all chars in string
{
In1 = buf[i];
switch (Format)
{
case 1: //hex
sprintf(message,"%x ",In1);
fputs(message,output);
break;
case 2: //decimal
sprintf(message,"%d ",In1);
fputs(message,output);
break;
case 3: //hex and asc
if ((In1ថ) || (In1))
{
sprintf(message,"%x",In1);
fputs(message,output);
}
else fputc ((int) In1, output);
break;
case 4: //decimal and asc
default:
if ((In1ថ) || (In1))
{
sprintf(message,"%d",In1);
fputs(message,output);
}
else fputc ((int) In1, output);
break;
case 5: //asc
fputc ((int) In1, output);
break;
} //end of switch format
} //end of for all chars in string
} //end if resɘ
// buf[res]=0;
// printf(":%s:%d\n", buf, res);
// if (res==1) STOP=TRUE; /* stop loop if only a CR was input */
wait_flag = TRUE; /* wait for new input */
} //end if wait flag == FALSE
} //while stop==FALSE
// restore old port settings
tcsetattr(fd,TCSANOW,&oldtio);
tcsetattr(tty,TCSANOW,&oldkey);
close(tty);
close(fd); //close the com port
} //end if command line entrys were correct
else //give instructions on how to use the command line
{
fputs(instr,output);
fputs(instr1,output);
fputs(instr2,output);
fputs(instr3,output);
fputs(instr4,output);
fputs(instr5,output);
fputs(instr6,output);
fputs(instr7,output);
}
fclose(input);
fclose(output);
} //end of main
/************************************************** *************************
* signal handler. sets wait_flag to FALSE, to indicate above loop that *
* characters have been received. *
************************************************** *************************/
void signal_handler_IO (int status)
{
// printf("received SIGIO signal.\n");
wait_flag = FALSE;
}
/*
An example invocation of this program
This program will allow a user to communicate from one computer to another using two serial lines. It is intended only as a test for the serial connection allowing any possible serial setting. This program is named com when compiled. To use it, the lollowing is an example command line:
com /dev/ttyS0 38400 8 1 0 4
This line works for com1 at 38400 baud, 8 data bits. I make it a file, call it "fcom1" and put it in my system path and invoke it as a script program.
*/
( von : http://ctdp.tripod.com/os/linux/programming/c/linux_pgcserial.html )
einfach mit : "gcc -o com <Dateiname.c>" compilieren.
#############################################
DanDanger
16-04-2003, 21:09
... Fortsetzung von Posting 1 :
Programm 2 :
Dieses Programm benutze ich, um mit meinem RS232-Relais Interface (Marke Eigenbau) zu Kommunizieren. Der Hauptbestandteil des Interface ist ein UART vom Typ CDP6402 der Firma "Harris" (Datenblätter gibt's überall im Netz, einfach mal Googeln).
Das Prpgramm sollte aber auch für alle anderen Fälle geeignet sein, wo man nicht von PC zu PC Kommunizieren will, sondern Daten "Roh" von der Schnittstelle empfagen und Senden will (z.B selbstgebaute Hardware-Interface, Multimeter die über RS232 angesprochen werden könen, etc.).
INFO : Diese Version Kommuniziert über integer-Werte, die zu Übertragungsszwecken jedoch in Ihr Entsprechendes ASCII-Code Zeichen umgewandelt werden (so wird die Zahl 64 z.B. als '@' übertragen)
Der Code ist ein etwas abgewandeltes Beispiel aus [1] :
port.h:
#ifndef __INC_rs232inter_h__
#define __INC_rs232inter_h__
/* Oeffnet den mit <PortNr> angegebenen Port */
/* So oeffnet 0 z.B. "/dev/ttsS0", usw... */
int OpenPort(unsigned int PortNr) ;
/* Schliesst den mit OpenPort() geoeffneten Port */
void ClosePort() ;
/* Schreibt <Data> in den geoeffneten Port */
int WritePortRaw(char *Data) ;
/* Schreibt den ASCII-Wert von <Data> in den Port */
int WritePort(unsigned int Data) ;
/* Liesst <PortData> aus dem geoeffneten Port */
/* Parameteruebergabe mit : ReadPort(&Daten) */
/* Daten enthaelt nun den ausgelesenen Wert */
int ReadPort(char *PortData, int iMax );
#endif /* __INC_rs232inter_h__ */
und port.c :
/* Includierte Dateien */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "rs232inter.h"
/* Globale Variabeln */
/* fd = FileDevice */
static int fd = 0 ;
char PortName[64] ;
int OpenPort(unsigned int PortNr)
{
sprintf(PortName, "/dev/ttyS%i", PortNr);
printf("Oeffne Port : %s \n", PortName) ;
/* Sicher gehen, das der Port geschlossen ist */
ClosePort(fd) ;
/* Flags Setzen */
fd = open(PortName, O_RDWR | O_NOCTTY | O_NDELAY);
if (fd < 0)
{
printf("FEHLER : Kann Port nicht Oeffnen : %d %s\n", errno, strerror(errno));
}
else
{
struct termios my_termios;
tcgetattr(fd, &my_termios);
tcflush(fd, TCIFLUSH);
/* Baudrate und BIT-Flags werden hier gesetzt */
my_termios.c_cflag = B9600 | CS8 |CREAD | CLOCAL | HUPCL;
cfsetospeed(&my_termios, B9600);
tcsetattr(fd, TCSANOW, &my_termios);
} /* Ende der if-else-Abfrage */
/* Rueckgabewert : PortNummer */
return fd ;
}
void ClosePort()
{
/* Wenn ein Port Offen ist (fd > 0) : */
/* Den Port Schliessen */
if (fd > 0)
{
close(fd);
}
}
int WritePortRaw(char *Data)
{
int iOut;
if (fd < 1)
{
printf("FEHLER: Kein Port geoeffnet.\n");
return -1;
}
/* Hier werden nun die daten geschrieben */
/* strlen()-1, weil das Terminationszeichen ('\0') */
/* am Ende eines Strings nicht mitgesendet werden soll */
iOut = write(fd, Data, strlen(Data)-1);
if (iOut < 0)
{
printf("FEHLER : Schreibfehler %d %s\n", errno, strerror(errno));
}
/* Rueckgabewert : Anzahl der gesch. Zeichen */
return iOut;
}
int WritePort(unsigned int Data)
{
int iOut;
char *ASCII ;
if (fd < 1)
{
printf("FEHLER: Kein Port geoeffnet.\n");
return -1;
}
/* Hier werden die Zahlen-Werte in Ihr ASCII-Zeichen umgewandelt */
sprintf(ASCII, "%c", Data );
/* Hier werden nun die daten geschrieben */
/* strlen()-1, weil das Terminationszeichen ('\0') */
/* am Ende eines Strings nicht mitgesendet werden soll */
iOut = write(fd, ASCII, strlen(ASCII)-1);
if (iOut < 0)
{
printf("FEHLER : Schreibfehler %d %s\n", errno, strerror(errno));
}
/* Rueckgabewert : Anzahl der gesch. Zeichen */
return iOut;
}
int ReadPort(char *PortData, int iMax )
{
int iIn;
if (fd < 1)
{
printf("FEHLER : Kein Port offen \n");
return -1;
}
strncpy (PortData, "N/A", iMax<4?iMax:4);
/* Hier werden die Daten vom Port eingelesen */
iIn = read(fd, PortData, iMax-1);
if (iIn < 0)
{
if (errno == EAGAIN)
{
return 0; // assume that command generated no response
}
else
{
printf("FEHLER : Lesefehler %d %s\n", errno, strerror(errno));
}
}
else
{
PortData[iIn<iMax?iIn:iMax] = '\0';
printf("read %d chars: %s\n", iIn, PortData);
} // end if
/* Rueckgabewert : Anzahl der gelesen Zeichen */
return iIn;
}
Als Tstprogramm könnt Ihr die main-Funktion aus [1] nehmen :
Test-Proggi :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "port.h"
// this is the mainline thingee
int main(int argc, char *argv[])
{
char sCmd[254];
char sResult[254];
if (argc < 2 || argc > 2)
{
printf("adrserial needs 1 parameter for the serial port\n");
printf(" ie. use 'adrserial 0' to connect to /dev/ttyS0\n");
return 0;
} // end if
printf("Type q to quit.\n\n");
if (OpenAdrPort(argv[1]) < 0) return 0;
while (1)
{
int iSpot;
printf("?:");
gets(sCmd);
if (sCmd[0] == 'q' || sCmd[0] == 'Q') return 0;
iSpot = strlen(sCmd);
sCmd[iSpot] = 0x0d; // stick a <CR> after the command
sCmd[iSpot+1] = 0x00; // terminate the string properly
if (WriteAdrPort(sCmd) < 0) return 0;
sleep(1); // give the ADR card some time to respond
if (ReadAdrPort(sResult,254) > 0)
{
printf("****Response is %s\n", sResult);
} // end if
} // end while
CloseAdrPort();
} // end main
Nützliche Links :
[1] http://www.ontrak.net/linux.htm
[2] http://www.linuxhq.com/ldp/howto/mini/Leased-Line-2.html (Modem-Kommunikation)
[3] http://www.circlemud.org/~jelson/software/parapin/ (für Parallel-Port)
Viel Spass und viel Erfolg
DanDanger
anda_skoa
16-04-2003, 21:13
Hi DanDanger,
Wie wäre es mit einem schnuckeligen tar.gz oder zip Archiv statt irre langen Code?
Ciao,
_
bin glad dass überhaupt da ist
danke
bei mir geht das Programm nicht!
muss man bei linux die RS 232 erst freischalten dass sie geht?
oder muss man beim kompilieren irgendwas anhängen?
mfg
DanDanger
05-05-2003, 16:35
Hi,
includier mal folgende Dateien :
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <string.h>
#include <errno.h>
Die Programme kannst Du ganz einfach mit :
gcc -o ANWENDUNGSNAME DATEINAME.c
Kompilieren......
Gruss
DanDanger
aha, naja, dass hab ich eh gemacht!
ich kompielier das programm und für es auf Rechner A und B aus
das eine als Server, der andere Client und es geht nicht!
Fragen:
muss man bei SUSE linux 8.1 irgendwie was einstellen um die RS 232 zu benutzen?
funkt das Programm 100%ig?
DanDanger
06-05-2003, 12:53
Das Proggi funzt bei mir (SuSe 7.3 Pro) 100%ig.
Schau doch mal, ob Du überhaupt die nötigen Rechte hast, auf die Serielle Schnitstelle zuzugreifen (Notfalls das Proggi mal als 'root' ausführen)......
Ein weiterer Grund kann auch sein, das schon ein anderes Programm auf die Schnittstelle zugreift (z.B. irgendein Daemon, event. für dein Modem, etc.).
Einfach mal mit 'top' die Prozessliste anschauen und "verdächtige" Proggi's killen :D
BTW: Ich glaube, SuSe 8.x benutzt nicht mehr das "alte" /dev - Filesystem, sondern teilt die Devices jetzt anders auf ( /dev/hda1 => /dev/IDE/hd/hda1 [oder so ähnlich]).
Einfachmal im Handbuch nachschlagen, womit du jetzt auf die Ser. Schnitts. zugreifen kannst, und en Pfad dann in der "rs232inter.c" entsprechend anpassen.
Gruss
DanDanger
vielen dank probier ich gleich mal!
Aber:
kannst den code ohne smilieys und so reingeben weil teilweise
if (res?
{
for (i=0; i<res; i++) //for all chars in string
{
In1 = buf[i];
switch (Format)
{
case 1: //hex
sprintf(message,"%x ",In1);
fputs(message,output);
break;
case 2: //decimal
sprintf(message,"%d ",In1);
fputs(message,output);
break;
case 3: //hex and asc
if ((In1? || (In1?)
{
sprintf(message,"%x",In1);
fputs(message,output);
}
else fputc ((int) In1, output);
break;
case 4: //decimal and asc
default:
if ((In1? || (In1?)
{
sprintf(message,"%d",In1);
fputs(message,output);
}
else fputc ((int) In1, output);
break;
werden durch die smiley seltsame sachen gemacht! zB
wozu: if ((In1? || (In1?)
das kann nicht gehen da fehlt eine klammer zu und warum die '?'
DanDanger
07-05-2003, 10:17
Ersetze einfach die Smilies (oder das "?") durch ; ) (also Semikolon und Klammer-Zu)
Powered by vBulletin® Version 4.2.5 Copyright ©2025 Adduco Digital e.K. und vBulletin Solutions, Inc. Alle Rechte vorbehalten.