【发布时间】:2012-02-06 18:38:06
【问题描述】:
我想在 Linux 上使用 C/C++ 代码从我的串口读取数据。
由于我仍然可以使用 GtkTerm 甚至使用 cat /dev/ttyUSB0 从该串行端口读取数据,因此这不是硬件/驱动程序问题。
使用 gtkterm 之类的程序后,似乎没有正确启动串行端口,因为读取确实有效。
这是我用来初始化串口的代码(第二版):
UbiDriver::UbiDriver(const std::string &ttyPort)
{
// Doc : http://www.easysw.com/~mike/serial/serial.html#2_4
m_serialHandle = open(ttyPort.c_str(), O_RDWR | O_NOCTTY | O_NDELAY); // Open perif
if(m_serialHandle < 0)
{
MY_THROW("Impossible d'ouvrir le port '" << ttyPort << "' !\nerrno = " << errno);
}
// Conf
//if(fcntl(m_serialHandle, F_SETFL, 0) == -1) // lecture en mode bloquant
if(fcntl(m_serialHandle, F_SETFL, O_NONBLOCK) == -1) // lecture en mode non bloquant
{
MY_THROW("fcntl failed !\nerrno = " << errno);
}
struct termios options;
tcgetattr(m_serialHandle, &options); // Init struct avec la conf actuelle
cfsetispeed(&options, B9600); // In speed
cfsetospeed(&options, B9600); // Output speed
options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
options.c_cflag |= (CLOCAL | CREAD); // Enable the receiver and set local mode...
options.c_cflag &= ~PARENB; // Desactive bit de parité
options.c_cflag &= ~CSTOPB; // Désactive 2 stop bits -> Active 1 stop bits
options.c_cflag &= ~CSIZE; // Désactive le bit "CSIZE"
options.c_cflag |= CS8; // Communication sur 8 bits
options.c_oflag &= ~OPOST; // Raw output is selected by resetting the OPOST option in the c_oflag member:
// Application de la conf
if(tcsetattr(m_serialHandle, TCSAFLUSH, &options) == -1) // Vidage buffer & application immédiate
{
MY_THROW("tcsetattr failed !\nerrno = " << errno);
}
}
并从端口读取数据
std::string UbiDriver::GetAnswer()
{
const int buffSize = 1024;
char buffer[buffSize] = {'\0'};
int count = 0;
std::string wholeAnswer = "";
int noDataTime = 0;
while(noDataTime < 2) // Tant qu'il y a des données à lire
{
count = read(m_serialHandle, buffer, buffSize - 1);
if(count == -1)
{
MY_THROW("Impossible de lire sur le port serie. Verifiez la connexion avec l'imprimante !")
}
if(count > 0)
{
noDataTime = 0;
buffer[count] = '\0';
for(int i = 0; i < count; i++)
{
buffer[i] &= ~128; // Supression du premier 1 du binaire
}
wholeAnswer += std::string(buffer);
std::cout << count << std::endl;
}
else
{
noDataTime++;
usleep(100000);
}
}
cerr << "----------- Answer -----------" << endl;
cerr << "Size = " << wholeAnswer.size() << endl;
cerr << wholeAnswer << endl;
return wholeAnswer;
return std::string("");
}
注意:此代码是您的 cmets 完成的第二个版本。
【问题讨论】:
-
你说它不起作用。什么不起作用?会发生什么?
-
我不会回答你的问题。这可能是一个特定的平台问题。但也许您可能会考虑使用比使用 termios 更高级别的库来执行此操作。也许是 Python 中的 PySerial 或使用 C 中的高级串行端口 I/O 库。
-
为什么检查read()是否返回-1的代码被注释掉了?它应该在那里,并且应该记录 errno,或者最好是 strerror(errno)。您还应该检查 tcgetattr、cfsetospeed 和 cfsetispeed 是否返回错误。
-
man tcsetattr 也这样说:“请注意,如果任何请求的更改可以成功执行,则 tcsetattr() 将返回成功。因此,在进行多项更改时,可能需要在此调用之后使用进一步调用 tcgetattr() 以检查所有更改是否已成功执行。"
标签: c++ c linux serial-port