POSIX 串行编程,非标准波特率

Posted

技术标签:

【中文标题】POSIX 串行编程,非标准波特率【英文标题】:Serial Programming for POSIX, non-standard baud rate 【发布时间】:2010-09-17 23:46:49 【问题描述】:

我正在 unix 中实现一个简单的程序,它接受 RS232 输入并将其保存到文件中。

我使用了这些参考资料: http://en.wikibooks.org/wiki/Serial_Programming/Serial_Linux 和 http://www.easysw.com/~mike/serial/serial.html

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include <string.h>

int main(int argc,char** argv)

        struct termios tio;
        struct termios stdio;
        int tty_fd;
        fd_set rdset;
        FILE *file;

        unsigned char c;

        memset(&tio,0,sizeof(tio));
        tio.c_iflag=0;
        tio.c_oflag=0;
        tio.c_cflag=CS8|CREAD|CLOCAL;           // 8n1, see termios.h for more information
        tio.c_lflag=0;
        tio.c_cc[VMIN]=1;
        tio.c_cc[VTIME]=5;

        tty_fd=open("/dev/ttyS1", O_RDWR | O_NONBLOCK);      

        speed_t baudrate = 1843200; //termios.h: typedef unsigned long speed_t;
        cfsetospeed(&tio,baudrate);
        cfsetispeed(&tio,baudrate);

        tcsetattr(tty_fd,TCSANOW,&tio);

        file = fopen("out.raw", "wb");      

        while (1)
        
                if (read(tty_fd,&c,1)>0) 
            fwrite(&c, 1, 1, file);
            fflush(file);
                
        

        //close(tty_fd);

我尝试过 921'600 bps 和 1'843'200 bps 的速度,它工作正常。 但是,如果我设置了一个非标准的波特率,例如 1'382'400 bps,它就不起作用了。

也就是说,这行得通:

cfsetospeed(&tio,1843200); cfsetispeed(&tio,1843200);

但这没有(它获取随机数据):

cfsetospeed(&tio,1382400); cfsetispeed(&tio,1382400);

可能是什么问题?

我尝试过使用 WinXP(使用 WIN32 函数 CreateFile、SetCommState 和 ReadFile), 它工作正常(1'843'200 bps 和非标准 1'382'400 bps)

ps:如果你问我为什么需要设置这个非标准的波特率,那是因为一台特殊的机器只能以这种速度工作。

问候, 大卫

【问题讨论】:

对 cfset[io]speed 的调用是否成功返回?这可能是驱动程序限制,并且您有一些内核黑客攻击。 你没有指定你正在开发什么风格的 Unix,但我查看了 Linux 2.6.32 源代码,它肯定是针对标准波特率进行硬编码的,显然是为了节省一些位被传递的结构。不幸的是,我想大多数posixes都会相似。但是,与其他设备驱动程序相比,串行驱动程序相对容易编写/修改。 您好,我正在为 Mac OSX 实现它。我在这里读过一些关于 custom_divisor 设置为 baud_base / your_new_baudrate 的内容。但是这个图书馆似乎很旧。 ***.com/questions/3192478/… 你好,卡尔。您提到您查看了 Linux 2.6.32 源代码,发现它是硬编码的。你在哪里找到这个的?我下载了 linux 源代码,并在该代码中执行“grep -i -R cfsetospeed *”我没有找到任何东西(仅与无关的东西 arch/um/drivers/slip_user.c)。您在哪里找到了 cfsetospeed 的实现?谢谢,大卫。 @DavidPortabella cfsetospeed 是用户空间的一部分,你不会直接在内核中找到它。但是在内核中查看例如drivers/tty/tty_ioctl.c,其中标准波特率是硬编码的。还有其他hacks 也可以。 【参考方案1】:

根据 mans cfsetospeed 接受不等于实际波特率值的宏 B0、B50、B75 等(例如 B9600 等于 15)。所以传递随机整数会导致未定义的行为。

cfsetospeed() 设置存储在 termios 中的输出波特率 termios_p 指向速度的结构,它必须是其中之一 这些常量:B0、B50 等

【讨论】:

以上是关于POSIX 串行编程,非标准波特率的主要内容,如果未能解决你的问题,请参考以下文章

串行与 SPI

波特率串行 windows 端口

RS232,RS422串口标准小结

Qt:支持波特率 250k 的串行库

RS-485 串行端口波特率性能效率

简述单片机串行口的工作方式