Последовательный ввод / вывод в C с помощью termios: ненадежная капитализация выхода

У меня есть очень маленькая программа на C, которая отправляет и получает строки ASCII с символом окончания строки в последовательное устройство. Он подключен к моему компьютеру с помощью USB-адаптера, на /dev/ttyUSB0,

Большую часть времени он отправляет команды только находят, но иногда он будет использовать заглавные буквы в верхнем регистре. Он оставляет все специальные символы в покое.

Я отправляю строку /home\n, Примерно 1 из каждых пяти раз я запускаю программу (просто запустив ./a.out без перекомпиляции), понятное для устройства отправленное сообщение /HOME\n,

Вот мой исходный код:

#include <stdio.h>
#include <stdlib.h>

#include "zserial.h"

int main() {
    char buf[256];
    int fd = connect("/dev/ttyUSB0");
    char *cmd = "/home\n";
    send(fd, cmd);
    receive(fd, buf, 256);
    puts(buf);

    exit(0);
}

И zserial.c:

#include <fcntl.h>
#include <termios.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "zserial.h"

int send(int fd, char *buf) {
    int len = strlen(buf);
    int nb = write(fd, buf, len);
    if (len != nb || nb < 1)  
        perror("Error: wrote no bytes!");
    tcdrain(fd);
    return nb; 
}

int receive(int fd, char *dst, int nbytes) {
    int i;
    char c;
    for(i = 0; i < nbytes;) {
        int r = read(fd, &c, 1); 
        /* printf("Read %d bytes\n", r); */
        if (r > 0) {
            dst[i++] = c;
            if (c == '\n') break;
        }
    }   
    dst[i] = 0; /* null-terminate the string */
    return i;
}

int connect(char *portname) {
    int fd; 
    struct termios tio;

    fd = open(portname, O_RDWR | O_NOCTTY | O_NONBLOCK);
    tio.c_cflag = CS8|CREAD|CLOCAL;
    if ((cfsetospeed(&tio, B115200) & cfsetispeed(&tio, B115200)) < 0) {
        perror("invalid baud rate");
        exit(-1);
    }   
    tcsetattr(fd, TCSANOW, &tio);

    return fd; 
}

Что я делаю неправильно? Есть ли какой-нибудь флаг termios, который изменяет вывод на последовательный порт?

1 ответ

Решение

c_oflag & OLCUC включает отображение строчных и прописных букв на выходе. Так как вы никогда не инициализировали tioНе удивительно, что у вас есть несколько случайных флагов.

У вас есть два варианта:

  1. tcgetattr текущие настройки в termios struct, чтобы инициализировать его, затем изменить те, которые вас интересуют, а затем записать их обратно tcsetattr

  2. инициализировать все поля termios известными значениями, а не только c_cflag и поля скорости.

Другие вопросы по тегам