How to Set the Baud Rate to 307,200 on Linux

Uncommon baud rate on serial port - Linux

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.

C code for non-standard baud rate on Debian/Raspberry Pi

So after a bit more searching I stumbled upon the following code at:

https://jim.sh/ftx/files/linux-custom-baudrate.c

Below, is a copy of the above code which I've dumbed down quite a bit for my purposes however, it should be quite simple to implement now.

#include<string.h>
#include<stdlib.h>
#include<stdio.h>
#include<errno.h>
#include<unistd.h>
#include<fcntl.h>
#include<termio.h>
#include <linux/serial.h>

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);
default: return 0;
}
#undef B
}

int main() {

struct termios options;
struct serial_struct serinfo;
int fd;
int speed = 0;
int rate = 625000;

/* Open and configure serial port */
if ((fd = open("/dev/ttyUSB0",O_RDWR|O_NOCTTY)) == -1)
{
return -1;
}

// if you've entered a standard baud the function below will return it
speed = rate_to_constant(rate);

if (speed == 0) {
/* Custom divisor */
serinfo.reserved_char[0] = 0;
if (ioctl(fd, TIOCGSERIAL, &serinfo) < 0)
return -1;
serinfo.flags &= ~ASYNC_SPD_MASK;
serinfo.flags |= ASYNC_SPD_CUST;
serinfo.custom_divisor = (serinfo.baud_base + (rate / 2)) / rate;
if (serinfo.custom_divisor < 1)
serinfo.custom_divisor = 1;
if (ioctl(fd, TIOCSSERIAL, &serinfo) < 0)
return -1;
if (ioctl(fd, TIOCGSERIAL, &serinfo) < 0)
return -1;
if (serinfo.custom_divisor * rate != serinfo.baud_base) {
warnx("actual baudrate is %d / %d = %f",
serinfo.baud_base, serinfo.custom_divisor,
(float)serinfo.baud_base / serinfo.custom_divisor);
}
}

fcntl(fd, F_SETFL, 0);
tcgetattr(fd, &options);
cfsetispeed(&options, speed ?: B38400);
cfsetospeed(&options, speed ?: B38400);
cfmakeraw(&options);
options.c_cflag |= (CLOCAL | CREAD);
options.c_cflag &= ~CRTSCTS;
if (tcsetattr(fd, TCSANOW, &options) != 0)
{
//return -1;
}

//return fd;

char ping_cmd[] = {2,1};
char ping_rec[7];

write(fd,&ping_cmd,sizeof(ping_cmd));
read(fd,&ping_rec,sizeof(ping_rec));

int i;
for (i = 0; i < sizeof(ping_rec); i++)
{
printf("%d ",ping_rec[i]);
}

close(fd);
return 0;
}

As the more astute coders out there will notice, since I pulled this code into my main, the presence of all those "return -1" is almost certainly bad programming practice, however, I'm not sure how I should clean it up and hence I'd love hear your suggestions - I will make edits as suggested.

In the meantime though, should you face a similar problem to me, the above should do nicely.

Specifying non-standard baud rate for FTDI virtual serial port under Linux

You can't change baud base, I suppose it is hardware related. So messing with the module won't do you any good. In your third point you only talk about the first method proposed for setting a custom baudrate, where you need to access the tty->alt_speed. It seems there is no interface to directly set tty struct from userspace, at least not with the ftdi_sio driver.

However, there is another method explained in the comments :

     * 3. You can also set baud rate by setting custom divisor as follows
* - set tty->termios->c_cflag speed to B38400
* - call TIOCSSERIAL ioctl with (struct serial_struct) set as
* follows:
* o flags & ASYNC_SPD_MASK == ASYNC_SPD_CUST
* o custom_divisor set to baud_base / your_new_baudrate

Did you try it ?

Dealing with serial port at 100 baud rate

You're actually in luck. 100 baud is low enough that you can compute a divisor that will do it (1,152) with typical 16450-compatible serial ports (which is pretty much what everything is) and linux supports custom divisors with the spd_cust parameter to setserial.



Related Topics



Leave a reply



Submit