我有一个非常小的 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
,因此设置了一些随机标志也就不足为奇了。
你有两个选择:
tcgetattr
把当前的设置放到一个termios
结构体中进行初始化,然后修改你感兴趣的,再用写回去tcsetattr
将 所有 termios 字段初始化为已知值,而不仅仅是
c_cflag
和速度字段。
关于c - C 中带有 termios : unreliable output capitalization 的串行 I/O,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26133047/