【编程】Linux下非特定波特率(如28800)的配置和使用

本文介绍了如何在Linux系统下配置非标准波特率,特别是28800波特率,以适配如TAX箱等铁路设备的数据通信。通过使用ioctl函数和struct serial_struct进行定制,详细阐述了设置过程,并提供了测试代码。同时推荐使用AccessPort串口调试助手进行测试。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

作为铁路院校毕业的学生,难免和铁路设备打交道。机车安全信息综合检测装置(简称TAX箱)就是这样一个奇葩的设备,数据输出的波特率为28800.而通用的串口波特率设置方法并没有配置成这个波特率的方法。没有办法,只能查资料。各种搜索引擎尝试了之后,发现也有同僚遇到这种问题,但是基本所有的搜索条目都指向了同一个帖子,或者其复制品。而这个帖子只给出了思路和部分代码,没有给出可运行的程序,无奈,只能自己去尝试,去修改,去完善,最终成功搞定,记录一下,供后来人使用,如需转载,请注明出处,谢谢。www.datouinfo.com

http://www.datouinfo.com/?p=1254

对于非标准的任意波特率需要用ioctl(fd, TIOCGSERIAL, p)和ioctl(fd, TIOCSSERIAL, p)的配合,ioctl的最后一个参数是struct serial_struct *类型,在linux/serial.h中定义。其中baud_base是基准晶振频率/16,通常是115200,你需要设的是custom_divisor这个值,最终的波特率为baud_base/custom_divisor,比如你需要28800,因为115200/4=28800,所以要设置custom_divisor=4,。

具体过程为,先设置波特率设为38400(tcsetattr),然后用TIOCGSERIAL得到当前的设置,将flags设置ASYNC_SPD_CUST位,设置custom_divisor,最后用TIOCSSERIAL设置。

使用setserial其实就是利用上述方法,来设置baud_base, custom_divisor等, 其内部实现就是使用ioctl来进行设置。

网上的东西真的是参差不齐,希望能呈现完善的正确的Blog给大家。附代码如下,如有疑问,欢迎留言讨论。由于是测试代码,只是保证可以运行。另外推荐一个串口调试助手AccessPort,可以提供28800的串口比特率作为测试。

001 #include <termios.h>
002 #include <sys/ioctl.h>
003 #include <stdio.h>      /*标准输入输出定义*/
004 #include <stdlib.h>     /*标准函数库定义*/
005 #include <unistd.h>     /*Unix标准函数定义*/
006 #include <sys/types.h>  /**/
007 #include <sys/stat.h>   /**/
008 #include <fcntl.h>      /*文件控制定义*/
009 #include <termios.h>    /*PPSIX终端控制定义*/
010 #include <errno.h>      /*错误号定义*/
011 #include <linux/serial.h>
012  
013 #define TRUE 1
014 #define FALSE 0
015  
016 /*
017 *功能:用于测试非标准波特率串口。
018 *此代码仅限于运行在X86架构的环境下,其他架构并未测试。在arm下未测试
019 *请在root下编译此代码
020 *如有问题,联系我:靳小都 hellojinhongdu#126.com
021 */
022  
023 struct serial_t {
024     int     fd;
025     char    *device;/*/dev/ttyS0,...*/
026     int     baud;
027     int     databit;/*5,6,7,8*/
028     char    parity;/*O,E,N*/
029     int    stopbit;/*1,2*/
030     int    startbit;/*1*/
031     struct termios    options;
032 };
033  
034  
035 int speed_arr[] = { B38400, B19200, B9600, B4800, B2400, B1200, B300,
036         B38400, B19200, B9600, B4800, B2400, B1200, B300, };
037 int name_arr[] = {38400,  19200,  9600,  4800,  2400,  1200,  300,
038         38400,  19200,  9600, 4800, 2400, 1200,  300, };
039  
040 void set_speed(int fd, int speed)
041 {
042   int   i;
043   int   status;
044   struct termios   Opt;
045   tcgetattr(fd, &Opt);
046   for ( i= 0;  i < sizeof(speed_arr) / sizeof(int);  i++)
047    {
048     if  (speed == name_arr[i])
049     {
050         tcflush(fd, TCIOFLUSH);
051         cfsetispeed(&Opt, speed_arr[i]);
052         cfsetospeed(&Opt, speed_arr[i]);
053         status = tcsetattr(fd, TCSANOW, &Opt);
054         if  (status != 0)
055             perror("tcsetattr fd1");
056         return;
057         }
058    tcflush(fd,TCIOFLUSH);
059    }
060 }
061  
062 //设置为特诉波特率,比如28800
063 int serial_set_speci_baud(struct serial_t *tty,int baud)
064 {
065     struct serial_struct ss,ss_set;
066     tcgetattr(tty->fd,&tty->options);
067     cfsetispeed(&tty->options,B38400);
068     cfsetospeed(&tty->options,B38400);
069  
070     tcflush(tty->fd,TCIFLUSH);/*handle unrecevie char*/
071     tcsetattr(tty->fd,TCSANOW,&tty->options);
072     if((ioctl(tty->fd,TIOCGSERIAL,&ss))<0){
073         printf("BAUD: error to get the serial_struct info:%s\n",strerror(errno));
074         return -1;
075     }
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值