0

I have difficulties setting the serial port parameters.
Program that works fine on same device, leaves followings stty output:

$ stty -a -F /dev/ttyUSB0  
speed 1200 baud; rows 0; columns 0; line = 0;
intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = <undef>; eol2 = <undef>;     swtch = <undef>; start = ^Q;
stop = ^S; susp = ^Z; rprnt = ^R; werase = ^W; lnext = ^V; flush = ^O; min = 0; time =     0;
-parenb -parodd cs8 -hupcl -cstopb cread clocal -crtscts
ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr -icrnl -ixon -ixoff -iuclc -ixany -imaxbel -iutf8
-opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
-isig -icanon -iexten -echo -echoe -echok -echonl noflsh -xcase -tostop -echoprt -echoctl -echoke

my attempt goes like this:

tcgetattr(fd, &options);

cfsetispeed(&options, B9600);
cfsetospeed(&options, B9600);
options.c_cflag |= (CLOCAL | CREAD);
options.c_cflag &= ~PARENB;
options.c_cflag &= ~CSTOPB;
options.c_cflag &= ~CSIZE;
options.c_cflag |= CS8;
options.c_cflag &= ~( ICANON | ECHO | ECHOE |ISIG );
options.c_iflag &= ~(IXON | IXOFF | IXANY );
options.c_iflag |= IGNBRK;
options.c_oflag |= ONLCR;

options.c_oflag &= ~(OCRNL|ONLRET|NLDLY|CRDLY|TABDLY|BSDLY|VTDLY|FFDLY);

tcsetattr(fd, TCSANOW, &options);

I've tried setting speed both B1200 and B9600 but that didn't work (in manual it says that should be B9600)

What is wrong in this options?

kometonja
  • 437
  • 4
  • 15
  • It's quite unclear in what way it's not working. Please try to clarify. – unwind Jan 22 '13 at 10:39
  • Thanks for replay. After initializing serial port (code posted above) i'm writing some bytes to a device in my test program. Device does not respond properly. So if I comment out posted code, set serial port with stty (with arguments as posted) and then run my program which just writes bytes, device works as expected. – kometonja Jan 22 '13 at 11:08
  • The baudrate should be just an OR value to c_cflag, for your case `options.c_cflag |= CS8 | B9600;`. Can you change the value on commandline like `stty -F /dev/ttyUSB0 9600`? – ott-- Jan 22 '13 at 14:57
  • is OR-ing c_cflag somehow different than setting speed with cfsetispeed? Yes, I can change the value with stty command and it works fine. – kometonja Jan 22 '13 at 15:18
  • Can you omit the cfsetispeed and cfsetospeed and use the `or` with B9600? – ott-- Jan 22 '13 at 16:47
  • ott-- i did what you said but it still doesn't work. after setting `options.c_cflag |= CS8 | B9600`, command `% stty speed -F /dev/ttyUSB0` returns value 150. if I implement cfgetispeed() in program it returns value B300. – kometonja Jan 22 '13 at 18:17
  • Are you trying to set simple raw mode for that tty? – ott-- Jan 22 '13 at 20:13
  • The `stty` settings are for **raw mode**, whereas your `tcgetattr()/tcsetattr()` code uses **canonical mode** for output only and raw mode for input. Try using `cfmakeraw()`. http://stackoverflow.com/questions/12437593/how-to-read-a-binary-data-over-serial-terminal-in-c-program/12457195#12457195 – sawdust Jan 24 '13 at 09:52
  • Yup, I had to set **raw** mode for device! Thanks for useful hints both; if you move comment to answer i'll accept it to mark question as solved – kometonja Jan 24 '13 at 22:45

2 Answers2

2

The stty settings appear to be for raw mode, whereas your tcgetattr()/tcsetattr() code tries to use non-canonical mode but is incomplete for output processing (OPOST is not cleared).
The result is that the serial port is in a half-raw mode for output.

Try using cfmakeraw() to setup non-canonical mode.

cfmakeraw() sets the terminal to something like the "raw" mode of the old Version 7 terminal driver: input is available character by character, echoing is disabled, and all special processing of terminal input and output characters is disabled. The terminal attributes are set as follows:

termios_p->c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP
            | INLCR | IGNCR | ICRNL | IXON);
termios_p->c_oflag &= ~OPOST;
termios_p->c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
termios_p->c_cflag &= ~(CSIZE | PARENB);
termios_p->c_cflag |= CS8;

For working sample code see this.
Note that the return codes from system calls during initialization are checked.

Community
  • 1
  • 1
sawdust
  • 16,103
  • 3
  • 40
  • 50
-2

You should try

B115200
B57600
B38400
B19200
B9600

one by one if you dont know which baudrate to set....

Chirag Desai
  • 1,249
  • 1
  • 10
  • 22
  • thanks for replay. how to you mean it's not a standard baud rate? I've tried only two of them, B9600 because it is mentioned in device documenation and B1200 because stty reports it.. i've also given correct permissions on /dev/ttyUSB0 for regular user. maybe i'm missing something obviously. btw it is not "real" serial port, it's pl2303 usb->serial interface, it that's relevant. – kometonja Jan 22 '13 at 11:26
  • may be its administrator permission issue...?? – Chirag Desai Jan 22 '13 at 11:51
  • `B1200` is a valid symbol for `cfsetospeed()`. At various points in time, 110, 1200 and 9600 baud were the *de facto* "standard" baud rates for RS-232. – sawdust Jan 25 '13 at 21:25