c - C 中带有 termios : unreliable output capitalization 的串行 I/O

标签 c linux io tty termios

我有一个非常小的 C 程序,它向串行设备发送和从串行设备接收以换行符结尾的 ASCII 字符串。它通过 USB 适配器插入我的计算机,位于 /dev/ttyUSB0 上。

大多数时候它只发送命令 find,但偶尔它会将所有小写字母大写为大写。它不理会所有特殊字符。

我发送的字符串是/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 标志可以修改串行端口上的输出?

最佳答案

c_oflag & OLCUC 在输出中打开小写到大写的映射。由于您从未初始化过 tio,因此设置了一些随机标志也就不足为奇了。

你有两个选择:

  1. tcgetattr 把当前的设置放到一个termios结构体中进行初始化,然后修改你感兴趣的,再用写回去tcsetattr

  2. 所有 termios 字段初始化为已知值,而不仅仅是 c_cflag 和速度字段。

关于c - C 中带有 termios : unreliable output capitalization 的串行 I/O,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26133047/

相关文章:

c - Apache2.4如何加载一个完整的库

linux - printf 使用 in/bin/bash

linux - 使用正则表达式提取多个值并将它们重新格式化为 shell oneliner 中的新字符串?

c# - 提供对超大 (50GB+) ASCII 文件的随机读取访问

linux - 使用 x64 汇编代码的基本输入

c - 如何使用c在opencv中基于X轴对点 vector 进行排序?

c++ - 从外部调用静态 C 函数

c - 如果第一个参数仅指示枚举值,如何找出参数的数量(使用变量参数)?

linux - 开发 GTK+ 应用程序的好代码编辑器

java - 如何迭代文本文件以执行不同的任务(包括创建未知数量的对象),具体取决于我正在阅读的行