Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 6 Sep 2006 18:13:36 -0600
From:      "Andrew Falanga" <af300wsm@gmail.com>
To:        "=?KOI8-R?B?88XSx8XKIPPPwsvP?=" <bug2bug@bug2bug.tk>,  freebsd-questions <freebsd-questions@freebsd.org>
Subject:   Re: A question about programming RS-232
Message-ID:  <340a29540609061713m78f85d8bu549e84c6fecb37a9@mail.gmail.com>
In-Reply-To: <200609042233.24740.bug2bug@bug2bug.tk>
References:  <200609042233.24740.bug2bug@bug2bug.tk>

next in thread | previous in thread | raw e-mail | index | archive | help
I am by no means the worlds best serial programmer, but recently I have done
some work on this subject and I noticed one thing in the code sample above
that should be avoided.  However, I'll give you what I saw in-line:


#include <stdio.h>
> #include <termios.h>
> #include <unistd.h>
> #include <fcntl.h>
>
> int main(void) {
> int t = 0, num = 10, fd, iOut; char *ch;
> struct termios my_termios;
> ch = (char *)malloc(6);
> memset(ch, 250, 6);
> fd = open("/dev/cuad0", O_RDWR | O_NONBLOCK);


Ok, great, we've opened our serial device.  Unless you need this to be a
controlling terminal, you should open with open( "/dev/cuad0", O_RDWR |
O_NONBLOCK | O_NOCTTY );  Check with the open man page to make sure I've
given you the correct constant for opening as a non-controlling terminal.


printf("Opened com port\n");
> if(fd < 0) return 0;
> // tcflush(fd, TCIFLUSH);
> my_termios.c_cflag = CS8 | CLOCAL;
> if(cfsetspeed(&my_termios, B9600) < 0) return 0;
> if(tcsetattr(fd, TCSANOW, &my_termios) < 0) return 0;


You've set the attributes you want to use in the structure you defined,
my_termios.  However, you should call tcgetattr() before changing what you
want to change (and make sure you always turn things on as you have done
above with bitwise or).  So, your code should look something like,

// assume an open file descriptor named fd
struct termios my_termios;

if( tcgetattr( fd, &my_termios ) < 0 ) {
   fprintf( stderr, "error in getting termios properties\n" );
   return AN_ERROR;
}

// turn on what you want
my_termios.c_cflag = CS8 | CLOCAL;

if( tcsetattr( fd, &my_termios ) < 0 } {
   fprintf( stderr, "error in setting new properties to serial port\n" );
   return AN_ERROR;
}


I don't know if this will solve your problems but I do know I read that you
should always get the current settings because the serial driver may use
certain bits and you don't want to turn them off.  Also, if you're going to
return the port settings to the state before you took hold of it, make two
termios structures and stuff the original settings away to be restored upon
exit or close of the port.

Lastly, here is a link to a serial programming guide that I found quite
helpful.  The info is probably dated to some degree, but it is non the less
useful.

http://www.easysw.com/~mike/serial/serial.html

Andy



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?340a29540609061713m78f85d8bu549e84c6fecb37a9>