This is a discussion on RS232 programming, helps needed... within the HP-UX Operating System forums, part of the Unix Operating Systems category; --> linda <plinda77@yahoo.com> wrote: > Hi All > I am doing a project recently requires RS232 communication between a > ...
| |||||||
| Register | FAQ | Members List | Calendar | Search | Today's Posts | Mark Forums Read |
| ||||
| linda <plinda77@yahoo.com> wrote: > Hi All > I am doing a project recently requires RS232 communication between a > hpux workstation and a robot. This machine has its own RS232 > communication protocol which can accept commands and return result > from queries. The RS232 connection requirement is very simple. > the workstation the machine > 9 pins connector 25 pins connector > Pin 2(Rx) connected to Pin 2(Tx) > Pin 3(Tx) connected to Pin 3(Rx) > Pin 5(Gnd) connected to Pin 7(Gnd) > Ive wrote a C code to control the machine. Apparently, the machine is > accepting the commands from the C program and performed its tasks, but > wouldnt response to the queries that Ive sent from the program. > Therefore Ive probe(pin2 - Tx) from the 25 pins Dsub connector and > found that the machine is actually returning the expected result but > the serial port is not set to read the result. The read result return > -1. > I am not a RS232 programmer and this is the first time I am doing so. > But I think it must something to do with the RS232 options that I > should set in my hpux box. > All kinds of RS232 related helps are appreciated. Thanks in advance. > ~ For a direct connection, i.e. no flow control, you should be using the device file that has 00 as the last 2 digits of the minor device number. As in: crw--w--w- 1 bin bin 78 0x023800 Sep 23 07:11 tty2d9 ^^ These digits. The termio man page should explain these bits. -- Jim Pennino Remove -spam-sux to reply. |
| |||
| On 23 Sep 2004 09:22:39 -0700 plinda77@yahoo.com (linda) wrote: > #define ENQ 5 > #define ACK 6 > #define NAK 15 > #define STX 2 > #define ETX 3 > > #define QUERY "XX" /* XX, something to represent an query, say 2 > bytes */ > > int main() > { > int fd; > int io_status; > int write_status; > int close_status; > struct termio t; Don't use termio, it has been superseded by termios. > char *device = "/dev/devicefile"; > char query[10]; > char recvbuf[10]; > > sprintf(query, "%c%s%c\n", STX, QUERY, ETX); Always use snprintf, it avoids buffer overflows. > /* need to encapsulate QUERY between the STX and ETX, to be recognize > by the robot */ > > if((fd = open(device, O_RDWR | O_NOCTTY | O_NDELAY))==-1) > fprintf(stderr, "Open RS232 Fail%d!\n", fd); > > if((io_status = ioctl(fd, TCGETA, &t))==-1) > fprintf(stderr, "IOCTL TCGETA Fail!\n"); Use tcgetattr() and tcsetattr(). > > t.c_cflag=B9600|CS8|HUPCL|CREAD; > > if((io_status = ioctl(fd, TCSETA, &t))==-1) > fprintf(stderr, "IOCTL TCSETA Fail!%d\n", io_status); You could try to print errno (it's helpful :-). > if((write_status = write(fd, &query, 5))==-1) > fprintf(stderr, "Write RS232 Fail!%d\n", write_status); You should output the bytes in a loop, and check for the number of bytes written. > /* let say the query returns 2 bytes, YY */ > /* actual data return from robot and received will be "2YY3" but ascii > character 2 and 3 is not printable(is this the problem?) therefore it > will be YY, as STX, "YY", ETX */ > > if((read_status = read(fd, &recvbuf, 5))==-1) > fprintf(stderr, "read RS232 Fail!%d\n", read_status); This is not the way to go about it. You should switch to raw mode, and read character by character. Once you've got your tty in raw mode, with the proper number of characters and timer set, you can start reading the characters. You'll need to know the robot's protocol to make reasonable vmin/vtime settings. > /* read_status received but is 0*/ > > close(fd); > > } > /* End of code */ > > Is there any settings that are capable of filter away the STX and ETX > during read? or it that needed? Here's something I hacked up. Warning: it's not tested as I don't currently have a serial device to hang off a HP-UX serial port. It should more or less work - I hope (famous last words). #include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <errno.h> #include <strings.h> #include <termios.h> #include <sys/fcntl.h> #define ENQ 5 #define ACK 6 #define NAK 15 #define STX 2 #define ETX 3 #define QUERY "XX" /* XX, something to represent an query, say 2 bytes */ /* Prototypes */ void fatal(char *); int tty_raw(int, int, int); char *device = "/dev/tty0p0"; int main(int argc, char *argv[]) { int bcount; /* byte counter */ int osize; /* output size */ int fd; char query[10]; char recvbuf[10]; switch (argc) { case 0: case 1: break; case 2: device = argv[1]; break; default: fprintf(stderr, "Format: %s: { tty-device (default: %s) }\n", argv[0], device); exit(1); break; } /* Open the tty and put in raw mode */ if((fd = open(device, O_RDWR | O_NOCTTY))==-1) { fatal("Open RS232 Failed"); } if (!isatty(fd)) { fatal("Not a tty"); } if (tty_raw(fd, 0, 10) < 0) { /* one character, 10 secs timeout */ fatal("Cannot set to raw mode"); } /* Prepare the output query */ osize = snprintf(query, sizeof(query), "%c%s%c\n", STX, QUERY, ETX); /* Send the message down the tty */ bcount = 0; while (bcount < osize) { int w; if ((w = write(fd, &query[bcount], osize-bcount)) == EOF) { break; } if (w == -1 && errno == EAGAIN) { continue; /* no data available in non-blocking mode */ } bcount += w; } /* Read the reply from the robot */ bcount = 0; while (bcount < sizeof(recvbuf)) { /* Stop buffer overflow */ int r; if ((r = read(fd, &recvbuf[bcount], 1)) == 0) { fatal("Robot closed connection"); } if (r == -1 && errno == EAGAIN) { continue; /* no data available in non-blocking mode */ } if (bcount == 0 && recvbuf[bcount] != STX) { fatal("Robot lost its mind"); } if (recvbuf[bcount] == ETX) { break; } bcount += r; } /* Do something with the reply */ recvbuf[bcount] = '\0'; /* Make it printable */ /* skip STX */ fprintf(stdout, "Reply from robot was: <%s>\n", recvbuf+1); exit(0); } /* Switch terminal to raw mode */ int tty_raw(int tty_fd, int vmin, int vtime) { struct termios cooked; struct termios raw; /* Keep a copy so we can go back in case of error */ tcgetattr(tty_fd, &cooked); tcgetattr(tty_fd, &raw); /* Set flags */ raw.c_lflag = 0; /* local flags */ /* Alternatively, remove the following flags: raw.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG); */ raw.c_iflag = 0; /* input flags */ /* Alternatively, remove the following flags: raw.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON); */ raw.c_oflag = 0; /* output flags */ /* Alternatively, remove the following flag: raw.c_oflag &= ~(OPOST); */ raw.c_cflag |= (B9600|CS8); /* control flags - make sure we get 8bits */ /* control characters: remove special treatments */ raw.c_cc[VINTR] = '\0'; raw.c_cc[VQUIT] = '\0'; raw.c_cc[VERASE] = '\0'; raw.c_cc[VKILL] = '\0'; raw.c_cc[VSTART] = '\0'; raw.c_cc[VSTOP] = '\0'; /* control characters: minimum number of bytes, timer before return*/ /* eg vmin = 5, vtime = 5 means return after 5 bytes or half a second after the first byte */ raw.c_cc[VMIN] = vmin; raw.c_cc[VTIME]= vtime; /* Now put the tty in raw mode after flushing */ if (tcsetattr(tty_fd, TCSAFLUSH, &raw) < 0) { tcsetattr(tty_fd, TCSAFLUSH, &cooked); return -1; } return 0; } /* Get out on fatal errors */ void fatal(char *message) { if (errno) { fprintf(stderr, "%s: %s\n", message, strerror(errno)); } else { fprintf(stderr, "%s\n", message); } exit (1); } It compiles OK with gcc -Wall on HP-UX 11.0, the rest is up to you (watch out for possible broken lines when copy/pasting the code). Take care, -- Stefaan -- "What is stated clearly conceives easily." -- Inspired sales droid |
| |||
| jimp@specsol-spam-sux.com wrote: |For a direct connection, i.e. no flow control, you should be using the |device file that has 00 as the last 2 digits of the minor device number. |As in: |crw--w--w- 1 bin bin 78 0x023800 Sep 23 07:11 tty2d9 | ^^ These digits. |The termio man page should explain these bits. The device file minor number bits can be decoded and set with the lssf and mksf commands. Look at the "man lssf" and "man mksf" manuals. You want the asio0 section of "man mksf" for workstation serial ports. -- Mike Stroyan, mike.stroyan@hp.com |
| |||
| On 24 Sep 2004 08:32:42 -0700 plinda77@yahoo.com (linda) wrote: > thanks a lot You're welcome. Please be aware I just threw it together and didn't have the possibility to test it. My last work on asynchronous communications in Unix was way back in 1990, plus I tend to make off-by-one errors in my loops. The basic ideas should be sound though. Please let me know if it helped. Take care, -- Stefaan -- "What is stated clearly conceives easily." -- Inspired sales droid |
| ||||
| linda wrote: > Hi All > > I am doing a project recently requires RS232 communication between a > hpux workstation and a robot. This machine has its own RS232 > communication protocol which can accept commands and return result > from queries. The RS232 connection requirement is very simple. > > the workstation the machine > 9 pins connector 25 pins connector > > Pin 2(Rx) connected to Pin 2(Tx) > Pin 3(Tx) connected to Pin 3(Rx) > Pin 5(Gnd) connected to Pin 7(Gnd) > > Ive wrote a C code to control the machine. Apparently, the machine is > accepting the commands from the C program and performed its tasks, but > wouldnt response to the queries that Ive sent from the program. > Therefore Ive probe(pin2 - Tx) from the 25 pins Dsub connector and > found that the machine is actually returning the expected result but > the serial port is not set to read the result. The read result return > -1. > > I am not a RS232 programmer and this is the first time I am doing so. > But I think it must something to do with the RS232 options that I > should set in my hpux box. > All kinds of RS232 related helps are appreciated. Thanks in advance. > ~ Most problems I see with new RS232 setups are that most unix implementations give a login-session (getty or such) on each found serial port. If you use the serial port for other purposses than a terminal-login be sure to disable this login. See your inittab file ("/etc/inittab" ?) for your situation. CBee |