繁体   English   中英

Linux RS485串行通信的时间消耗

[英]Time consumption of Linux RS485 serial communication

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

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

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

根据我的计算和数字示波器,发送8个字节的成本为2.083ms,接收23个字节的成本为5.99ms,Modbus RTU设备的响应时间约为1.3ms。 因此,通信过程的时间总计花费9.373ms。 但是在我的测试程序中,我发现平均通信时间约为15毫秒(平均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;
}

感谢木屑! 以下链接有帮助! 平均时间从15ms减少到10ms。 PXA270上的RS232通信中的高延迟

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM