The development of Linux has exceeded Microsoft's imagination in recent years, and has caught up with Microsoft's trend. As a result, most people begin to learn about Linux. Generally, in Linux, set the serial port to use function settings related to terminal I/O, such as tcsetattr. in Linux, there is an index to the list of common baud rates, and the register of the asynchronous communication chip is set with the underlying Driver Based on the configured baud rate.
For non-standard random baud rates, the ioctl (fd, TIOCGSERIAL, p) and ioctl (fd, TIOCSSERIAL, p) must be used together. The last parameter of ioctl is the strucsct serial_struct * type, in Linux/serial. h. Here, baud_base is the baseline crystal oscillator Frequency/16, usually 115200. You need to set the custom_divisor value. The final baud rate is baud_base/custom_divisor. For example, you need 28800 because 115200/4 = 28800, therefore, set custom_divisor = 4 ,.
The specific process is to first set the baud rate to 38400 (tcsetattr), then use TIOCGSERIAL to get the current settings, set the flags ASYNC_SPD_CUST bit, set custom_divisor, and finally use TIOCSSERIAL settings.
Setserial is actually used to set baud_base, custom_divisor, etc. Its internal implementation is to use ioctl for setting,
In addition, you can use hardware to replace the crystal oscillator and use some non-standard baud rates based on the ratio.
Reference: http://blog.ednchina.com/seam_liu/7181/post.aspx
- #include <termios.h>
- #include <sys/ioctl.h>
- #include <Linux/serial.h>
- struct serial_t {
- int fd;
- char *device;/*/dev/ttyS0,...*/
- int baud;
- int databit;/*5,6,7,8*/
- char parity;/*O,E,N*/
- int stopbit;/*1,2*/
- int startbit;/*1*/
- struct termios options;
- };
// Set it to the specific baud rate, such as 28800
- int serial_set_speci_baud(struct serial_t *tty,int baud)
- {
- struct serial_struct ss,ss_set;
- cfsetispeed(&tty->options,B38400);
- cfsetospeed(&tty->options,B38400);
- tcflush(tty->fd,TCIFLUSH);/*handle unrecevie char*/
- tcsetattr(tty->fd,TCSANOW,&tty->options);
- if((ioctl(tty->fd,TIOCGSERIAL,&ss))<0){
- dprintk("BAUD: error to get the serial_struct info:%s\n",strerror(errno));
- return -1;
- }
- ss.flags = ASYNC_SPD_CUST;
- ssss.custom_divisor = ss.baud_base / baud;
- if((ioctl(tty->fd,TIOCSSERIAL,&ss))<0){
- dprintk("BAUD: error to set serial_struct:%s\n",strerror(errno));
- return -2;
- }
- ioctl(tty->fd,TIOCGSERIAL,&ss_set);
- dprintk("BAUD: success set baud to %d,custom_divisor=%d,baud_base=%d\n",
- baud,ss_set.custom_divisor,ss_set.baud_base);
- return 0;
- }
Usage: you only need to specify the baud of serial_t.
- static struct serial_t __seri_conf[] = {
- [0] = {//connect with b board, ttyS0
- .device = "/dev/ttyS0",
- .baud = 28800,
- .databit = 8,
- .parity = 'N',
- .stopbit = 1,
- },
- };
The above is the configuration and usage of non-standard baud rates in Linux.