我正在为一个小型硬件项目开发接收器。我正在使用UART传输数据的小型电路板上。
接收器代码完整显示在下面,我将在短期内分别解释有问题的位。
#define TTY "/dev/ttys002"
#include <stdio.h>
#include <string.h>
#include <unistd.h> //Unix standard functions
#include <fcntl.h> //File controls
#include <errno.h> //Error numbers
#include <assert.h>
#include <termios.h> //Posix terminal
int open_port(const char * tty) {
int fd;
fd = open(tty, (O_RDWR | O_NOCTTY | O_NDELAY));
assert("__failed to open port__" && fd != -1);
//Block until read
fcntl(fd, F_SETFL, 0);
return fd;
}
void configure_port(int fd) {
struct termios options;
//Get current options
tcgetattr(fd, &options);
//9600 Baud
cfsetispeed(&options, B9600);
cfsetospeed(&options, B9600);
//Receive & local mode
options.c_cflag |= (CLOCAL | CREAD);
//Raw output
options.c_oflag &= ~OPOST;
//No hardware flow control
options.c_cflag &= ~CRTSCTS;
//No parity, 1 stop bit
options.c_cflag &= ~PARENB;
options.c_cflag &= ~CSTOPB;
//8 data bits
options.c_cflag &= ~CSIZE;
options.c_cflag |= CS8;
//Write options back, set them immediately
tcsetattr(fd, TCSANOW, &options);
}
int main(int argc, const char * argv[]) {
int fd = open_port(TTY);
const size_t count = 8;
char buf[count + 1];
ssize_t n;
configure_port(fd);
while (1) {
n = read(fd, buf, count);
buf[count] = '\0';
if (n > 0) {
printf("%s\n", buf);
}
}
return 0;
}
由于目前手头没有硬件,因此我决定通过常规的tty(
#define TTY "/dev/ttys002"
)测试接收器。为了测试它,我简单地编译并运行了上面的代码,然后打开了一个单独的终端,并:echo "text" >> /dev/ttys002
所有这些工作都很好并且很好,我得到了我正在回荡到tty中的所有数据。
但是,当我在tty中输入一条长消息时,就会出现问题:
echo "this is a longer test message" >> /dev/ttys002
我在程序输出中将整个消息作为单个字符串接收。为什么会这样呢?我本来希望将文本分成8个字符的块(
const size_t count = 8;
)。如果很重要,我将this guide作为配置的基础。
编辑:请参阅评论以对该问题进行进一步讨论。
最佳答案
恕我直言,您的消息被分成了八个字符的块:n = read(fd, buf, count);
一次不能提供超过字节数的计数。
但是由于您未在RAW模式下配置tty行,因此仍处于行缓冲模式。因此,底层驱动程序将阻止第一次读取,直到它的完整行以\n
终止(或超过缓冲区容量)为止。
然后,读取返回前8个字节,而下一个读取也立即返回8个字节,因为驱动程序缓冲区中有可用数据。
如果要使用原始输入模式,则应在man termios中查看非规范模式:
options.c_cflags &= ~ICANON;
/* optionally if defaults are not appropriates */
options.c_cc[VMIN] = vmin; /* default is 1 */
options.c_cc[VTIME] = vtime; /* default is 0 */
但是无论如何,您都读取了字符,并且从不添加终止null,因此buf没有理由将null终止。您只应打印实际读取的字符数:
const size_t count = 8;
char buf[count];
ssize_t n;
configure_port(fd);
while (1) {
n = read(fd, buf, count);
if (n > 0) {
printf("%.*s\n", n, buf); /* only print the n characters */
}
}
关于c - 为什么我的缓冲区长度被忽略?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/30667070/