This is a multi-part message in MIME format. --------------080607000900010509020304 Content-Type: text/plain; charset=us-ascii; format=flowed Content-Transfer-Encoding: 7bit Hello, I do this all the time, I have a program "fiddle" (see attached) that does serial i/o in linux, basically a "hyperterminal" (minus the VT100 emulation) but that can be controlled on the linux side as well, so that it can dump files or validate serial coming in etc. etc. as needed by the project. Basically, if you type nothing, whatever comes in the serial port is displayed. If you start typing, if you type a key that matches a command it implements, it runs (whatever). Otherwise it is sent down the serial line. Pretty handy, really, and I've used it in a variety of forms for a number of projects. Feel free to email me any questions about it... Best Jesse 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 > > -- "There are 10 kinds of people in the world; those who understand binary and those who don't." -- http://www.piclist.com hint: PICList Posts must start with ONE topic: [PIC]:,[SX]:,[AVR]: ->uP ONLY! [EE]:,[OT]: ->Other [BUY]:,[AD]: ->Ads --------------080607000900010509020304 Content-Type: text/plain; name="fiddle.cpp" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="fiddle.cpp" /****************************************************************** ** File: fiddle.cpp ** ** Copyright (C) 2002 Jesse Lackey ** All rights reserved. **************************************************************************** ** 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 at www.gnu.org **************************************************************************** */ #include #include #include #include #include #include #include #include #include #include #include #include #define MAX_DEVICE_NAME 20 /* maximum length of the name of the /dev comm port driver */ typedef enum { S_TIMEOUT, /* timeout */ S_DTE, /* incoming data coming from kbd */ S_DCE, /* incoming data from serial port */ S_MAX /* not used - just for checking */ } S_ORIGINATOR; void cleanup_termios(int signal); void init_stdin(struct termios *sts); void init_comm(struct termios *pts); char device[MAX_DEVICE_NAME]; /* serial device name */ int pf = 0; /* serial port file descriptor */ struct termios pots; /* old port termios settings to restore */ struct termios sots; /* old stdout/in termios settings to restore */ // beginning linux programming p187 struct termios sts; /* termios settings on stdout/in */ static int peek_character= -1; int readch(); int kbhit(); bool check_serial_in( int uSecWait, bool doPrintChar ); void init_comm(struct termios *pts) { cfmakeraw(pts); /* // some things we want to set arbitrarily pts->c_lflag &= ~ICANON; pts->c_lflag &= ~(ECHO | ECHOCTL | ECHONL); pts->c_cflag |= HUPCL; pts->c_cc[VMIN] = 1; pts->c_cc[VTIME] = 0; // no CR/LF mapping pts->c_oflag &= ~ONLCR; pts->c_oflag &= ~OCRNL; pts->c_iflag &= ~ICRNL; pts->c_iflag &= IGNPAR; //jsl // no flow control pts->c_cflag &= ~CRTSCTS; pts->c_iflag &= ~(IXON | IXOFF | IXANY); */ //cfsetospeed(pts, B38400); //cfsetispeed(pts, B38400); cfsetospeed(pts, B9600); cfsetispeed(pts, B9600); } void init_stdin(struct termios *sts) { /* again, some arbitrary things */ /* sts->c_iflag &= ~BRKINT; sts->c_iflag |= IGNBRK; sts->c_lflag &= ~ISIG; sts->c_cc[VMIN] = 1; sts->c_cc[VTIME] = 0; sts->c_lflag &= ~ICANON; */ /* no local echo: allow the other end to do the echoing */ //sts->c_lflag &= ~(ECHO | ECHOCTL | ECHONL); // beginning linux programming p187 sts->c_cc[VMIN] = 1; sts->c_cc[VTIME] = 0; sts->c_lflag &= ~ICANON; // sts->c_lflag &= ~ECHO; // sts->c_lflag &= ~ISIG; } /******************************************************************** Main functions ******************************************************************** static void cleanup_termios(int signal) signal handler to restore terminal set befor exit int main(int argc, char *argv[]) - main program function ********************************************************************/ /* restore original terminal settings on exit */ void cleanup_termios(int signal) { tcsetattr(pf, TCSANOW, &pots); tcsetattr(STDIN_FILENO, TCSANOW, &sots); exit(0); } void main_usage(int exitcode, char *str, char *dev) { fprintf(stderr, "Usage: fiddle\n"); fprintf(stderr, "Exitcode %d - %s %s \n\n", exitcode, str, dev); exit(exitcode); } typedef unsigned char byte; void do_flush_serial_in() { byte buf[1]; int count=0; printf("Flushing..."); fflush(NULL); fd_set ready; do { FD_ZERO(&ready); FD_SET(pf, &ready); struct timeval tv; tv.tv_sec= 1; tv.tv_usec= 0; select(pf+1, &ready, NULL, NULL, &tv); if (FD_ISSET(pf, &ready)) { int i= read(pf, buf, 1); if (i==1) { count++; printf("0x%02x ('%c') ", ((unsigned int)buf[0]) & 0xFF, isprint( (char)(buf[0]) ) ? (char)(buf[0]) : '.'); } else break; } else { break; } } while (1); printf("done. Flushed %d chars\n",count); } int main(int argc, char *argv[]) { struct termios pts; /* termios settings on port */ struct sigaction sact;/* used to initialize the signal handler */ device[0] = '\0'; sprintf(device,"/dev/ttyS0"); /* open the device */ pf = open(device, O_RDWR); if (pf < 0) main_usage(2, "cannot open device", device); /* modify the port configuration */ tcgetattr(pf, &pts); memcpy(&pots, &pts, sizeof(pots)); init_comm(&pts); tcsetattr(pf, TCSANOW, &pts); /* Now deal with the local terminal side */ tcgetattr(STDIN_FILENO, &sts); memcpy(&sots, &sts, sizeof(sots)); /* to be used upon exit */ init_stdin(&sts); tcsetattr(STDIN_FILENO, TCSANOW, &sts); /* set the signal handler to restore the old * termios handler */ sact.sa_handler = cleanup_termios; sigaction(SIGHUP, &sact, NULL); sigaction(SIGINT, &sact, NULL); sigaction(SIGPIPE, &sact, NULL); sigaction(SIGTERM, &sact, NULL); printf("\n\n----\nLocal commands: ~ (for help),H,F,C,ctrl-c\n----\n"); fflush(NULL); /* run the main program loop */ bool doexit= false; while(!doexit) { while (!kbhit()) { check_serial_in( 30 * 1000, true ); // 30millisec wait } if (kbhit()) { // printf("\n"); char ch= readch(); switch (ch) { // flush case 'F': { do_flush_serial_in(); } break; /* // hit return ... do nothing, just loop and we'll print the // one-line command summary again case '\n': { } break; */ case 0x03: // ctrl-c { doexit= true; break; } case '~': { printf("~= show this help\n"); printf("?= show help in universalboard\n"); printf("F= flush serial in\n"); printf("ctrl-c= exit\n"); printf("all others-> passed to board\n"); fflush(NULL); } break; default: { // pass it to serial board write (pf, &ch, 1); tcdrain(pf); } break; } } } printf("\n"); fflush(NULL); /* restore original terminal settings and exit */ tcsetattr(pf, TCSANOW, &pots); tcsetattr(STDIN_FILENO, TCSANOW, &sots); exit(0); } // return true if there is a char waiting - which only happens if // doPrintChar is false AND there is a char waiting bool check_serial_in( int uSecWait, bool doPrintChar ) { byte buf2; int i; fd_set ready; FD_ZERO(&ready); FD_SET(pf, &ready); struct timeval tv; tv.tv_sec= 0; //tv.tv_usec= 30 * 1000; // 30millisec tv.tv_usec= uSecWait; select(pf+1, &ready, NULL, NULL, &tv); if (FD_ISSET(pf, &ready)) { if (doPrintChar) { i= read(pf, &buf2, 1); if (i!=1) printf("err in check_serial_in() - got %d chars, expect 1\n",i); else { printf("%c", buf2); } } else { return true; } } else { fflush(NULL); } return false; } // beginning linux programming p187 int kbhit() { char ch; int nread; if (peek_character != -1) return 1; sts.c_cc[VMIN]= 0; tcsetattr(0, TCSANOW, &sts); nread = read(0,&ch,1); sts.c_cc[VMIN]=1; tcsetattr(0, TCSANOW, &sts); if (nread==1) { peek_character= ch; return 1; } return 0; } int readch() { char ch; if (peek_character != -1) { ch= peek_character; peek_character= -1; return ch; } read(0,&ch,1); return ch; } -- http://www.piclist.com hint: PICList Posts must start with ONE topic: [PIC]:,[SX]:,[AVR]: ->uP ONLY! [EE]:,[OT]: ->Other [BUY]:,[AD]: ->Ads --------------080607000900010509020304--