如何在 Linux 上将波特率设置为 307,200?
- 2024-10-30 08:36:00
- admin 原创
- 55
问题描述:
基本上我使用以下代码来设置串行端口的波特率:
struct termios options;
tcgetattr(fd, &options);
cfsetispeed(&options, B115200);
cfsetospeed(&options, B115200);
tcsetattr(fd, TCSANOW, &options);
这很有效。但我知道我必须与使用波特率为 307,200 的设备进行通信。我该如何设置?cfsetispeed(&options, B307200);
不起作用,没有B307200
定义。
我尝试使用 MOXA Uport 1150(实际上是 USB 转串口转换器)和英特尔主板的标准串口。我不知道后者的具体类型,setserial 只是将其报告为 16550A。
解决方案 1:
Linux 对非标准波特率使用一种肮脏的方法,称为“波特率混叠”。基本上,您告诉串行驱动程序以不同的方式解释该值。这由成员中的标志B38400
控制。ASYNC_SPD_CUST
`serial_struct`flags
您需要手动计算自定义速度的除数,如下所示:
// 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) {
fprintf(stderr, "Cannot set serial port speed to %d. Closest possible is %d
", speed, closestSpeed));
}
ioctl(port, TIOCSSERIAL, &ss);
cfsetispeed(&tios, B38400);
cfsetospeed(&tios, B38400);
当然,您需要一个具有合适baud_base
除数设置的串行驱动程序。上述代码片段允许 2% 的偏差,这对于大多数用途来说应该没问题。
并再次告诉驱动程序解释B38400
为 38400 波特:
ioctl(mHandle, TIOCGSERIAL, &ss);
ss.flags &= ~ASYNC_SPD_MASK;
ioctl(mHandle, TIOCSSERIAL, &ss);
需要注意的是:我不确定这种方法是否可以在其他 *nix 版本之间移植。
解决方案 2:
我使用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
命令实现)。
解决方案 3:
在许多操作系统上,枚举值在数值上等于波特率。 因此,只需跳过宏/枚举并传递所需的波特率,例如
cfsetispeed(&options, 307200);
当然,您应该检查返回代码以确保此技巧确实有效,此外并非所有波特率都受所有 UART 支持。
您还可以尝试使用和ioctl 代码设置struct serial_struct中的选项。TIOCGSERIAL
`TIOCSSERIAL`
解决方案 4:
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);
解决方案 5:
是否支持该速度取决于系统。如果B307200
没有定义,则您的系统可能不支持该速度。
这是 stty.c 的源代码: http://www.koders.com/c/fid35874B30FDEAFEE83FAD9EA9A59F983C08B714D7.aspx
您可以看到所有高速变量都是#ifdef,因为对这些速度的支持因系统而异。
解决方案 6:
尝试 ioctl 调用 - 您可以指定任意波特率。也就是说,
ioctl(serialFileDescriptor,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);
- 2024年20款好用的项目管理软件推荐,项目管理提效的20个工具和技巧
- 2024年开源项目管理软件有哪些?推荐5款好用的项目管理工具
- 项目管理软件有哪些?推荐7款超好用的项目管理工具
- 项目管理软件哪个最好用?盘点推荐5款好用的项目管理工具
- 项目管理软件有哪些最好用?推荐6款好用的项目管理工具
- 项目管理软件有哪些,盘点推荐国内外超好用的7款项目管理工具
- 2024项目管理软件排行榜(10类常用的项目管理工具全推荐)
- 项目管理软件排行榜:2024年项目经理必备5款开源项目管理软件汇总
- 2024年常用的项目管理软件有哪些?推荐这10款国内外好用的项目管理工具
- 项目管理必备:盘点2024年13款好用的项目管理软件