Networking Forums

Networking Forums > Computer Networking > Linux Networking > HELP -- RS-422 serial port programming yields 0x0F char in response??

Reply
Thread Tools Display Modes

HELP -- RS-422 serial port programming yields 0x0F char in response??

 
 
Joshua Colvin
Guest
Posts: n/a

 
      07-31-2003, 07:16 PM
Hello all,
I'm trying to setup a socket connection to a serial port under Linux.
When talking to the device on the other end of the serial port I get
an SI (shift in) character (hex value 0x0f, octal value 017) embedded
in the response. So rather than get "RESPONSE" I get "RESP\017ONSE".
It happens like clockwork, same place, every time. While it COULD be
the device on the other end (it's 3rd party closed source
proprietary),
I seriously doubt it. I'm using cfmakeraw to put the port into raw
mode, and have been playing with the termios settings to no avail.

The closest I could find to the meaning of this character is an
additional character set code and is controlled by IEXTEN or VDISCARD.
However setting or clearing either of these has no effect. Does anyone
have any insight as to what this char is and why I'm seeing it??

I doubt RS-422 has anything to do with this, I'm sure I'm not
configuring the serial port properly. Below is the code. You can see
the various commented-out stuff I've been trying with no luck. Any
help is greatly appreciated. I'm slowly going crazy.

Thanks for any help.
Josh


/************************************************** ****************************
Procedure: OpenSerialPort(...)

Purpose: Attempts to open the serial port passed-in as parameter
'port'

Notes: This might also 'exit' and not just 'return' if we could not
open our
serial device!
************************************************** ****************************/
int OpenSerialPort(comm_data_t* port,
const comm_connection_t* environment,
FILE* logfile)
{
int retval = 0; /* our return value */

port->fd = open(port->dev, O_RDWR | O_NOCTTY | O_NDELAY);
if (port->fd < 0)
{
Logger(logfile, "ERROR -- 2 Could not open our serial device",
MSG_ERROR);
perror(port->dev);
retval = 1;
port->comm_status = COMM_DOWN;
}
else
{
/* we could open our serial port */
Logger(logfile," -- Debug: 2 Successfully opened our serial
device", MSG_ERROR);

/* if we are using an RF95A the RTS line must be disabled (low)
*/
if (environment->RF_MODEM_95A == 1)
{
ioctl(port->fd, TIOCMGET, &port->modem_line);
port->modem_line &= ~TIOCM_RTS;
ioctl(port->fd, TIOCMSET, &port->modem_line);
} /* end if */

tcgetattr(port->fd,&port->ser_oldtio); // save the current modem
setting so we can restore them
tcgetattr(port->fd,&port->ser_newtio); // save the current modem
settings to the new settings structure

cfmakeraw(&port->ser_newtio); // set struct for new term
settings to raw. See man 'cfmakeraw'

port->ser_newtio.c_cflag &= ~CRTSCTS; // make sure rts/cts flow
control is turned off
// port->ser_newtio.c_lflag |= IEXTEN;
// port->ser_newtio.c_cflag |= (CLOCAL | CREAD); // make sure
receiver is enabled and port owner not changed

// port->ser_newtio.c_lflag &= ~(ECHO | ECHONL | ICANON | IEXTEN
| ISIG); /*| ECHOE | NOFLSH | ISTRIP); */
// port->ser_newtio.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | INLCR
| ICRNL | IGNCR | /* INPCK | */ ISTRIP | IXON); /* | IXOFF | IXANY);
*/
// port->ser_newtio.c_lflag &= ~(CSIZE | PARENB);
// port->ser_newtio.c_cflag &= ~(CSIZE | PARENB);
// port->ser_newtio.c_cflag |= CS8;
// port->ser_newtio.c_oflag &= ~OPOST;

port->ser_newtio.c_cc[VMIN] = 1;
port->ser_newtio.c_cc[VTIME] = 0;
//port->ser_newtio.c_cc[VDISCARD] = 0;

cfsetispeed(&port->ser_newtio, port->ser_speed); // set the
input baudrate for new terminal settings
cfsetospeed(&port->ser_newtio, port->ser_speed); // set the
output baudrate for new terminal settings

tcflush(port->fd, TCIOFLUSH); // clear the input and output port
buffers
tcsetattr(port->fd,TCSANOW,&port->ser_newtio); // set the new
attributes for the serial port immediately

tcgetattr(1,&port->ser_old_stdout_tio); // we gotta do this -
there is a Linux bug
tcsetattr(1,TCSANOW,&port->ser_newtio); // make stdout settings
like modem settings
tcgetattr(0,&port->ser_oldstdtio); // get stdin settings for
restoration ...
tcgetattr(0,&port->ser_newstdtio); // ... and use them as a
basis for changes
tcsetattr(0,TCSANOW,&port->ser_newstdtio); // set the new
attributes immediately
tcsetattr(port->fd,TCSANOW,&port->ser_newtio); // set the new
attributes for the serial port immediately
tcsetattr(port->fd,TCSANOW,&port->ser_newstdtio); // set the new
attributes immediately
tcflush(port->fd, TCIOFLUSH); // clear the input and output port
buffers

port->comm_status = COMM_OK; //we really need some error checing
on all of the above calls ...

} /* end else */

if (port->fd < 0)
{
Logger(logfile, "ERROR -- 2b Could not open our serial device",
MSG_ERROR);
perror(port->dev);
exit(-1);
} /* end if port->fd < 0 */


//set the serial port to return immediately after a read
fcntl(port->fd, F_SETFL, FNDELAY);
//fcntl(port->fd, F_SETFL, O_NONBLOCK);

return(retval);

} /* end OpenSerialPort */
 
Reply With Quote
 
 
 
 
Floyd Davidson
Guest
Posts: n/a

 
      07-31-2003, 11:02 PM
(E-Mail Removed) (Joshua Colvin) wrote:
>Hello all,
>I'm trying to setup a socket connection to a serial port under Linux.
>When talking to the device on the other end of the serial port I get
>an SI (shift in) character (hex value 0x0f, octal value 017) embedded
>in the response. So rather than get "RESPONSE" I get "RESP\017ONSE".
>It happens like clockwork, same place, every time. While it COULD be
>the device on the other end (it's 3rd party closed source
>proprietary),


I would almost bet money that it is being inserted by the device
at the other end. I know of nothing else that would cause
that to happen on a repeatable basis in the middle of a word.

>I seriously doubt it. I'm using cfmakeraw to put the port into raw
>mode, and have been playing with the termios settings to no avail.
>
>The closest I could find to the meaning of this character is an
>additional character set code and is controlled by IEXTEN or VDISCARD.
>However setting or clearing either of these has no effect. Does anyone
>have any insight as to what this char is and why I'm seeing it??


SI and SO are control characters used to switch a terminal to an
alternate font and back. Commonly the alternate font will be
block graphics, for example.

man console_codes

>I doubt RS-422 has anything to do with this, I'm sure I'm not
>configuring the serial port properly. Below is the code. You can see
>the various commented-out stuff I've been trying with no luck. Any
>help is greatly appreciated. I'm slowly going crazy.
>
>Thanks for any help.
>Josh


Your posting software line wrapped the code. I've undone everything
I noticed, though it will once again be wrapped by many readers, but
at least it won't get a double dose of the uglies from it. The only
solution for this is to reformat code before you post, and try very
hard to keep lines at less than about 60 columns. That allows it to
be quoted a couple times before it wraps and gets the uglies again.

>/************************************************** ****************************
> Procedure: OpenSerialPort(...)
>
> Purpose: Attempts to open the serial port passed-in as parameter 'port'
>
> Notes: This might also 'exit' and not just 'return' if we could not open our
> serial device!
>************************************************* *****************************/
>int OpenSerialPort(comm_data_t* port,
> const comm_connection_t* environment,
> FILE* logfile)
>{
> int retval = 0; /* our return value */
>
> port->fd = open(port->dev, O_RDWR | O_NOCTTY | O_NDELAY);
> if (port->fd < 0)
> {
> Logger(logfile, "ERROR -- 2 Could not open our serial device", MSG_ERROR);
> perror(port->dev);
> retval = 1;
> port->comm_status = COMM_DOWN;


This code would be a lot clearer if you put the exit here and
skipped the else part of this construct.

if (port->fd < 0)
{
...
exit(1);
}

...


> }
> else
> {
> /* we could open our serial port */
> Logger(logfile," -- Debug: 2 Successfully opened our serial device", MSG_ERROR);
>
> /* if we are using an RF95A the RTS line must be disabled (low) */
> if (environment->RF_MODEM_95A == 1)
> {
> ioctl(port->fd, TIOCMGET, &port->modem_line);
> port->modem_line &= ~TIOCM_RTS;
> ioctl(port->fd, TIOCMSET, &port->modem_line);
> } /* end if */


I'm not sure the above is doing you much good in that position.
You first want to turn off the modem controls and then make sure
RTS is off. Hence, I'd move this to the end of the
configuration.

> tcgetattr(port->fd,&port->ser_oldtio); // save the current modem setting so we can restore them
> tcgetattr(port->fd,&port->ser_newtio); // save the current modem settings to the new settings structure
>


That one is going to byte you badd, sooner or later. You are
assuming that, except for the specific options you are changing
below, the serial port is currently configured correctly. Since
you are _not_ setting every possible option that could affect
how it will work, it is very possible that eventually you'll run
this program after some other program has configured the serial
port, and it won't work.

The classic example is that pppd sets the line discipline to
other than 0, and if it crashes or is killed with SIGKILL, it
does not restore it. Your configuration does not reset that.

Rather than copy the existing configuration to the new struct,
it is far better to just clear the new struct and start from
scratch.

#include <string.h>
memset(&port->ser_newtio, 0, sizeof *port->ser_newtio)

You can then eliminate some of the below code, such as the first
line that clears CRTSCTS, because it is already cleared.

> cfmakeraw(&port->ser_newtio); // set struct for new term settings to raw. See man 'cfmakeraw'
> port->ser_newtio.c_cflag &= ~CRTSCTS; // make sure rts/cts flow control is turned off
>// port->ser_newtio.c_lflag |= IEXTEN;
>// port->ser_newtio.c_cflag |= (CLOCAL | CREAD); // make sure receiver is enabled and port owner not changed


That one is commented out, but with the above you will
definitely need to put it back in! At least the CREAD enabled
part. CLOCAL depends on what you are doing.

>// port->ser_newtio.c_lflag &= ~(ECHO | ECHONL | ICANON | IEXTEN | ISIG); /*| ECHOE | NOFLSH | ISTRIP); */
>// port->ser_newtio.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | INLCR | ICRNL | IGNCR | /* INPCK | */ ISTRIP | IXON); /* | IXOFF | IXANY); */
>// port->ser_newtio.c_lflag &= ~(CSIZE | PARENB);
>// port->ser_newtio.c_cflag &= ~(CSIZE | PARENB);
>// port->ser_newtio.c_cflag |= CS8;


Put that one back in too.

>// port->ser_newtio.c_oflag &= ~OPOST;
>
> port->ser_newtio.c_cc[VMIN] = 1;
> port->ser_newtio.c_cc[VTIME] = 0;
> //port->ser_newtio.c_cc[VDISCARD] = 0;
>
> cfsetispeed(&port->ser_newtio, port->ser_speed); // set the input baudrate for new terminal settings
> cfsetospeed(&port->ser_newtio, port->ser_speed); // set the output baudrate for new terminal settings
>
> tcflush(port->fd, TCIOFLUSH); // clear the input and output port buffers
> tcsetattr(port->fd,TCSANOW,&port->ser_newtio); // set the new attributes for the serial port immediately
>
> tcgetattr(1,&port->ser_old_stdout_tio); // we gotta do this - there is a Linux bug


What "bug" is that?

> tcsetattr(1,TCSANOW,&port->ser_newtio); // make stdout settings like modem settings
> tcgetattr(0,&port->ser_oldstdtio); // get stdin settings for restoration ...
> tcgetattr(0,&port->ser_newstdtio); // ... and use them as a basis for changes


> tcsetattr(0,TCSANOW,&port->ser_newstdtio); // set the new attributes immediately
> tcsetattr(port->fd,TCSANOW,&port->ser_newtio); // set the new attributes for the serial port immediately
> tcsetattr(port->fd,TCSANOW,&port->ser_newstdtio); // set the new attributes immediately


This got too convoluted to follow!

You have, in order:

1. configured the serial port (ser_newtio)
2. saved stdout's config (ser_old_stdout_tio)
3. config'd stdout using the serial port config (ser_newtio)
4. saved stdin's config (ser_oldstdtio)
5. saved stdin's config (ser_newstdtio)
6. config'd stdin with stdin's config (ser_newstdtio)
7. config'd the serial port, again (ser_newtio)
8. config'd the serial port using stdin's config (ser_newstdtio)

Item 1, you want to keep. I can't believe that any of the rest
of that is useful. In particular, it does no good to set up a
configuration for the serial port, use it for the stdout, while
writing it twice to the serial port and then finally overwriting
it using the stdin config!

(Damned those all night programming sessions! :-)

> tcflush(port->fd, TCIOFLUSH); // clear the input and output port buffers
>
> port->comm_status = COMM_OK; //we really need some error checing on all of the above calls ...


There is *never* any point in writing a comment that you need to
add error checking. Don't waste time with the comment, *add* *the*
*error* *checking*.

You have no idea what happened there, because if any single part
of that has a typo that resulted in a failed function call, the
rest of it is useless.

>
> } /* end else */
>
> if (port->fd < 0)
> {
> Logger(logfile, "ERROR -- 2b Could not open our serial device", MSG_ERROR);
> perror(port->dev);
> exit(-1);
> } /* end if port->fd < 0 */


That should have all been placed up above where the port was
opened, IMHO.

>
> //set the serial port to return immediately after a read
> fcntl(port->fd, F_SETFL, FNDELAY);
> //fcntl(port->fd, F_SETFL, O_NONBLOCK);


I like to separate the open function from the configuration
function, so I'll just copy my entire open function here
for you, just to show a different way of doing the above.

int
open_serial_port(char *port)
{
int fd, oldflags;

/* O_NDELAY allows open w/o carrier detect */
if (-1 != (fd = open(port, O_RDWR | O_NDELAY))) {
/* clear O_NDELAY to allow read() to block */
if ((-1 != (oldflags = fcntl(fd, F_GETFL, 0))) &&
(-1 != fcntl(fd, F_SETFL, oldflags & ~O_NDELAY))) {
/* flush input and output */
if (0 == tcflush(fd, TCIOFLUSH)) {
return fd;
}
}
}
return -1;
}


> return(retval);
>
>} /* end OpenSerialPort */


--
Floyd L. Davidson <http://web.newsguy.com/floyd_davidson>
Ukpeagvik (Barrow, Alaska) (E-Mail Removed)
 
Reply With Quote
 
/dev/rob0
Guest
Posts: n/a

 
      08-01-2003, 03:10 AM
In article <(E-Mail Removed)>, Floyd Davidson wrote:
> (Damned those all night programming sessions! :-)


I guess so ... for you, "all night" is what, six months long?

So are you enjoying the sunshine now?
--
/dev/rob0 - preferred_email=i$((28*28+28))@softhome.net
or put "not-spam" or "/dev/rob0" in Subject header to reply
 
Reply With Quote
 
Floyd Davidson
Guest
Posts: n/a

 
      08-01-2003, 07:00 AM
/dev/rob0 <(E-Mail Removed)> wrote:
>In article <(E-Mail Removed)>, Floyd Davidson wrote:
>> (Damned those all night programming sessions! :-)

>
>I guess so ... for you, "all night" is what, six months long?


Well, the sun goes down on November 18, and comes back up
January 23. But we do get some twilight hours even on
December 21st. (Maybe 3 of them!) It would be possible to
drive with no lights on, but that is _not_ recommended.

Barrow is big on Christmas light displays, because we don't have
to wait until evening to drive around and look at them. If we
aren't out before 12:00 or so, we just wait until 2:30, by which
time it is pitch black again. (Actual "noon" comes at about
1:12 PM here.)

So if "all night" is from when it gets dark to when it gets
light, that can be as long as 21 hours here. That's enough to
give anybody a caffeine fit!

>So are you enjoying the sunshine now?


Sunshine is another thing. (And I'm a night person, so you can
imagine the trouble this can be.) At the spring and fall
equinox, everyone including us is getting exactly 12 hours of
direct sunshine a day. But here, by May 13th the sun no longer
sets. Of course, by that time it has been weeks since it got
actually dark. And then on August 1st the sun sets again, but
it is a few weeks again before it goes far enough down to get
dark. So figure from the middle of April until the end of
August, it is _never_ dark. Thats some 5 1/2 months straight.

It sounds weird to people who are used to things like the sun
coming up in the east and setting in the west, or who expect to
see the sun directly overhead at noon. Or most of all for
someone who wants to go to bed when the sun goes down. But
those are just thing you only expect if you live where that
happens. Not having that is hardly missed, given the variety of
much more interesting phenomenon that we do have.

--
Floyd L. Davidson <http://web.newsguy.com/floyd_davidson>
Ukpeagvik (Barrow, Alaska) (E-Mail Removed)
 
Reply With Quote
 
James Knott
Guest
Posts: n/a

 
      08-01-2003, 10:40 AM
Joshua Colvin wrote:

> I'm trying to setup a socket connection to a serial port under Linux.
> When talking to the device on the other end of the serial port I get
> an SI (shift in) character (hex value 0x0f, octal value 017) embedded
> in the response. So rather than get "RESPONSE" I get "RESP\017ONSE".
> It happens like clockwork, same place, every time. While it COULD be
> the device on the other end (it's 3rd party closed source
> proprietary),
> I seriously doubt it.


Try monitoring the line, to see if the same thing appears there.

Incidentally, from a software perspective, EIA422 (RS422) is exactly the
same as EIA232. The difference is in the connection (balanced vs
unbalanced).

--

Fundamentalism is fundamentally wrong.

To reply to this message, replace everything to the left of "@" with
james.knott.
 
Reply With Quote
 
 
 
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
no serial port and no parrallel port how do i console to a router sloan949@gmail.com Linux Networking 4 02-13-2007 07:02 PM
Map serial port through TS Tippy Windows Networking 0 11-23-2005 12:06 AM
Parallel port programming Md.Zaheeruddin Khan Linux Networking 0 10-07-2004 01:35 PM
Serial Port Multiplexing (2 apps to 1 port) Onslo Linux Networking 0 10-06-2004 08:53 AM
programming serial port Carmin Linux Networking 11 11-20-2003 01:32 AM



1 2 3 4 5 6 7 8 9 10 11