gpt4 book ai didi

c - 启用流控制的 Linux 上的串行通信 - 不良行为

转载 作者:太空狗 更新时间:2023-10-29 12:27:04 25 4
gpt4 key购买 nike

为了管理串口,我写了常用的函数,基于如下结构:

  typedef struct
{
int PHandle;
unsigned int Port;
unsigned int BaudRate;
unsigned char Parity;
unsigned char FlowControl;
char Device[MAX_SIZE];
} Tst_SPort;

我在另一个文件中调用这些函数(见下文)以测试 RS232 串口。需要开启流量控制。

  int iInit(Tst_SPort *port, const char *device, int baudRate, unsigned char parity, unsigned char flowControl)
{
strncpy(port->Device, device, MAX_SIZE);
port->PHandle = iOpen(port);
port->Port = -1;
port->BaudRate = baudRate;
port->Parity = parity;
port->FlowControl = flowControl;
if(port->PHandle > 0)
{
setuart(port, port->BaudRate);
}
return port->PHandle;
}

int iOpen(Tst_SPort *port)
{
port->PHandle = open(port->Device, O_RDWR | O_NOCTTY);
if(port->PHandle < 0)
{
perror("open:");
return (-1);
}
return (port->PHandle);
}

void setuart(Tst_SPort *port, int baudRate)
{
struct termios opt, optCmp;
struct serial_struct info;

if(port->PHandle > 0)
{
bzero(&opt, sizeof(opt));
bzero(&optCmp, sizeof(optCmp));

if(ioctl(port->PHandle, TIOCGSERIAL, &info) == 0)
port->Port = info.port;

fcntl(port->PHandle, F_SETFL, O_NONBLOCK);

if (tcgetattr(port->PHandle, &opt) < 0)
perror("tcgetattr Get:");

if(baudRate > 0)
{
cfsetospeed (&opt, baudRate);
cfsetispeed (&opt, baudRate);
}

opt.c_iflag = IGNPAR;
opt.c_oflag &= ~OPOST
opt.c_oflag &= ~ONLCR;
opt.c_lflag = 0;
opt.c_cflag |= (CLOCAL | CREAD);
opt.c_cflag &= ~(PARENB | PARODD);
opt.c_cflag |= port->Parity;
opt.c_cflag &= ~CSTOPB;
opt.c_cflag &= ~CSIZE;
opt.c_cflag |= CS8;
if(!port->FlowControl)
opt.c_cflag &= ~CRTSCTS;
else
opt.c_cflag |= CRTSCTS;

opt.c_cc[VMIN] = 0;
opt.c_cc[VTIME] = 50;

if(tcsetattr(opt->PHandle, TCSANOW, &opt) < 0)
perror("tcgetattr Update :");

if (tcgetattr(opt->PHandle, &optCmp) < 0)
perror("tcgetattr Read:");

/* Compare */
if (memcmp((void *)&opt, (void *)&optCmp, sizeof(opt)) != 0)
printf("Conf failed");

tcflush(port->PHandle, TCIFLUSH);
}
}

int iRead(Tst_SPort *port, char *buffer, unsigned long buffLength)
{
struct timeval tv;
fd_set recv;
int s32Read = 0;
int s32Offset = 0;
int s32SRes = 0;

tv.tv_sec = 0;
tv.tv_usec = 100000; /* 100ms */

if ((port) && (port->PHandle > 0))
{
while (s32Offset < buffLength)
{
FD_ZERO(&recv);
FD_SET(port->PHandle, &recv);

s32SRes = select(port->PHandle + 1, &recv, NULL, NULL, &tv);
if ((s32SRes == -1) && (errno == EINTR))
{
continue;
}
else if(s32SRes > 0)
{
if (FD_ISSET(port->PHandle, &recv))
{
s32Read = read(port->PHandle, buffer + s32Offset, buffLength - s32Offset);
if(s32Read > 0)
{
tv.tv_sec = 0;
tv.tv_usec = 5000;
s32Offset += s32Read;
continue;
}
}
}
break;
}
}
return s32Offset;
}

int iClose(Tst_SPort *port)
{
return (close(port->Phandle));
}

为了验证实现,引脚 Tx 和 Rx 已连接在一起,CTS 和 RTS 同上。一切正常,可以正确读取发送的消息。此外,当 Tx 与 Rx 断开连接时,不会按预期读取任何内容。

但是,当 CTS 从 RTS 上拔下时,测试会在端口关闭步骤(约 20 秒)后阻塞。

但是,如果使用 flowControl == 0 调用函数 setuart(),测试不会阻塞并立即返回预期的错误代码。

我可能理解有误,尤其是在端口配置方面。这是做事的好方法吗?

最佳答案

您面临的问题是正确的行为。

在启用流量控制的情况下让 CTS 保持未连接状态,意味着 DTE(又名 PC)无法将数据发送到 DCE(从设备)。

当您尝试写入 UART 输出缓冲区时,它可能已满,应用程序暂时停止运行并等待缓冲区空间可用。

关于c - 启用流控制的 Linux 上的串行通信 - 不良行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37346287/

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