串行端口上不常见的波特率 - Linux

Uncommon baud rate on serial port - Linux

我目前正在尝试编写一个程序来读取串行端口。在这个端口上我收到了波特率为875000的数据。这种情况确实不常见,我没有成功修改它。我已经编写了一个小 C 程序来执行此操作,但它不适用于 875000...这里是串口编程的部分代码:

    #include <stdio.h>
    #include <stdlib.h>
    #include <asm/termios.h>
    #include <sys/fcntl.h>
    #include <unistd.h>
    #include <errno.h>
    #include <string.h>
    #include "test.h"

    void read_Serial_Port(const char* DEVICE_PORT)
    {
        int file;
        struct ktermios options;
        unsigned int nCountMax = 60;
        bool b;

        file = open(DEVICE_PORT, O_RDONLY | O_NOCTTY | O_NDELAY);

        if(file == -1){perror("Unable to open the serial port\n");}
        //printf("Serial port open successful !\n");
        int speed = atoi("875000");

        ioctl(file, TCGETS2, &options);     


        options.c_ispeed = speed;
        options.c_ospeed = speed;

        options.c_cflag |= (CLOCAL | CREAD);              
        options.c_cflag |= PARENB;                  
        options.c_cflag |= PARODD; 
        options.c_cflag &= ~CBAUD;

        options.c_cflag |= BOTHER;                                          
        options.c_cflag &= ~CSIZE;                      
        options.c_cflag |= CS8;     

        ioctl(file, TCSETS2, &options); 


        //printf("Reading serial port ...\n\n"); 
        b = readMessage(file, nCountMax);

        if (b == 0){printf("Error while reading serial port\n");}
        //else printf("\nSerial port read successful\n");

        close(file);
        //printf("Serial port closed\n");
    };

最后我在 Whosebug 上找到了另一个主题,它已经完成并解决了我的问题:How to set baud rate to 307200 on Linux?

这是我修改后的代码:

static int rate_to_constant(int baudrate) {
#define B(x) case x: return B##x
switch(baudrate) {
    B(50);     B(75);     B(110);    B(134);    B(150);
    B(200);    B(300);    B(600);    B(1200);   B(1800);
    B(2400);   B(4800);   B(9600);   B(19200);  B(38400);
    B(57600);  B(115200); B(230400); B(460800); B(500000); 
    B(576000); B(921600); B(1000000);B(1152000);B(1500000);
    B(2000000);B(2500000);B(3000000);B(3500000);B(4000000); 
default: return 0;
}
#undef B
}    


int Custom_Baudrate(const char* Device, int rate)
  {

/*Declaration of all the variables needed*/
struct termios2 options;
struct serial_struct serinfo;
int file=-1;
int speed = 0;
int r=rate;



/* Open and configure serial port */
file = open(Device,O_RDWR|O_NOCTTY);

if(file==-1){printf("\nERROR : Unable to open the serial port\n\n");return 1;}

speed = rate_to_constant(r);



/*Find best Baudrate*/
if (speed == 0) {

    /* Custom divisor */
    serinfo.reserved_char[0] = 0;
    if (ioctl(file, TIOCGSERIAL, &serinfo) < 0) file=-1;
    serinfo.flags &= ~ASYNC_SPD_MASK;
    serinfo.flags |= ASYNC_SPD_CUST;

    serinfo.custom_divisor = ((serinfo.baud_base + (r / 2)) / r);

    if (serinfo.custom_divisor < 1) 
        serinfo.custom_divisor = 1;
    if (ioctl(file, TIOCSSERIAL, &serinfo) < 0) file=-1;
    if (ioctl(file, TIOCGSERIAL, &serinfo) < 0) file=-1;
    if (serinfo.custom_divisor * r != serinfo.baud_base) {
        warnx("actual baudrate is %d / %d = %f",
              serinfo.baud_base, serinfo.custom_divisor,
              (float)
              serinfo.baud_base / serinfo.custom_divisor);
    }
}



/*Set the best Baudrate (if desired baudrate is unvailable, it's set automatically at 38400)*/
fcntl(file, F_SETFL, 0);
tcgetattr(file, &options);
cfsetispeed(&options, speed ?: B38400);
cfsetospeed(&options, speed ?: B38400);
cfmakeraw(&options);
options.c_cflag |= (CLOCAL | CREAD);
options.c_cflag &= ~CRTSCTS;
if (tcsetattr(file, TCSANOW, &options) != 0) file=-1;


/*Read the serial port*/
communicate_Serial_Port(file);

close(file);
return 1;
}

在此代码中,您只需精确确定所需的波特率,它就会找到您可以使用的最接近的值。该值基于您设备的 "base baudrate",它会搜索一个除数以设置最佳波特率。但是,某些波特率应该始终不可用,因此该程序会将 38400 作为基础(这是一个选择)。 我用几个波特率测试它,它总是有效。

我是 Whosebug 的新手,我希望这个 post 能正确完成问题。

不幸的是,对于自定义波特率,您有时需要自定义硬件,或者至少需要自定义驱动程序。 Linux 处理的标准波特率非常有限,但现代 UART 通常可以达到更多,因为波特率发生器的时钟频率比 30-40 年前高得多,此外还经常支持小数分频器。一个例子: https://assets.maxlinear.com/web/documents/xr17v358.pdf

它可以使用125MHz 或62.5MHz 作为参考,在125MHz 时,875000 的波特率需要8 和15/16 的分频器。为此,您必须使用自定义 exar_serial 驱动程序而不是通常的 Linux 串行子系统。

在较旧的硬件上,通常会找到一个不同的 crystal 来获得您想要的频率,甚至经常使用可变或可选振荡器。