This is a multi-part message in MIME format. --------------000902080100000806010905 Content-Type: text/plain; charset=us-ascii; format=flowed Content-Transfer-Encoding: 7bit I guess this can help. It's from a HOWTO, I just updated the include file names to be compatible to the newer glibc Francisco Herbert Graf wrote: >Hello all, > >I'm trying to write a small program that sends a few things over a serial >port and then reads a few things back. I've having trouble getting it to >work. > >I'm using open, write and read to do my things, accessing the device through >the /dev/ttyS1 interface. Things work fine for a while and then seem to go >crazy. For example, I can send a few things down the line, but then when I >do a single byte read from the port I continuously get the newline >character. > >Anybody have some simple gcc compatible c code of accessing the serial port >in Linux? I'm using Redhat 9.0 and gcc. Thanks, TTYL > >---------------------------------- >Herbert's PIC Stuff: >http://repatch.dyndns.org:8383/pic_stuff/ > >-- >http://www.piclist.com hint: PICList Posts must start with ONE topic: >[PIC]:,[SX]:,[AVR]: ->uP ONLY! [EE]:,[OT]: ->Other [BUY]:,[AD]: ->Ads > >. > > > -- http://www.piclist.com hint: PICList Posts must start with ONE topic: [PIC]:,[SX]:,[AVR]: ->uP ONLY! [EE]:,[OT]: ->Other [BUY]:,[AD]: ->Ads --------------000902080100000806010905 Content-Type: text/x-csrc; name="miniterm.c" Content-Disposition: inline; filename="miniterm.c" Content-Transfer-Encoding: quoted-printable X-MIME-Autoconverted: from 8bit to quoted-printable by telcommail.net id i1GL4vEL074137 /*! * \file miniterm.c * \author Sven Goldt (goldt@math.tu-berlin.de) * * \brief RS232 controllable device terminal * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * This is like all programs in the Linux Programmer's Guide meant * as a simple practical demonstration. * It can be used as a base for a real terminal program. * =20 * updated for newer include files for glibc 2.3.1 * by Francisco J. A. Ares (frares@netscape.net) * * updated to work with RS232 controllable device * by Francisco J. A. Ares (frares@netscape.net) */ #include #include #include #include #include #include #include #include #include /*! \brief Defini=E7=E3o da velocidade a ser usada */ #define BAUDRATE B9600 /*! \brief Ctrl-D =E9 usado para sair do \b miniterm */ #define ENDMINITERM 4 /*! \brief Caractere de retorno de carro */ #define CRETURN 0x0d /*! \brief Caractere de avan=E7o de linha */ #define NLINE 0x0a /*! \brief Defini=E7=E3o de l=F3gica bin=E1ria para \b FALSE */ #define FALSE 0 /*! \brief Defini=E7=E3o de l=F3gica bin=E1ria para \b TRUE */ #define TRUE 1 /*! \brief Indicativo de finaliza=E7=E3o do processo \a child */ volatile int STOP=3DFALSE;=20 /*! \brief Usado para convers=E3o \a decimal / \a hexa */ int hex[16] =3D { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', = 'B', 'C', 'D', 'E', 'F' }; /*! \brief Dispositivo serial padr=E3o */ char SerialDevice[20] =3D "/dev/ttyS1"; /*! \brief Comportamento padr=E3o de envio de \a CRC */ char SendCRC =3D FALSE; /*! \brief N=FAmero padr=E3o de caracteres a serem enviados */ int CharsToSend =3D 0; /*! \brief N=FAmero padr=E3o de caracteres a ser recebido antes de operar= um \a EOL */ int CharsToGet =3D 0; /*! \brief Estruturas de configura=E7=E3o da interface \b RS232 */ struct termios oldtio, newtio, oldstdtio, newstdtio; /*! \brief Estrutura de defini=E7=E3o dos sinais do processo \a child */ struct sigaction sa; /*! \brief Buffer com apenas 16 \a bytes de tamanho */ int outbuf[16]; /*! \brief Descritor de arquivo para manipular a interface serial */ int fd; /*! \brief \a Handler para o fim do processo \a child */ void child_handler(int s) { STOP=3DTRUE; } /*! \brief interpretador da linha de comando */ void CommandLineInterpreter(int argc, char *argv[]) { /*! \brief Contador auxiliar */ int i; if ( ( argv[1] =3D=3D "--help" ) || ( argv[1] =3D=3D "-h" ) ) { perror("miniterm [-d ] [-c] [-ns ] [-nr <= count to receive>]"); exit (-1); } else { for (i=3D1;i0) printf ( "Sending %d chars\n", CharsToSend); else puts ( "Sending chars until "); if (CharsToGet>0) printf ( "Receiving %d chars\n\n", CharsToGet); else puts ( "Receiving chars until \n"); /* "puts" already sends a ne= wline, and I want another one */ /* terminal settings done, now handle in/ouput */ switch (fork()) { case 0: /* child */ /* user input */ c1=3Dgetchar(); while ( c1 !=3D ENDMINITERM ) { if ( c1 !=3D ENDMINITERM ) { if ( CharsToSend > 0) { /* hex digits, fixed number of bytes to be sent */ for ( ac =3D 0; ac < (SendCRC?CharsToSend-1:CharsToSend); ac++ ) { /* get hex digits */ write(1,&c1,1); /* stdout */ c2 =3D getchar(); write(1,&c2,1); /* converts two nibble chars to one only byte */ c1=3D ( ( c1 < 0x3a ? c1 & 0x0f : ( c1 & 0x5f ) + 9 - 0x40 ) << 4 ) | ( c2 < 0x3a ? c2 & 0x0f : ( c2 & 0x5f ) + 9 - 0x40 ) ; /* put new byte in buffer */ outbuf[ac] =3D c1; /* separating hex digits on stdout (screen, basically) */ c2 =3D ' '; write(1,&c2,1); /* done with all bytes? */ if (ac !=3D (SendCRC?CharsToSend-2:CharsToSend-1) ) c1 =3D getchar(); } /* send bytes and calculate check summ */ ac =3D 0; for ( c2 =3D 0 ; c2 < (SendCRC?CharsToSend-1:CharsToSend) ; c2++ ) { c1 =3D outbuf[c2]; ac +=3D c1; write(fd,&c1,1); } } else { /* typed chars are the bytes to be sent */ c2 =3D 0; /* done with all bytes? */ while (c1 !=3D NLINE) { /* put new byte in buffer */ outbuf[c2] =3D c1; write(1,&c1,1); /* stdout */ c2++; c1 =3D getchar(); } /* text delimiters to external device (maybe some more command line param= eters here) */ outbuf[c2] =3D CRETURN; c2++; outbuf[c2] =3D NLINE; c2++; outbuf[c2] =3D 0; /* send bytes and calculate check summ */ ac =3D 0; c2 =3D 0; c1 =3D outbuf[c2]; while (c1 !=3D NLINE) { c1 =3D outbuf[c2]; ac +=3D c1; write(fd,&c1,1); c2++; } } /* common part for both ways of typing bytes/chars */ if (SendCRC) { /* separating digits on stdout (screen, basically) */ c2 =3D ' '; /* extra space to checksum byte */ write(1,&c2,1); write(fd,&ac,1); /* serial device */ /* converts one byte to two hex nibbles */ c2 =3D hex[ ( ac & 0xf0 ) >> 4 ]; write(1,&c2,1); c2 =3D hex[ ac & 0x0f ]; write(1,&c2,1); } /* separating (at least trying to) input / output */ c2 =3D ' '; write(1,&c2,1); c2 =3D '-'; write(1,&c2,1); c2 =3D ' '; write(1,&c2,1); /* delay - have to find something better */ for ( c1 =3D 0; c1 <=3D 0x1fff; c1++) for ( c2 =3D 0; c2 <=3D 0x1fff; c2++) ; /* new line on display anyhow, no matter if I get one through the serial = */ c2 =3D NLINE; write(1,&c2,1); c1=3Dgetchar(); } } /* gracefully quit, child part */ tcsetattr(fd,TCSANOW,&oldtio); /* restore old modem setings */ tcsetattr(0,TCSANOW,&oldstdtio); /* restore old tty setings */ close(fd); exit(0); /* will send a SIGCHLD to the parent */ break; case -1: perror("fork"); tcsetattr(fd,TCSANOW,&oldtio); close(fd); exit(-1); default: /* parent */ /* stdin not needed */ close(0); /* handle dying child */ sa.sa_handler =3D child_handler; sa.sa_flags =3D 0; sigaction(SIGCHLD,&sa,NULL); /* serial device input handler */ while (STOP=3D=3DFALSE) { read(fd,&c1,1); /* serial device */ if (STOP=3D=3DFALSE) { if (CharsToGet !=3D 0) { /* hex digits, fixed number of bytes to be received */ /* converts one byte to two hex nibbles */ c2 =3D hex[ ( c1 & 0xf0 ) >> 4 ]; write(1,&c2,1); c2 =3D hex[ c1 & 0x0f ]; write(1,&c2,1); c2 =3D ' '; write(1,&c2,1); /* done with all bytes? */ if ( ++ac =3D=3D CharsToGet) { c2 =3D NLINE; write(1,&c2,1); /* stdout */ ac =3D 0; } } else { /* bytes received are just echoed to stdout */ if ( ( c1 =3D=3D NLINE ) || ( c1 =3D=3D CRETURN) ) c1 =3D ' '; write(1,&c1,1); /* stdout */ } } } /* gracefully quit, parent part */ c2 =3D NLINE; write(1,&c2,1); /* stdout */ close(1); /* wait for child to die or it will become a zombie */ wait(NULL); break; } return (0); } /*! \test * Mitsubishi camera example:=20 *=20 * - program command line: miniterm -d /dev/ttyS1 *=20 * - manual iris adjust RS232 command: "IRM-30" ... "IRM+30" followed= by CR + LF (using as end of input) *=20 * - expected answer: "RE" + CR + LF + "SE0007" + CR + LF *=20 * - screenshot: *=20 * IRM17 - RE *=20 * SE0007 *=20 *=20 * IRM18 - RE *=20 * SE0007 *=20 *=20 * IRM31 - ERR1 *=20 * IRM30 - RE *=20 * SE0007 *=20 *=20 *=20 * Another camera example: *=20 * - program command line: miniterm -d /dev/ttyS1 -ns 6 -nr = 9 -c *=20 * - manual iris adjust RS232 command: c5 aa 7c 00 *=20 * - expected answer: c5 aa 7c 7c XX XX XX= ( XX means don't care ) *=20 * - screenshot: *=20 * c5 aa 7c df 00 CA - C5 AA 7C DF 7C 07 04 56 A7 *=20 * c5 aa 7c ff 00 EA - C5 AA 7C FF 7C 07 04 56 C7 *=20 *=20 * note that when the checksum is in use, it is one of the number * of bytes to be sent specified on the command line parameter. *=20 * crtl-D exits from the program at the beginning of a new command. */ --------------000902080100000806010905--