gpt4 book ai didi

规范模式 Linux 串口

转载 作者:太空宇宙 更新时间:2023-11-04 09:59:51 33 4
gpt4 key购买 nike

规范模式状态的 Termios 手册页 ( http://man7.org/linux/man-pages/man3/termios.3.html ):

Input is made available line by line. An input line is available when one of the line delimiters is typed (NL, EOL, EOL2; or EOF at the start of line). Except in the case of EOF, the line delimiter is included in the buffer returned by read(2).

我的问题是:当一个硬件输出数据以符合规范时 - 它是否将 0xD0xA (CRLF) 字节放在传输线的开头以告诉 read() 函数数据已准备好读取?

我之前没有考虑太多,默认(可能是错误的)认为 0xD0xA 位于传输线的末端。

最佳答案

is it putting the 0xD0xA (CRLF) bytes at the beginning of the transmission line to tell the read() function that data is ready to be read?

my last comment to you in your other post 基本上已经回答了您的问题.
显然您不相信手册页 或我,并且也不清楚“行分隔符”、行终止符和 EOL 是什么意思。

“串行端口”“硬件” 没有“开始”“结束” “传输线”。这只是 U[S]ART 的有效负载数据。
当在规范模式下使用 termios 读取串行终端缓冲区时,线路终止只有上下文。
参见 Linux serial drivers了解您的用户空间代码是如何从硬件中删除的。

Linux 使用换行符或具有 ASCII 代码 0x0A 的换行符作为行终止符,如 ma​​n 页面(您已引用)中明确说明的那样。
Termios 允许定义额外的行尾字符,即用于串行终端的 VEOL 和 VEOL2。
行分隔符的每次出现都可能并且将导致(待处理的)规范 read() 返回。
行分隔符将是缓冲区中返回的最后一个字符,除非用户缓冲区太小而无法包含整行。

为 EOF 定义的字符,即 VEOF,默认为 EOT 的 ASCII 代码 0x04,termios 处理方式略有不同。
收到 EOF 字符会导致(待处理的)规范 read() 像行分隔符一样返回,但 EOF 字符不会存储在返回的缓冲区中。
因此,当 EOF 前面有一个行定界符时,read() 将返回一个零代码,一个实际的空行!

如果你是一个多疑的 Thomas,那么你应该将一对 USB-RS232 适配器交叉连接在一起,并测试使用 termios 从串行终端读取时会发生什么。
在第一个串行终端上使用终端仿真器程序(如 minicom)输入数据,并使用以下 C 程序在另一个串行终端上查看规范读取。

#define SERIALTERMINAL      "/dev/ttyUSB1"
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>

int set_interface_attribs(int fd, int speed)
{
struct termios tty;

if (tcgetattr(fd, &tty) < 0) {
printf("Error from tcgetattr: %s\n", strerror(errno));
return -1;
}

cfsetospeed(&tty, (speed_t)speed);
cfsetispeed(&tty, (speed_t)speed);

tty.c_cflag |= CLOCAL | CREAD;
tty.c_cflag &= ~CSIZE;
tty.c_cflag |= CS8; /* 8-bit characters */
tty.c_cflag &= ~PARENB; /* no parity bit */
tty.c_cflag &= ~CSTOPB; /* only need 1 stop bit */
tty.c_cflag &= ~CRTSCTS; /* no hardware flowcontrol */

tty.c_lflag |= ICANON | ISIG; /* canonical input */
tty.c_lflag &= ~(ECHO | ECHOE | ECHONL | IEXTEN);

tty.c_iflag &= ~IGNCR; /* preserve carriage return */
tty.c_iflag &= ~INPCK;
tty.c_iflag &= ~(INLCR | ICRNL | IUCLC | IMAXBEL);
tty.c_iflag &= ~(IXON | IXOFF | IXANY); /* no SW flowcontrol */

tty.c_oflag &= ~OPOST;

tty.c_cc[VEOL] = 0;
tty.c_cc[VEOL2] = 0;
tty.c_cc[VEOF] = 0x04;

if (tcsetattr(fd, TCSANOW, &tty) != 0) {
printf("Error from tcsetattr: %s\n", strerror(errno));
return -1;
}
return 0;
}


int main()
{
char *portname = SERIALTERMINAL;
int fd;
int wlen;

fd = open(portname, O_RDWR | O_NOCTTY | O_SYNC);
if (fd < 0) {
printf("Error opening %s: %s\n", portname, strerror(errno));
return -1;
}
/*baudrate 115200, 8 bits, no parity, 1 stop bit */
set_interface_attribs(fd, B115200);

/* simple output */
wlen = write(fd, "Hello!\n", 7);
if (wlen != 7) {
printf("Error from write: %d, %d\n", wlen, errno);
}
tcdrain(fd); /* delay for output */


/* simple canonical input */
do {
unsigned char buf[83];
unsigned char *p;
int rdlen;

rdlen = read(fd, buf, sizeof(buf) - 1);
if (rdlen > 0) {
buf[rdlen] = 0;
printf("Read %d:", rdlen);
/* first display as hex numbers then ASCII */
for (p = buf; rdlen-- > 0; p++) {
printf(" 0x%x", *p);
if (*p < ' ')
*p = '.'; /* replace any control chars */
}
printf("\n \"%s\"\n\n", buf);
} else if (rdlen < 0) {
printf("Error from read: %d: %s\n", rdlen, strerror(errno));
} else { /* rdlen == 0 */
printf("Nothing read. EOF?\n");
}
/* repeat read */
} while (1);
}

请注意,程序不会删除'\r'字符(即属性IGNCR被清除),但回车也没有定义为行分隔符。
因此,此 termios 配置中的回车没有特殊含义,就像任何可打印字符一样通过。

所以键入(相当于)ABCDEFG^M^J 被读作:

Read 9: 0x41 0x42 0x43 0x44 0x45 0x46 0x47 0xd 0xa
"ABCDEFG.."

123^Mabc^J 读作:

Read 8: 0x31 0x32 0x33 0xd 0x61 0x62 0x63 0xa
"123.abc."

替代的 termios 配置可以删除回车符或将回车符视为行分隔符。

关于规范模式 Linux 串口,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57152937/

33 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com