gpt4 book ai didi

linux - Linux RS485串口通讯耗时

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

我正在尝试通过一个 USB 到 RS232 到 RS485 端口以波特率 38400、1 个起始位、8 个数据位、无奇偶校验和 1 个停止位与多个 Modbus RTU 设备通信。

与一台Modbus RTU设备的通讯过程如下:

  1. 向设备发送8个字节;
  2. 等待设备的回复;
  3. 收到 23 字节的回复。

根据我和数字示波器的计算,发送8个字节花费2.083ms,接收23个字节花费5.99ms,Modbus RTU设备的响应时间约为1.3ms。所以通信过程的时间总共花费了9.373ms。但在我的测试程序中,我发现平均通信时间约为 15ms(平均 10000 次)。我想知道额外的 5 毫秒是从哪里来的,我该如何优化我的程序来减少这个时间。

提前致谢!

测试程序如下:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <errno.h>
#include <string.h>
#include <signal.h>

void print_hex_buf(unsigned char *buffer, int size)
{
for (int i=0; i<size; i++)
{
printf("%02x ", buffer[i]);
}
printf("\n");
}

void diff_time(struct timeval t1, struct timeval t2, struct timeval *diff)
{
time_t sec;
suseconds_t usec;

//time in two different days
if (t1.tv_sec > t2.tv_sec)
sec = t2.tv_sec + 24*60*60 - t1.tv_sec;
else
sec = t2.tv_sec - t1.tv_sec;

usec = t2.tv_usec - t1.tv_usec;
if (usec < 0)
{
sec -= 1;
usec += 1000000;
}

diff->tv_sec = sec;
diff->tv_usec = usec;
}

int serial_write(int uart_fd, char *buffer, int size)
{
int count = 0;

count = write(uart_fd, buffer, size);
return count;
}

int serial_read(int uart_fd, char *buffer, int size)
{
int count = 0;
int bytes_read = 0;
int read_retry = 0;

fd_set fds_read;
struct timeval timeout;
FD_ZERO(&fds_read);
FD_SET(uart_fd, &fds_read);

timeout.tv_sec = 0;
timeout.tv_usec = 500000; //500ms

int ret = select(uart_fd + 1, &fds_read, NULL, NULL, &timeout);
if (ret > 0 && FD_ISSET(uart_fd, &fds_read))
{
count = read(uart_fd, buffer, size);
bytes_read = (count > 0)?count:0;
while (bytes_read < size && read_retry++ < 500)
{
count = read(uart_fd, buffer+bytes_read, size-bytes_read);
bytes_read += (count > 0)?count:0;
if (bytes_read >= size)
break;
}
}
else
{
printf("Failed to from uart!\n");
return -1;
}

return bytes_read;
}

int main(int argc, char** argv)
{
int fd;
struct termios opt;
int count;
unsigned char send_buf[] = { 0x01, 0x04, 0x00, 0x00, 0x00, 0x09, 0x30, 0x0c};
unsigned char buffer[256];
int iteration = 0;
int delay_ms = 0;
int err_count = 0;
int cycle = 0;
suseconds_t average_time = 0;

setbuf(stdout, NULL);

if (argc != 3)
{
printf("Usage: testuart [uart device] [iteration]\n");
return 0;
}

iteration = atoi(argv[2]);

fd = open(argv[1], O_RDWR | O_NOCTTY | O_NDELAY);
if (fd == -1)
{
printf("Failed to open port: %s\n", argv[1]);
return -1;
}

if (tcgetattr(fd, &opt) != 0)
{
printf("Failed to get uart attribute!\n");
return -1;
}

opt.c_cflag = B38400|CS8|CREAD|CLOCAL;
opt.c_iflag = IGNPAR;
opt.c_cflag &= ~PARENB;
opt.c_cflag &= ~PARODD;
opt.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
opt.c_oflag &= ~OPOST;
opt.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);

tcflush(fd, TCIFLUSH);

if (tcsetattr(fd, TCSANOW, &opt) != 0)
{
printf("Failed to setup serial port!\n");
close(fd);
return -1;
}

while (cycle++ < iteration)
{
printf("Send hex command:\n");
print_hex_buf(send_buf, 8);
struct timeval tm_start;
struct timeval tm_end;
struct timeval tm_diff;
gettimeofday(&tm_start, NULL);
count = serial_write(fd, send_buf, 8);
if (count != 8)
{
printf("Failed to write 8 bytes!\n");
close(fd);
return -1;
}

count = serial_read(fd, buffer, 23);
if (count <= 0)
{
printf("serial read returns %d\n", count);
close(fd);
return -1;
}

gettimeofday(&tm_end, NULL);
diff_time(tm_start, tm_end, &tm_diff);

print_hex_buf(buffer, count);
printf("serial communication costs %ld.%06ld seconds.\n",
tm_diff.tv_sec, tm_diff.tv_usec);
average_time = ((average_time*(cycle-1))+tm_diff.tv_usec)/cycle;
}

printf("%d times, average time in usec is %ld\n", cycle-1, average_time);
close(fd);
return 0;
}

最佳答案

感谢木屑!以下链接有帮助!平均时间从 15 毫秒减少到 10 毫秒。 High delay in RS232 communication on a PXA270

关于linux - Linux RS485串口通讯耗时,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53627274/

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