16. november 2005 - 00:17Der er
49 kommentarer og 1 løsning
serial port i Linux
Hej...
jeg har siddet og kigget på diverse ting der skulle kunne skrive til serielporten i linux, men jeg har ikke rigtig fundet noget der virkede (som jeg kunne compile)
Er der en der har et virkende eksempel på hvordan C/C++ kan håndtere serielporten i Linux?
altså som sådan skulle man vel lave det sådan at man kan skrive til com porten som til en fil ... eller noget lignende. så jeg fx kan skrive på porten og så modtager en hyperterminal (eller samme program på en anden maskine) det jeg skriver. ?
/* baudrate settings are defined in <asm/termbits.h>, which is included by <termios.h> */ #define BAUDRATE B38400 /* change this definition for the correct port */ #define MODEMDEVICE "/dev/ttyS1" #define _POSIX_SOURCE 1 /* POSIX compliant source */
#define FALSE 0 #define TRUE 1
volatile int STOP=FALSE;
int main() { int fd, res; char buf[255]; /* Open modem device for reading and writing and not as controlling tty because we don't want to get killed if linenoise sends CTRL-C. */ fd = open(MODEMDEVICE, O_RDWR); if (fd < 0) { perror(MODEMDEVICE); exit(-1); } buf[0] = 0x04; write(fd, buf, 1); close(fd); }
Alt i Linux er en fil ja. Alle programmerings og scripting sprog kan læse og skrive til filer hvilket gør at linux arkitekturmæssigt er ufatteligt kraftfuldt for selv det mindste scripting sprog.
Men du skal skrive til den rigtige fil. Dine devices er i /dev folderen. Kig efter om du har et com1 device der, eller om det hedder ttyS0 osv.
ok, men så vil jeg gerne se dig skrive råt output til seriel port, harddisk, lydkort, printer, osv med bare een linje i en kommandoprompt på Windows =)
ja men hvis du gør sådan så får du vel ikke sat porten op til at skrive til den ? altså med baud osv ? Det skal man jo i hvert tilfælde i hyperterminalen i windows
Kan lige så godt være ttyS1 eller ttyS2. Jeg kan egentlig ikke huske kommandoen til at se hvilken terminal er logget på. Måske er det bare så simpelt som at skrive "who". Jeg har ikke min linux kasse tændt ligenu.
Hvis den kompilerer unden at skrive noget, tyder det på at det virker. Har den lavet et program? Programmet hedder måske a.out hvis ikke du har fortalt den hvad det skal hedde. Du kan bruge -omyprogram hvis du vil have programmet til at hedde myprogram
hvis jeg bruger g++ -o serial ./serialtest.cpp så laver den en fil (serial) og jeg bruger så chmod 0x serial til at gøre den eksekverbar og den kører også men der sker intet
Ja, hyperterminal på Windows burde kunne læse det du skriver fra Linux. Det kræver kun et NULL-modem kabel og at hyperterminal er sat rigtigt op, f.ex. med baud-rate. Kan du få andre programmer på linux til at sende til windows maskinen?
/* baudrate settings are defined in <asm/termbits.h>, which is included by <termios.h> */ #define BAUDRATE B115800 /* change this definition for the correct port */ #define MODEMDEVICE "/dev/ttyS0" #define _POSIX_SOURCE 1 /* POSIX compliant source */
#define FALSE 0 #define TRUE 1
volatile int STOP=FALSE;
int main() { int fd, res; char buf[255]; /* Open modem device for reading and writing and not as controlling tty because we don't want to get killed if linenoise sends CTRL-C. */ fd = open(MODEMDEVICE, O_RDWR); if (fd < 0) { perror(MODEMDEVICE); exit(-1); } buf[0] = 0x04; write(fd, buf, 1); close(fd); }
hmm... nu har jeg fundet ud af at det "kun" virker når jeg har været inde i minicom først, idet der elelrs ikke er åbnet for porten (den skal vel initialiseres på en eller anden måde ?)
Jeg mener bestemt at du bruger setserial til at sætte hastighed, paritet osv på porten. "man setserial". Dette altså forudsagt at jeg forstår dit spørgsmål helt rigtigt.
/* baudrate settings are defined in <asm/termbits.h>, which is included by <termios.h> */ #define BAUDRATE B115200 /* change this definition for the correct port */ #define MODEMDEVICE "/dev/ttyS0" #define _POSIX_SOURCE 1 /* POSIX compliant source */
#define FALSE 0 #define TRUE 1
volatile int STOP=FALSE;
/* Name: Main Function: Opens and Initializes the SerialPort. And then writes to it. */
main() { int fd,c, res; struct termios oldtio,newtio; char buf[255]; /* Open modem device for reading and writing and not as controlling tty because we don't want to get killed if linenoise sends CTRL-C. */
/* BAUDRATE: Set bps rate. You could also use cfsetispeed and cfsetospeed. CRTSCTS : output hardware flow control (only used if the cable has all necessary lines. See sect. 7 of Serial-HOWTO) CS8 : 8n1 (8bit,no parity,1 stopbit) CLOCAL : local connection, no modem contol CREAD : enable receiving characters */ newtio.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD;
/* IGNPAR : ignore bytes with parity errors ICRNL : map CR to NL (otherwise a CR input on the other computer will not terminate input) otherwise make device raw (no other input processing) */ newtio.c_iflag = IGNPAR | ICRNL;
/* Raw output. */ newtio.c_oflag = 0;
/* ICANON : enable canonical input disable all echo functionality, and don't send signals to calling program */ newtio.c_lflag = ICANON;
/* initialize all control characters default values can be found in /usr/include/termios.h, and are given in the comments, but we don't need them here */ newtio.c_cc[VINTR] = 0; /* Ctrl-c */ newtio.c_cc[VQUIT] = 0; /* Ctrl-\ */ newtio.c_cc[VERASE] = 0; /* del */ newtio.c_cc[VKILL] = 0; /* @ */ newtio.c_cc[VEOF] = 4; /* Ctrl-d */ newtio.c_cc[VTIME] = 0; /* inter-character timer unused */ newtio.c_cc[VMIN] = 1; /* blocking read until 1 character arrives */ newtio.c_cc[VSWTC] = 0; /* '\0' */ newtio.c_cc[VSTART] = 0; /* Ctrl-q */ newtio.c_cc[VSTOP] = 0; /* Ctrl-s */ newtio.c_cc[VSUSP] = 0; /* Ctrl-z */ newtio.c_cc[VEOL] = 0; /* '\0' */ newtio.c_cc[VREPRINT] = 0; /* Ctrl-r */ newtio.c_cc[VDISCARD] = 0; /* Ctrl-u */ newtio.c_cc[VWERASE] = 0; /* Ctrl-w */ newtio.c_cc[VLNEXT] = 0; /* Ctrl-v */ newtio.c_cc[VEOL2] = 0; /* '\0' */
/* now clean the modem line and activate the settings for the port */ tcflush(fd, TCIFLUSH); tcsetattr(fd,TCSANOW,&newtio);
/* Nu skriver jeg et tegn på porten og lukker den igen. */
/* baudrate settings are defined in <asm/termbits.h>, which is included by <termios.h> */ #define BAUDRATE B115200 /* change this definition for the correct port */ #define MODEMDEVICE "/dev/ttyS0" #define _POSIX_SOURCE 1 /* POSIX compliant source */
#define FALSE 0 #define TRUE 1
volatile int STOP=FALSE;
/* Name: Main Function: Opens and Initializes the SerialPort. And then writes to it. */
main() { int fd,c, res; struct termios oldtio,newtio; char buf[255]; /* Open modem device for reading and writing and not as controlling tty because we don't want to get killed if linenoise sends CTRL-C. */
/* BAUDRATE: Set bps rate. You could also use cfsetispeed and cfsetospeed. CRTSCTS : output hardware flow control (only used if the cable has all necessary lines. See sect. 7 of Serial-HOWTO) CS8 : 8n1 (8bit,no parity,1 stopbit) CLOCAL : local connection, no modem contol CREAD : enable receiving characters */ newtio.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD;
/* IGNPAR : ignore bytes with parity errors ICRNL : map CR to NL (otherwise a CR input on the other computer will not terminate input) otherwise make device raw (no other input processing) */ newtio.c_iflag = IGNPAR | ICRNL;
/* Raw output. */ newtio.c_oflag = 0;
/* ICANON : enable canonical input disable all echo functionality, and don't send signals to calling program */ newtio.c_lflag = ICANON;
/* initialize all control characters default values can be found in /usr/include/termios.h, and are given in the comments, but we don't need them here */ newtio.c_cc[VINTR] = 0; /* Ctrl-c */ newtio.c_cc[VQUIT] = 0; /* Ctrl-\ */ newtio.c_cc[VERASE] = 0; /* del */ newtio.c_cc[VKILL] = 0; /* @ */ newtio.c_cc[VEOF] = 4; /* Ctrl-d */ newtio.c_cc[VTIME] = 0; /* inter-character timer unused */ newtio.c_cc[VMIN] = 1; /* blocking read until 1 character arrives */ newtio.c_cc[VSWTC] = 0; /* '\0' */ newtio.c_cc[VSTART] = 0; /* Ctrl-q */ newtio.c_cc[VSTOP] = 0; /* Ctrl-s */ newtio.c_cc[VSUSP] = 0; /* Ctrl-z */ newtio.c_cc[VEOL] = 0; /* '\0' */ newtio.c_cc[VREPRINT] = 0; /* Ctrl-r */ newtio.c_cc[VDISCARD] = 0; /* Ctrl-u */ newtio.c_cc[VWERASE] = 0; /* Ctrl-w */ newtio.c_cc[VLNEXT] = 0; /* Ctrl-v */ newtio.c_cc[VEOL2] = 0; /* '\0' */
/* now clean the modem line and activate the settings for the port */ tcflush(fd, TCIFLUSH); tcsetattr(fd,TCSANOW,&newtio);
/* Nu skriver jeg et tegn på porten og lukker den igen. */
Du burde kunne læse med read. Du skal nok sætte den op til om du vil vente på at der bliver modtaget noget eller den skal returnere med det samme. De steder jeg har brugt det har jeg brugt ioctl til det.
men mht read så vil det være sådan at den får en string eller lignende hver gang der bliver skrevet til den hvis det er. I så fald skal den bare tage det og smække det i en fil (istedet for skrive det på skærmen)
Prøv at skrive man ioctl på din Linux box. Lidt søgning på google giver f.ex: o If the object the descriptor is associated with is marked for 4.2BSD-style non-blocking I/O (with the FIONBIO ioctl() request or a call to fcntl(2V) using the FNDELAY flag from <sys/file.h> or the O_NDELAY flag from <fcntl.h> in the 4.2BSD environment), the read will return -1 and errno will be set to EWOULDBLOCK.
ok, kan være jeg lige kigger på det senere. lige nu skal jeg vist koncentrere mig om at få den til at kommunikere med mit php. Det burde dog være tilgængeligt under linux.
Tak for hjælpen. Jeg vender tilbage hvis jeg får brug for hjælp til read.
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.