シングルボード コンピュータを RS485 経由で別のデバイスに接続しています。コンピューターはデバイスに要求を送信し、応答を受信する必要があります (デバイス依存のプロトコルを使用)。問題なくメッセージを送信でき、デバイスはそれらを受信します (たとえば、デバイスのパラメータを変更できます)。この問題は、デバイスからパラメーターを読み取りたいときに発生します。この場合、私は間違った応答を受け取ります (間違った文字、シフトされたメッセージ、不完全なメッセージなど)。
ここに私の初期化コードがあります:
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()
は、RS485 がデータを送受信できるように、(GPIO を介して) UART を設定するために使用されます。
Linux デスクトップ コンピューターでコードを使用すると、USB/RS485 アダプターが送信モードと受信モードを自動的に切り替えるため、問題なく動作します。私のシングルボードコンピューターでは、手動で行う必要があります。そのため、GPIO を設定してレスポンスを受信すると、タイミングの問題が発生すると思います。どうすればこの問題を処理できますか?