There is a code

int open_port() { int fd; /* Файловый дескриптор для порта */ fd = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY | O_NDELAY); if (fd == -1) { /* Не удалось открыть порт */ /* perror() выводит сообщение (в стандартный поток ошибок), затем описание последней случившейся ошибки (на основании errno) */ perror("open_port: Unable to open /dev/ttyS0 - "); } else { /* Порт успешно открыт */ /* fcntl выполняет одну из различных дополнительных операций над файловым дескриптором fd */ /* F_SETFL - Устанавливает часть флагов, относящихся к состоянию файла, согласно значению, указанному в аргументе arg. (0) */ fcntl(fd, F_SETFL, 0); printf("Ok - Port open!\n"); } return (fd); } int main(int argc, char **argv) { system("clear"); int fd; fd = open_port(); /* ----------------- Запись ------------------*/ int n; /* Количество посланных байт(write) */ char buf[] = "qwertyuiop"; /* Буффер ввода */ int length; /* Длина строки ввода (Количество байт) */ length = strlen(buf); n = write(fd, buf, length); /* write возвр. -1 при ошибке */ /* stderr - стандартный поток ошибок */ if (n == -1) { fputs("Записать не удалось!\n", stderr); } else { printf("Успешно записано %d байт(а) \n", n); } /* ------------------ Чтение ---------------- */ int k,i; fcntl(fd, F_SETFL, FNDELAY); char buf1[10]; k = read(fd, buf1, length); if (k == -1) { printf("buffer = %s, Kod = %d \n", buf1, k); printf("Ошибка чтения!\n"); } else { printf("buffer = %s, Kod = %d \n", buf1, k); } close(fd); printf("Ok - Port Close!\n\n"); return 0; } 

Which should read and write to the comport. He writes regularly, but he does not read from it. The code is not entirely mine, and I understand the subject a little, therefore I have 2 questions, the first how to read from the port com and the 2nd where to read how it works. The com port is now self-contained on my TXD on the RXD via the mini-it works.

  • the output of the program to attach to the question would not hurt ... and add strerror(errno) in case of errors. - Fat-Zer
  • And how did the minicom thread or at least cat have already checked that the port / jumper / is something still functioning correctly? - Fat-Zer
  • and who will set the speed? - eri
  • Speaking of speeds ... it’s good to sleep before reading. - Fat-Zer
  • And with some thread minicom or at least cat already checked that the port / jumper / is something still functioning correctly? - Fat-Zer yes, it works through the minicom - SkiF

2 answers 2

By default, the terminal (and the serial port in particular) is opened in a mode suitable for a teletype (as seen from the name tty) or a terminal. From here two features which most of all prevent to work to the given code:

  1. The terminal opens in the "canonical" mode, which means that read () 'at the buffer will be issued only in whole lines or chunks of at least 4096 bytes.
    Solutions:
    • Add '\n' to buf : char buf[] = "qwertyuiop\n";
    • Configure the port in normal mode.
  2. Expected output will be only once. because By default, the terminal has an echo on and every time it is read from the buffer, the read line is sent to the write buffer again (and since the port is closed, then it will come to the read buffer through it). To get rid of this will have to configure the port.

There is also another problem with non-blocking reading: by the time the process begins to read, the data from the system buffer simply does not have time to be transmitted to the port. Because the default port speed is only 9600 baud, and the read attempt happens almost instantly.
Solutions:

  • Open port with O_SYNC
  • Refuse non-blocking read 'a, removing fcntl(fd, F_SETFL, FNDELAY);
  • Add a delay before reading usleep ((1000000L/9600L+1)*8*n*2) (be careful, the time is approximate. You shouldn’t rely on it in real code, although an arbitrary value in the number is taken to double the delay)

You can configure the port in the same way as the @eri response using tcsetattr() , but I advise you to figure out the flags (2/3 in the dead load code that IMHO only distracts from the point) and carefully read man 3 tcsetattr .

  • I agree about the fact that a lot of superfluous, but Linux keeps on the port what the previous program has done. so I expose everything that is possible so as not to get unexpected results. - eri
  • @eri, I’m rather talking about the fact that memset () already removes all unnecessary, so you only need to manually turn on the necessary ... in the end, all the code collapses in 4-6 lines. - Fat-Zer

How do you understand what he writes regularly? If the port is opened by another program in parallel, then it will only be read to one of them.

And you need to set the speed and bits on the port.

For example:

Kopipasta from my code, which kopipaschena (find where I will write the link)

 #include <stdlib.h> #include <stdio.h> #include <string.h> #include <termios.h> void setport(int fd){ struct termios tty; memset (&tty, 0, sizeof tty); cfsetospeed (&tty, 115200); cfsetispeed (&tty, 115200); tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8; // 8-bit chars // disable IGNBRK for mismatched speed tests; otherwise receive break // as \000 chars tty.c_iflag &= ~IGNBRK; // disable break processing tty.c_lflag = 0; // no signaling chars, no echo, // no canonical processing tty.c_oflag = 0; // no remapping, no delays tty.c_cc[VMIN] = 0; // read doesn't block tty.c_cc[VTIME] = 5; // 0.5 seconds read timeout tty.c_iflag &= ~(IXON | IXOFF | IXANY); // shut off xon/xoff ctrl tty.c_cflag |= (CLOCAL | CREAD);// ignore modem controls, // enable reading tty.c_cflag &= ~(PARENB | PARODD); // shut off parity tty.c_cflag |= 0; tty.c_cflag &= ~CSTOPB; tty.c_cflag &= ~CRTSCTS; if (tcsetattr (fd, TCSANOW, &tty) != 0) { fprintf (stderr,"error %d from tcsetattr", errno); } } int main(int argc, char **argv){ ...... int fd = open (portname, O_RDWR | O_NOCTTY | O_SYNC); if (fd<0) { return -11; } setport(fd); ...... } 
  • Does it make sense to set speeds if the port is closed to itself? - Fat-Zer
  • "As you understand what he writes correctly," the diode responsible for receiving and sending is on fire - SkiF
  • @ Fat-Zer there are other flags besides simple ones. - eri