Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/130.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何在Linux上将波特率设置为307200?_C++_C_Linux_Serial Port_Baud Rate - Fatal编程技术网

C++ 如何在Linux上将波特率设置为307200?

C++ 如何在Linux上将波特率设置为307200?,c++,c,linux,serial-port,baud-rate,C++,C,Linux,Serial Port,Baud Rate,基本上,我使用以下代码设置串行端口的波特率: struct termios options; tcgetattr(fd, &options); cfsetispeed(&options, B115200); cfsetospeed(&options, B115200); tcsetattr(fd, TCSANOW, &options); 这很有效。但是我知道我必须和一个波特率为307200的设备通信。我该怎么设置呢cfsetispeed(&options,B30

基本上,我使用以下代码设置串行端口的波特率:

struct termios options;
tcgetattr(fd, &options);
cfsetispeed(&options, B115200);
cfsetospeed(&options, B115200);
tcsetattr(fd, TCSANOW, &options);
这很有效。但是我知道我必须和一个波特率为307200的设备通信。我该怎么设置呢<代码>cfsetispeed(&options,B307200)不起作用,未定义
B307200


我使用MOXA Uport 1150(实际上是USB到串行转换器)和Intel主板的标准串行端口进行了尝试。我不知道后者的确切类型,setserial只是将其报告为16550A。

对该速度的支持取决于系统。如果未定义
B307200
,则您的系统可能不支持它

下面是stty.c的源代码:


您可以看到,所有高速变量都是“ifdef”,因为对这些速度的支持因系统而异。

在许多操作系统上,枚举值在数字上等于波特率。因此,只需跳过宏/枚举并传递所需的波特率,例如

cfsetispeed(&options, 307200);
当然,您应该检查返回代码,以确保此技巧实际起作用,而且并非所有UART都支持所有波特率


您还可以尝试使用
TIOCGSERIAL
TIOCSSERIAL
ioctl代码设置选项。

尝试ioctl调用-您可以指定任意波特率。就是

ioctl(串行文件描述符、IOSSIOSPEED和波特率)

打开串行端口:

// Open the serial like POSIX C
serialFileDescriptor = open(
    "/dev/tty.usbserial-A6008cD3",
    O_RDWR |
    O_NOCTTY |
    O_NONBLOCK );

// Block non-root users from using this port
ioctl(serialFileDescriptor, TIOCEXCL);

// Clear the O_NONBLOCK flag, so that read() will
//   block and wait for data.
fcntl(serialFileDescriptor, F_SETFL, 0);

// Grab the options for the serial port
tcgetattr(serialFileDescriptor, &options);

// Setting raw-mode allows the use of tcsetattr() and ioctl()
cfmakeraw(&options);

// Specify any arbitrary baud rate
ioctl(serialFileDescriptor, IOSSIOSPEED, &baudRate);
// This selector will be called as another thread
- (void)incomingTextUpdateThread: (NSThread *) parentThread {
    char byte_buffer[100]; // Buffer for holding incoming data
    int numBytes=1; // Number of bytes read during read

    // Create a pool so we can use regular Cocoa stuff.
    //   Child threads can't re-use the parent's autorelease pool
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

    // This will loop until the serial port closes
    while(numBytes>0) {
        // read() blocks until data is read or the port is closed
        numBytes = read(serialFileDescriptor, byte_buffer, 100);

        // You would want to do something useful here
        NSLog([NSString stringWithCString:byte_buffer length:numBytes]);
    }
}
uint8_t val = 'A';
write(serialFileDescriptor, val, 1);
io_object_t serialPort;
io_iterator_t serialPortIterator;

// Ask for all the serial ports
IOServiceGetMatchingServices(
    kIOMasterPortDefault,
    IOServiceMatching(kIOSerialBSDServiceValue),
    &serialPortIterator);

// Loop through all the serial ports
while (serialPort = IOIteratorNext(serialPortIterator)) {
    // You want to do something useful here
    NSLog(
        (NSString*)IORegistryEntryCreateCFProperty(
            serialPort, CFSTR(kIOCalloutDeviceKey),
            kCFAllocatorDefault, 0));
    IOObjectRelease(serialPort);
}

IOObjectRelease(serialPortIterator);
从串行端口读取:

// Open the serial like POSIX C
serialFileDescriptor = open(
    "/dev/tty.usbserial-A6008cD3",
    O_RDWR |
    O_NOCTTY |
    O_NONBLOCK );

// Block non-root users from using this port
ioctl(serialFileDescriptor, TIOCEXCL);

// Clear the O_NONBLOCK flag, so that read() will
//   block and wait for data.
fcntl(serialFileDescriptor, F_SETFL, 0);

// Grab the options for the serial port
tcgetattr(serialFileDescriptor, &options);

// Setting raw-mode allows the use of tcsetattr() and ioctl()
cfmakeraw(&options);

// Specify any arbitrary baud rate
ioctl(serialFileDescriptor, IOSSIOSPEED, &baudRate);
// This selector will be called as another thread
- (void)incomingTextUpdateThread: (NSThread *) parentThread {
    char byte_buffer[100]; // Buffer for holding incoming data
    int numBytes=1; // Number of bytes read during read

    // Create a pool so we can use regular Cocoa stuff.
    //   Child threads can't re-use the parent's autorelease pool
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

    // This will loop until the serial port closes
    while(numBytes>0) {
        // read() blocks until data is read or the port is closed
        numBytes = read(serialFileDescriptor, byte_buffer, 100);

        // You would want to do something useful here
        NSLog([NSString stringWithCString:byte_buffer length:numBytes]);
    }
}
uint8_t val = 'A';
write(serialFileDescriptor, val, 1);
io_object_t serialPort;
io_iterator_t serialPortIterator;

// Ask for all the serial ports
IOServiceGetMatchingServices(
    kIOMasterPortDefault,
    IOServiceMatching(kIOSerialBSDServiceValue),
    &serialPortIterator);

// Loop through all the serial ports
while (serialPort = IOIteratorNext(serialPortIterator)) {
    // You want to do something useful here
    NSLog(
        (NSString*)IORegistryEntryCreateCFProperty(
            serialPort, CFSTR(kIOCalloutDeviceKey),
            kCFAllocatorDefault, 0));
    IOObjectRelease(serialPort);
}

IOObjectRelease(serialPortIterator);
写入串行端口:

// Open the serial like POSIX C
serialFileDescriptor = open(
    "/dev/tty.usbserial-A6008cD3",
    O_RDWR |
    O_NOCTTY |
    O_NONBLOCK );

// Block non-root users from using this port
ioctl(serialFileDescriptor, TIOCEXCL);

// Clear the O_NONBLOCK flag, so that read() will
//   block and wait for data.
fcntl(serialFileDescriptor, F_SETFL, 0);

// Grab the options for the serial port
tcgetattr(serialFileDescriptor, &options);

// Setting raw-mode allows the use of tcsetattr() and ioctl()
cfmakeraw(&options);

// Specify any arbitrary baud rate
ioctl(serialFileDescriptor, IOSSIOSPEED, &baudRate);
// This selector will be called as another thread
- (void)incomingTextUpdateThread: (NSThread *) parentThread {
    char byte_buffer[100]; // Buffer for holding incoming data
    int numBytes=1; // Number of bytes read during read

    // Create a pool so we can use regular Cocoa stuff.
    //   Child threads can't re-use the parent's autorelease pool
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

    // This will loop until the serial port closes
    while(numBytes>0) {
        // read() blocks until data is read or the port is closed
        numBytes = read(serialFileDescriptor, byte_buffer, 100);

        // You would want to do something useful here
        NSLog([NSString stringWithCString:byte_buffer length:numBytes]);
    }
}
uint8_t val = 'A';
write(serialFileDescriptor, val, 1);
io_object_t serialPort;
io_iterator_t serialPortIterator;

// Ask for all the serial ports
IOServiceGetMatchingServices(
    kIOMasterPortDefault,
    IOServiceMatching(kIOSerialBSDServiceValue),
    &serialPortIterator);

// Loop through all the serial ports
while (serialPort = IOIteratorNext(serialPortIterator)) {
    // You want to do something useful here
    NSLog(
        (NSString*)IORegistryEntryCreateCFProperty(
            serialPort, CFSTR(kIOCalloutDeviceKey),
            kCFAllocatorDefault, 0));
    IOObjectRelease(serialPort);
}

IOObjectRelease(serialPortIterator);
列出可用串行端口:

// Open the serial like POSIX C
serialFileDescriptor = open(
    "/dev/tty.usbserial-A6008cD3",
    O_RDWR |
    O_NOCTTY |
    O_NONBLOCK );

// Block non-root users from using this port
ioctl(serialFileDescriptor, TIOCEXCL);

// Clear the O_NONBLOCK flag, so that read() will
//   block and wait for data.
fcntl(serialFileDescriptor, F_SETFL, 0);

// Grab the options for the serial port
tcgetattr(serialFileDescriptor, &options);

// Setting raw-mode allows the use of tcsetattr() and ioctl()
cfmakeraw(&options);

// Specify any arbitrary baud rate
ioctl(serialFileDescriptor, IOSSIOSPEED, &baudRate);
// This selector will be called as another thread
- (void)incomingTextUpdateThread: (NSThread *) parentThread {
    char byte_buffer[100]; // Buffer for holding incoming data
    int numBytes=1; // Number of bytes read during read

    // Create a pool so we can use regular Cocoa stuff.
    //   Child threads can't re-use the parent's autorelease pool
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

    // This will loop until the serial port closes
    while(numBytes>0) {
        // read() blocks until data is read or the port is closed
        numBytes = read(serialFileDescriptor, byte_buffer, 100);

        // You would want to do something useful here
        NSLog([NSString stringWithCString:byte_buffer length:numBytes]);
    }
}
uint8_t val = 'A';
write(serialFileDescriptor, val, 1);
io_object_t serialPort;
io_iterator_t serialPortIterator;

// Ask for all the serial ports
IOServiceGetMatchingServices(
    kIOMasterPortDefault,
    IOServiceMatching(kIOSerialBSDServiceValue),
    &serialPortIterator);

// Loop through all the serial ports
while (serialPort = IOIteratorNext(serialPortIterator)) {
    // You want to do something useful here
    NSLog(
        (NSString*)IORegistryEntryCreateCFProperty(
            serialPort, CFSTR(kIOCalloutDeviceKey),
            kCFAllocatorDefault, 0));
    IOObjectRelease(serialPort);
}

IOObjectRelease(serialPortIterator);

USB协商也有类似的问题。我为您找到了这个答案,也可以使用:

struct serial_struct ser_info; 
ioctl(ser_dev, TIOCGSERIAL, &ser_info); 
ser_info.flags = ASYNC_SPD_CUST | ASYNC_LOW_LATENCY; 
ser_info.custom_divisor = ser_info.baud_base / CUST_BAUD_RATE; 
ioctl(ser_dev, TIOCSSERIAL, &ser_info);

Linux对非标准波特率使用脏方法,称为“波特率别名”。基本上,您告诉串行驱动程序以不同的方式解释值
B38400
。这由
serial\u struct
成员
标志中的
ASYNC\u SPD\u CUST
标志控制

您需要手动计算自定义速度的除数,如下所示:

// configure port to use custom speed instead of 38400
ioctl(port, TIOCGSERIAL, &ss);
ss.flags = (ss.flags & ~ASYNC_SPD_MASK) | ASYNC_SPD_CUST;
ss.custom_divisor = (ss.baud_base + (speed / 2)) / speed;
closestSpeed = ss.baud_base / ss.custom_divisor;

if (closestSpeed < speed * 98 / 100 || closestSpeed > speed * 102 / 100) {
    sprintf(stderr, "Cannot set serial port speed to %d. Closest possible is %d\n", speed, closestSpeed));
}

ioctl(port, TIOCSSERIAL, &ss);

cfsetispeed(&tios, B38400);
cfsetospeed(&tios, B38400);

警告:我不确定这个方法是否可以在其他*nix版本之间移植。

我使用
termios2
ioctl()
命令完成了这项工作

struct termios2 options;
ioctl(fd, TCGETS2, &options);
options.c_cflag &= ~CBAUD;    //Remove current BAUD rate
options.c_cflag |= BOTHER;    //Allow custom BAUD rate using int input
options.c_ispeed = 307200;    //Set the input BAUD rate
options.c_ospeed = 307200;    //Set the output BAUD rate
ioctl(fd, TCSETS2, &options);


之后,您应该能够查询端口设置并查看自定义波特率以及其他设置(可以使用
stty
命令)。

您可以使用“stty”设置此波特率吗?如果没有,我怀疑你能(对我来说似乎是一个模糊的速度);如果可以,请看一下它的代码。“速度”选项由termios.h中的八进制值定义,因此您可以通过分析这些值来假设推导出正确的值。No
stty
不起作用,因为它使用一些硬编码值检查波特率。有趣的是,
serserserial
允许设置307200,并且不报告错误。但是当我尝试从串口读取数据时,它不起作用。你真的确定你的设备的波特率是307200吗?这不是无线电通信特有的东西吗?是的,我确信307200是正确的。-1这在Linux上是不正确的,请参阅/usr/include/bits/termios中的定义。佩恩说过这在Linux上不起作用吗
cfsetispeed
需要一个八进制值。我试过使用
0000022
,它应该是307200,但不起作用。
0000022
=
18
,我不知道“应该是307200”。你是对的,它应该是0000024。但这只是一个假设,因为9600被定义为0000015,19200被定义为0000016,38400被定义为0000017。@cairol:我发布了一些额外的信息。关于
TIOCSSERIAL
的详细信息很难找到,您可能需要阅读源代码,但您可以通过这种方式获得非标准波特率。感谢链接。代码中定义了许多高速波特率,但不是307200。Linux上似乎不支持此波特率,因为它既不是在
/usr/include/bits/termios.h
中定义的,也不是在另一个
Bxy
中定义的。老式UNIX的速度为4位。可能VAX硬件在硬件中有类似的4位波特率。无论如何,现代硬件有一个“基本波特率”和一个约数,可以是16位,允许65536个不同的波特率。Linux内核保留旧接口的时间太长了。(大约二十年前,我就不再争论要改变它了)。内核的适当接口只需为请求的波特率设置一个整数。然后内核可以做任何必要的尝试和实现,用户空间libc可以模拟旧的行为。。。太久了,这个问题是关于Linux的,而不是关于BSD的。Linux支持不同的IOCTL,我想我已经在回答中列出了合适的IOCTL。如果你有一些关于
TIOCSSERIAL
的示例代码,那会很有帮助,值得一试。这对我很有用。还有一个问题。还有一个与这个答案相关的问题。OMG。那只是。。。真可怕(有人在设计API之前完全忘了在早餐麦片粥上撒上抽象内容。@放松比你想象的更可怕,因为它的文档记录得很糟糕。我想这就是为什么3年前的这个答案仍然得到支持的原因:)这并不是所有的芯片都支持的。对于多产的PL2303,驱动程序不支持
TIOCSSERIAL
ioctl
命令。我可以直接设置波特率(在我的例子中使用
B921600
)。您必须在Linux中使用
struct termios2
来设置波特率和相应的IOCTL。波特率实际上是307200吗?你量过了吗?实际最接近的波特率可能是230400和460800,也可能不是。@PeterMortensen我没有实际测量实际波特率,但我使用的是一个自定义微控制器,它以自定义波特率运行,似乎没有任何通信问题。确保您遵循了上述所有步骤