强制传输C中的所有串行数据

时间:2011-10-12 23:20:28

标签: c serial-port

我遇到了C语言中串口问题的时间问题。很长一段时间,我以一个波特率(例如9600)向设备发送命令,并期望在另一个设备上发出响应(比如38400)。我无法控制这个协议。情况的原型如下所示:

 open() serial port
 set baud rate to 9600 using termios struct
 write() command
 change baud rate to 38400 using termios struct
 read() response

我遇到的问题是设备无法理解我发送的命令,因为波特率在完成写入之前会更改为38400。我非常肯定写入工作正常,因为它返回我打算写入的字节数。我尝试在写入调用之后添加一个usleep(100000),虽然有时会工作,但我无法保证在更改波特率并读取响应之前,整个消息将在9600传输。我也尝试用tcflush(fd,TCOFLUSH)刷新缓冲区,但我不想丢弃任何数据,所以这也不是正确的方法。

如何强制写入所有串行数据并保证在下次调用之前写入以将波特率更改为38400?这似乎发生在芯片级别,所以我唯一希望包括FTDI库(它是FTDI芯片)并访问寄存器以查看数据何时完成传输?感谢。

4 个答案:

答案 0 :(得分:1)

将WaitCommEvent与包含EV_TXEMPTY的掩码一起使用,以等待驱动程序发送消息。

答案 1 :(得分:1)

为什么不将发射器设置为9600,将接收器设置为38400?最常见的串口硬件支持这一点。

// fd = file descriptor of serial port.  For example:
//  int fd = open ("/dev/ttyUSB0", O_RDWR | O_NOCTTY | O_SYNC);
int
somefunction (int fd)  
{
        struct termios tty;
        memset (&tty, 0, sizeof tty);
        if (tcgetattr (fd, &tty) != 0)
        {
                error ("error %d from tcgetattr: %s", errno, strerror (errno));
                return -1;
        }

        cfsetospeed (&tty, B9600);    // set tty transmitter to 9600
        cfsetispeed (&tty, B38400);   // set receiver to 38400

        if (tcsetattr (fd, TCSADRAIN, &tty) != 0)  // waits until pending output done before changing
        {
                error ("error %d from tcsetattr", errno);
                return -1;
        }
        return 0;
}

我已将我的代码修改为使用TCSADRAIN而不是TCSANOW,以便在发送所有待处理的输出之后才会发生费率更改。

答案 2 :(得分:0)

您应该使用tcdrain()TCSADRAIN tcsetattr()的可选操作代替tcflush

答案 3 :(得分:0)

我使用了Windows FTDI API,发现他们的整个模型令人讨厌地异步。使用正常的串行端口,我希望您可以对消息长度(以位为单位,包括启动,停止,奇偶校验)和波特率进行数学计算,并在传输消息之前合理估计休眠时间。但是,对于FTDI部分,您要处理FTDI部分本身的USB延迟和未知排队。如果您的设备的回复时间不到1毫秒,甚至可能无法在TX和RX阶段之间可靠地转换FTDI。

是否可以将RX连接到不同的UART?这将大大简化您的问题。

如果没有,您可以考虑使用专用线缆将TX连接到RX,以便在切换之前看到您的信息消失。使用二极管,您可以避免设备也看到自己的传输。 3/4双工?