gpt4 book ai didi

C 编程检查缓冲区中的消息

转载 作者:行者123 更新时间:2023-11-30 16:22:33 25 4
gpt4 key购买 nike

我是 C 编程新手,所以这可能是一个基本问题。

我有一个 Arduino 通过串口与我的 PC 通信。我遇到的问题是我的电脑读取速度快于串行数据传入(可能是一个常见问题)。

将在 PC 和 arduino 之间发送的消息将具有一些定义的包结构。对于此示例,每条消息均以 ASCII '<' 开头,以 '>' 结尾

我能够打开/创建串行端口并接收数据(复制 some code from stackoverflow ),但是我想将程序修改为:

1) 将所有可用数据从串行端口读取到消息缓冲区中,非阻塞,因此如果没有可用数据,则继续 #2

2) 从消息缓冲区的开头开始查找完整消息,如果有“<”,则继续搜索,直到找到“>”。找到完整消息后,将消息打印到屏幕上,并从缓冲区中删除该消息,将任何未处理的数据移动到缓冲区的开头(这是我真正坚持的部分 )。如果没有找到“>”,则继续#1

我想将逻辑/功能复制到arduino,以便arduino和PC以相同的方式进行通信。

这是我复制的代码,用于打开串行端口并连续从串行端口读取任何内容

#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); /* ignore modem controls*/
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 */

/* setup for non-canonical mode */
tty.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON);
tty.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
tty.c_oflag &= ~OPOST;

/* fetch bytes as they become available */
tty.c_cc[VMIN] = 1;
tty.c_cc[VTIME] = 1;

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

void set_mincount(int fd, int mcount)
{
struct termios tty;

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

tty.c_cc[VMIN] = mcount ? 1 : 0;
tty.c_cc[VTIME] = 5; /* half second timer */

if (tcsetattr(fd, TCSANOW, &tty) < 0)
printf("Error tcsetattr: %s\n", strerror(errno));
}


int main()
{
char *portname = "/dev/ttyACM0";
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 9600, 8 bits, no parity, 1 stop bit */
set_interface_attribs(fd, B9600);
//set_mincount(fd, 0); /* set to pure timed read */

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


/* simple noncanonical input */
do {
unsigned char buf[80];
int rdlen;

rdlen = read(fd, buf, sizeof(buf) - 1);
if (rdlen > 0) {
unsigned char *p;
printf("Read %d:", rdlen);
for (p = buf; rdlen-- > 0; p++)
printf(" 0x%x", *p);
printf("\n");
} else if (rdlen < 0) {
printf("Error from read: %d: %s\n", rdlen, strerror(errno));
} else { /* rdlen == 0 */
printf("Timeout from read\n");
}
/* repeat read to get full message */
} while (1);
}

最佳答案

(1) 打开时将文件描述符设置为非阻塞,或者仅使用 poll() 检查是否有数据要读取。如果您需要进入内核缓冲区并检查缓冲区中有多少字节,您可以使用 ioctl(fd, FIONREAD, &result),但正如有人指出的那样,您确实不需要这样做。无论哪种方式,man ioctl_tty(2) 都有关于 ttys 可用的 ioctl 的详细信息。

(2) 您只需在迭代输入时检查缓冲区中是否有“<”。像这样的事情:

int in_tag = 0;
for (;;) {
// read block
// for each char 'c'
if (in_tag) {
if (c == '>') in_tag = 0;
} else if (c == '<') in_tag = 1;

当然,弄清楚如何处理像“<>”这样的东西是一个完全不同的问题......

关于C 编程检查缓冲区中的消息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54383385/

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