gpt4 book ai didi

c++ - 通过 RS485 通讯

转载 作者:太空狗 更新时间:2023-10-29 12:33:54 27 4
gpt4 key购买 nike

我有一台通过 RS485 连接到另一台设备的单板计算机。计算机应向设备发送请求并接收响应(使用设备相关协议(protocol))。我可以毫无问题地发送消息并且设备接收它们(例如,我可以更改设备的参数)。当我想从设备读取参数时出现问题。在这种情况下,我收到了错误的回复(错误的字符、移位的消息、不完整的消息……)。

这是我的初始化代码:

Bool
SerialCommunicator::initPort()
{
if (isInitialized_)
return true;

if (!paramSet())
return false;

bzero( &termIO_, sizeof ( struct termios ));
termIO_.c_iflag |= IGNBRK | IGNPAR;
termIO_.c_cflag |= CREAD | CLOCAL;
termIO_.c_cflag |= CS8;
termIO_.c_oflag |= 0;
termIO_.c_lflag |= 0;

termIO_.c_cc[VTIME] = 0;
termIO_.c_cc[VMIN] = 13; // number of frame characters

String path("/dev/tty" + portSuffix_);
serHandle_ = open(path.c_str(), O_RDWR /*| O_NOCTTY*/);
if (serHandle_ > -1)
{
isInitialized_ = (cfsetispeed(&termIO_, B19200) == 0)
&& (cfsetospeed(&termIO_, B19200) == 0);
isInitialized_ = isInitialized_ && (tcsetattr(serHandle_, TCSANOW, &termIO_) == 0);


return isInitialized_;
}
else
return false;
}

发送代码:

Bool
SerialCommunicator::sendFrame(UByte *_frame, UInt _size)
{
FD_ZERO( &wrFd_ );
FD_ZERO( &rdFd_ );
FD_SET( serHandle_, &wrFd_);
FD_SET( serHandle_, &rdFd_);

Int retVal;
aux_gpio_write_settings();
retVal = select(serHandle_+1, &rdFd_, &wrFd_, NULL, &timeval_);
if (retVal > 0)
{
if( FD_ISSET(serHandle_, &wrFd_) )
{

UInt bytesToSend = _size;
UInt bytesSent = 0;
UInt bytesSentTotal = 0;
while ( bytesToSend > 0 )
{
bytesSent = write( serHandle_, _frame + bytesSentTotal, bytesToSend );
if (bytesSent > 0)
{
bytesToSend -= bytesSent;
bytesSentTotal += bytesSent;
}

}
aux_gpio_read_settings();
tcflush(serHandle_, TCIOFLUSH);
return true;
}
}
usleep(SLEEPTIME);
return false;
}

接收码:

Bool
SerialCommunicator::receiveFrame(UByte *_frame, UInt _size)
{
FD_ZERO( &rdFd_ );
FD_ZERO( &wrFd_ );
FD_SET( serHandle_, &rdFd_ );
FD_SET( serHandle_, &wrFd_ );

Bool retVal;
aux_gpio_read_settings();
retVal = select(serHandle_+1, &rdFd_, &wrFd_, NULL, &timeval_);
if (retVal > 0)
{
if( FD_ISSET(serHandle_, &rdFd_) )
{

UInt bytesToReceive = _size;
UInt bytesReceived = 0;
UInt bytesReceivedTotal = 0;
while ( bytesToReceive > 0 )
{
bytesReceived = read( serHandle_, _frame + bytesReceivedTotal, bytesToReceive );
if (bytesReceived > 0)
{
bytesToReceive -= bytesReceived;
bytesReceivedTotal += bytesReceived;
}
}
return true;
}
}
return false;
}

函数 aux_gpio_write_settings()aux_gpio_read_settings() 用于设置 UART(通过 GPIO)s.t. RS485 可以发送或接收数据。

如果我在我的 linux 台式电脑上使用代码,它工作正常,因为 USB/RS485 适配器会自动在发送和接收模式之间切换。在我的单板计算机上,我必须手动完成。因此,我认为设置 GPIO 和接收响应会导致时序问题。我该如何处理这个问题?

最佳答案

这可能与您在 receiveFrame 中的错误有关读循环。当您收到的数据少于所需的数据量时,您会减少循环中下一次接收的数据量,但是当使用与前一个循环相同的指针时,您会覆盖您读取的第一个数据。您需要增加指针并减小尺寸:

bytesReceived   = read( serHandle_, _frame, bytesToReceive );
if (bytesReceived > 0)
{
bytesToReceive -= bytesReceived;
_frame += bytesReceived;
}

您在发送数据时遇到了类似的问题,您一遍又一遍地发送相同的数据,只是每次发送的数据更少。

我还建议您实际检查错误(当 bytesReceived < 0 时),并适本地处理这些情况。

关于c++ - 通过 RS485 通讯,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18082073/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com