0

I am trying to listen to a serial port with a C program utilizing CRTSCTS (to prevent an independently powered Arduino from rebooting after the computer it is connected to restarts).

I started with the code from here: Canonical Mode Linux Serial Port

After some adaptations it looks like this:

#define SERIALTERMINAL      "/dev/ttyUSB0"
#include <errno.h>
#include <fcntl.h> 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>

int set_interface_attribs(int fd, int speed)
{
    struct termios tty;

    if (tcgetattr(fd, &tty) < 0) {
        printf("Error from tcgetattr: %s\n", strerror(errno));
        return -1;
    }

    cfsetospeed(&tty, (speed_t)speed);
    cfsetispeed(&tty, (speed_t)speed);

    tty.c_cflag |= CLOCAL | CREAD;
    tty.c_cflag &= ~CSIZE;
    tty.c_cflag |= CS8;         /* 8-bit characters */
    tty.c_cflag &= ~PARENB;     /* no parity bit */
    tty.c_cflag &= ~CSTOPB;     /* only need 1 stop bit */
    //tty.c_cflag &= ~CRTSCTS;
    tty.c_cflag |= ~CRTSCTS;    //trying to turn on CRTSCTS


    tty.c_cflag &= ~HUPCL; //trying turning off HUPCL - it works!

    tty.c_lflag |= ICANON | ISIG;  /* canonical input */
    tty.c_lflag &= ~(ECHO | ECHOE | ECHONL | IEXTEN);

    tty.c_iflag &= ~IGNCR;  /* preserve carriage return */
    tty.c_iflag &= ~INPCK;
    tty.c_iflag &= ~(INLCR | ICRNL | IUCLC | IMAXBEL);
    tty.c_iflag &= ~(IXON | IXOFF | IXANY);   /* no SW flowcontrol */
    //tty.c_iflag |= ~IXON; //try ixon

    tty.c_oflag &= ~OPOST;

    tty.c_cc[VEOL] = 0;
    tty.c_cc[VEOL2] = 0;
    tty.c_cc[VEOF] = 0x04;

    if (tcsetattr(fd, TCSANOW, &tty) != 0) {
        printf("Error from tcsetattr: %s\n", strerror(errno));
        return -1;
    }
    return 0;
}


int main()
{
    char *portname = SERIALTERMINAL;
    int fd;
    int wlen;

    //fd = open(portname, O_RDWR | O_NOCTTY | O_SYNC); original version
    fd = open(portname, O_RDONLY | O_NOCTTY);
    if (fd < 0) {
        printf("Error opening %s: %s\n", portname, strerror(errno));
        return -1;
    }
    /*baudrate 115200, 8 bits, no parity, 1 stop bit */
    set_interface_attribs(fd, B115200);


    /* simple canonical input */
    do {
        unsigned char buf[700];
        unsigned char *p;
        int rdlen;

        rdlen = read(fd, buf, sizeof(buf) - 1);
        if (rdlen > 0) {
            buf[rdlen] = 0;

            printf("%s", buf);

        } else if (rdlen < 0) {
            printf("Error from read: %d: %s\n", rdlen, strerror(errno));
        } else {  /* rdlen == 0 */
            printf("Nothing read. EOF?\n");
        }               
        /* repeat read */
    } while (1);
}

When the program is run it doesn't show any output.

Going back out of CRTSCTS mode by swapping:

tty.c_cflag |= ~CRTSCTS;

with

tty.c_cflag &= ~CRTSCTS;

the program will show output but it is then not in the CRTSCTS mode which I need in order to prevent sending a DTR signal which results in an Arduino reset.

I have tried quite a few different options after reading through the Termios documentation: http://man7.org/linux/man-pages/man3/termios.3.html but to no avail.

So the question is what combination of options will allow reading from the serial port without sending a DTR signal?

user2395126
  • 526
  • 1
  • 7
  • 20
  • 1
    The line `tty.c_cflag |= ~CRTSCTS;` should be `tty.c_cflag |= CRTSCTS;`. Please note that `~` is the "binary not" (bit-wise inversion) operator. – the busybee Sep 17 '19 at 09:59
  • Thanks! I corrected the code but it seems that the Arduino is still receiving a DTR signal. Any suggestions? – user2395126 Sep 20 '19 at 19:49
  • *"Arduino is still receiving a DTR signal"* -- If DTR is being used for board conrol rather than serial handshake, then disable the HW flow-control in termios. You can then try to manipulate the DTR line using **ioctl()** commands TIOCMBIC and TIOCMBIS on the TIOCM_DTR flag. Reference the [manpage for tty_ioctl](https://linux.die.net/man/4/tty_ioctl). – sawdust Oct 04 '19 at 23:18

0 Answers0