如何在 Linux 上将波特率设置为 307200?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4968529/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to set baud rate to 307200 on Linux?
提问by cairol
Basically I'm using the following code to set the baud rate of a serial port:
基本上我使用以下代码来设置串行端口的波特率:
struct termios options;
tcgetattr(fd, &options);
cfsetispeed(&options, B115200);
cfsetospeed(&options, B115200);
tcsetattr(fd, TCSANOW, &options);
This works very well. But know I have to communicate with a device that uses a baud rate of 307200. How can I set that? cfsetispeed(&options, B307200);
doesn't work, there is no B307200
defined.
这非常有效。但是我知道我必须与使用 307200 波特率的设备进行通信。我该如何设置?cfsetispeed(&options, B307200);
不起作用,没有B307200
定义。
I tried it using a MOXA Uport 1150 (that's actually a USB-to-serial converter) and the standard serial port of an Intel motherboard. I don't know the exact kind of the latter, setserial just reports it as 16550A.
我使用 MOXA Uport 1150(实际上是 USB 到串行转换器)和 Intel 主板的标准串行端口进行了尝试。我不知道后者的确切类型,setserial 只是将其报告为 16550A。
回答by payne
Support for that speed is system dependent. If B307200
isn't defined, then your system likely doesn't support it.
对该速度的支持取决于系统。如果B307200
未定义,则您的系统可能不支持它。
Here's the source code for stty.c: http://www.koders.com/c/fid35874B30FDEAFEE83FAD9EA9A59F983C08B714D7.aspx
这是 stty.c 的源代码:http: //www.koders.com/c/fid35874B30FDEAFEE83FAD9EA9A59F983C08B714D7.aspx
You can see that all of the high-speed variables are #ifdef'd, because support for those speeds varies by system.
您可以看到所有高速变量都被 #ifdef'd,因为对这些速度的支持因系统而异。
回答by Ben Voigt
On many OSes, the enumerated values are numerically equal to the baud rate. So just skip the macro/enumeration and pass the baud rate you want, e.g.
在许多操作系统上,枚举值在数字上等于波特率。 所以只需跳过宏/枚举并传递您想要的波特率,例如
cfsetispeed(&options, 307200);
cfsetispeed(&options, 307200);
Of course you should check the return code to make sure this trick actually worked, furthermore not all baud rates are supported by all UARTs.
当然,您应该检查返回代码以确保此技巧确实有效,而且并非所有 UART 都支持所有波特率。
You can also try setting the options in struct serial_structusing the TIOCGSERIAL
and TIOCSSERIAL
ioctl codes.
您还可以尝试使用和ioctl 代码在struct serial_struct 中设置选项。TIOCGSERIAL
TIOCSSERIAL
回答by Bruce Chidester
Try the ioctl call - you can specify an arbitrary baud rate. That is,
尝试 ioctl 调用 - 您可以指定任意波特率。那是,
ioctl(serialFileDescriptor, IOSSIOSPEED, &baudRate);
ioctl(串行文件描述符,IOSSIOSPEED,&baudRate);
To open the serial port:
打开串口:
// 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);
To read from the serial port:
从串行端口读取:
// 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]);
}
}
To write to the serial port:
要写入串行端口:
uint8_t val = 'A';
write(serialFileDescriptor, val, 1);
To list availble serial ports:
列出可用的串行端口:
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);
回答by Bruce Chidester
USB Negotiation has a similar issue. I found this answer for you which might be used as well:
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);
回答by cyco130
Linux uses a dirty method for non-standard baud rates, called "baud rate aliasing". Basically, you tell the serial driver to interpret the value B38400
differently. This is controlled with the ASYNC_SPD_CUST
flag in serial_struct
member flags
.
Linux 对非标准波特率使用一种脏方法,称为“波特率混叠”。基本上,您告诉串行驱动程序以B38400
不同的方式解释该值。这是由member 中的ASYNC_SPD_CUST
标志控制的。serial_struct
flags
You need to manually calculate the divisor for the custom speed as follows:
您需要手动计算自定义速度的除数,如下所示:
// 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);
Of course, you need a serial driver with suitable baud_base
and divisor settings. The preceding snippet allows for 2% deviation, which should be ok for most purposes.
当然,您需要一个具有合适baud_base
和除数设置的串行驱动程序。前面的代码段允许 2% 的偏差,这对于大多数用途来说应该是可以的。
And to tell the driver to interpret B38400
as 38400 baud again:
并告诉驱动程序B38400
再次解释为 38400 波特:
ioctl(mHandle, TIOCGSERIAL, &ss);
ss.flags &= ~ASYNC_SPD_MASK;
ioctl(mHandle, TIOCSSERIAL, &ss);
As a word of caution: I'm not sure if this method is portable between other *nix flavors.
提醒一下:我不确定这种方法是否可以在其他 *nix 风格之间移植。
回答by Chef Pharaoh
I accomplished this using termios2
and ioctl()
commands.
我使用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);
After that, you should be able to query the port settings and see your custom BAUD rate, as well as the other settings (possible with stty
commands).
之后,您应该能够查询端口设置并查看您的自定义波特率以及其他设置(可以使用stty
命令)。