简体   繁体   中英

Uncommon baud rate on serial port - Linux

I'm currently trying to make a programm to read a serial port. On this port I receive data with a baud rate of 875000. It's really uncommon and I don't succeed to modified it. I've make a little C programm to do that but it didn't work with 875000... Here some part of the code with the programmation of the serial port :

    #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");
    };

Finally i've found another topic on stackoverflow wich is complete and solve my problem : How to set baud rate to 307200 on Linux?

Here is my code with the modification :

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;
}

In this code you just have to precise wich baudrate you want and it find the nearest value that you can use. This value is based on the "base baudrate" of your device and it search a divisor to set the best baudrate. However, some baudrate should always being unavailable so this program will put the 38400 as a base (it's a choice). I've test it with several baudrate and it always work.

I'm new on stackoverflow, i hope this post will complete correctly the question.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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