簡體   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