无法以某些波特率通信 [英] Can't communicate with certain baud rates
问题描述
我的应用程序能够以 4800、9600 和 115200 等波特率进行通信,但不能以 14400 或 38400 进行通信.我必须包含 asm/termios
因为我需要 struct termios2
因为我将使用 c_ispeed
和 c_ospeed
成员来获得任何 buad 速率.
My application is able to communicate with baud rates like 4800, 9600 and 115200 but can't with 14400 or 38400. I have to include asm/termios
because I need struct termios2
since I'm going to use c_ispeed
and c_ospeed
members for any buad rate.
另外我遇到的第二个问题是read
函数在VTIME
之后没有返回.你知道为什么会这样吗?任何帮助表示赞赏.谢谢.
Also the second problem I encounter is that read
function doesn't return afterVTIME
. Do you know why this happens? Any help is appreciated. Thanks.
#include <asm/termios.h>
int serialDevice = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY | O_SYNC);
serialSettings.baudRate = 4800;
serialSettings.dataBits = 8;
serialSettings.hardwareFlowControl = 0;
serialSettings.parity = 0;
serialSettings.parityOdd = 0;
serialSettings.stopBits = 1;
serialSettings.xonxoff = 1;
setSerialSettings(serialDevice, &serialSettings);
//-------------------------------------------------------
int8_t setSerialSettings(int serialDevice, Serial_Params_t *settings)
{
struct termios2 tty;
memset(&tty, 0, sizeof tty);
// get current serial settings
if (ioctl(serialDevice, TCGETS2, &tty) == -1)
{
sendLog("Can't get serial attributes | setSerialSettings", LOG_TYPE_ERROR);
return FALSE;
}
// baudrate
tty.c_cflag &= ~CBAUD;
tty.c_cflag |= BOTHER;
tty.c_ispeed = MAX(110, MIN(settings->baudRate, MAX_BAUDRATE));
tty.c_ospeed = MAX(110, MIN(settings->baudRate, MAX_BAUDRATE));
// enable input parity check
tty.c_iflag |= INPCK;
// data bits: CS5, CS6, CS7, CS8
tty.c_cflag &= ~CSIZE;
switch (settings->dataBits)
{
case 5:
tty.c_cflag |= CS5;
break;
case 6:
tty.c_cflag |= CS6;
break;
case 7:
tty.c_cflag |= CS7;
break;
case 8:
default:
tty.c_cflag |= CS8;
break;
}
// stop bit
switch (settings->stopBits)
{
case 1:
default:
tty.c_cflag &= ~CSTOPB;
break;
case 2:
tty.c_cflag |= CSTOPB;
}
// parity
if (settings->parity == 1)
tty.c_cflag |= PARENB;
else
tty.c_cflag &= ~PARENB;
// odd/even parity
if (settings->parityOdd == 1)
tty.c_cflag |= PARODD;
else
tty.c_cflag &= ~PARODD;
// flow control
// XON/XOFF
if (settings->xonxoff == 1)
tty.c_iflag |= (IXON | IXOFF | IXANY);
else
tty.c_iflag &= ~(IXON | IXOFF | IXANY);
// enable RTS/CTS
if (settings->hardwareFlowControl == 1)
tty.c_cflag |= CRTSCTS;
else
tty.c_cflag &= ~CRTSCTS;
tty.c_cc[VMIN] = 1; // return read function when receive 1 byte
tty.c_cc[VTIME] = 10; // 1 seconds read timeout (deciseconds)
tty.c_cflag |= CREAD | CLOCAL; // turn on READ & ignore ctrl lines
// non-canonical mode
tty.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL);
tty.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
tty.c_oflag &= ~OPOST;
// flush port & apply attributes
tcflush(serialDevice, TCIFLUSH);
if (ioctl(serialDevice, TCSETS2, &tty) == -1)
{
sendLog("Can't set serial attributes | setSerialSettings", LOG_TYPE_ERROR);
return FALSE;
}
return TRUE;
}
推荐答案
我的应用程序能够以 4800、9600 和 115200 等波特率进行通信,但不能以 14400 或 38400 进行通信.
My application is able to communicate with baud rates like 4800, 9600 and 115200 but can't with 14400 or 38400.
这里有一篇关于自定义串行速度设置如何工作的非常好的文章:https://github.com/npat-efault/picocom/blob/master/termios2.txt.
There is a pretty nice writeup for how custom serial speed setting works here: https://github.com/npat-efault/picocom/blob/master/termios2.txt.
简而言之,给定由 tty
标识的 struct termios2
,要将输入和输出速度设置为自定义值,您必须
In brief, given a struct termios2
identified by tty
, to set both input and output speed to custom values, you must
- 确保
tty.c_cflag &CBAUD == 麻烦
.您似乎正确地做到了这一点. - 在
tty.c_ospeed
中设置所需的输出速度.你也这样做. 要么
- ensure that
tty.c_cflag & CBAUD == BOTHER
. You appear to do this correctly. - set the desired output speed in
tty.c_ospeed
. You do this, too. either
- 确保
(tty.c_cflag >> IBSHIFT) &CBAUD == B0
,此时输出速度也将用作输入速度,或 - 确保
(tty.c_cflag >> IBSHIFT) &CBAUD == BOTHER
,在这种情况下tty.c_ispeed
将用作输入速度.
- ensure that
(tty.c_cflag >> IBSHIFT) & CBAUD == B0
, in which case the output speed will also be used as the input speed, or - ensure that
(tty.c_cflag >> IBSHIFT) & CBAUD == BOTHER
, in which casetty.c_ispeed
will be used as the input speed.
你不做任何一个.我不确定为什么这会导致某些速度而不是其他速度的错误通信,但据说该驱动程序会玩一些带有速度设置的有趣游戏,也许您已经偶然发现了.
You do not do either of those. I'm uncertain why this would cause incorrect communication for some speeds and not others, but the driver is reputed to play some interesting games with speed settings, and maybe you've stumbled across one.
至于
read
函数在 VTIME
我认为您的期望不正确.您将 VMIN
和 VTIME
都设置为非零值.在这种情况下,VTIME
是最大字符间时间,而不是整体读取超时.使用这些设置,阻塞读取将无限期地等待第一个字符,然后将继续读取后续字符,直到请求的数量,只要每个字符到达前一个字符的 VTIME
分秒之内.
I think you have incorrect expectations. You are setting VMIN
and VTIME
both to nonzero values. In this case, VTIME
is the maximum inter-character time, not an overall read timeout. With these settings, a blocking read will wait indefinitely for the first character, then will keep reading subsequent characters, up to the requested number, as long as each one arrives within VTIME
deciseconds of the previous one.
如果您希望每次 read()
调用都有一个整体超时,那么将 VMIN
设置为 0,并为某些 read()
做好准备> 调用读取 0 个字节.与往常一样,read()
也可以读取正数但少于请求的字节数.与您目前使用的配置相比,这种配置更可能发生这种情况,具体取决于您选择的 VTIME
和对等方的行为.
If you want an overall timeout on every read()
call, then set VMIN
to 0, and be prepared for some read()
calls to read 0 bytes. As always, read()
may also read a positive number of bytes but fewer than requested. That may be more likely to happen in this configuration than in the one you're presently using, depending on your choice of VTIME
and the behavior of the peer.
这篇关于无法以某些波特率通信的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!