[英]Communication via RS485
我有一台單板計算機通過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()
用於設置UART(通過GPIO),從而RS485可以發送或接收數據。
如果我在linux台式計算機上使用該代碼,則可以正常工作,因為USB / RS485適配器會自動在發送和接收模式之間切換。 在單板計算機上,我必須手動進行操作。 因此,我認為設置GPIO和接收響應會導致時序問題。 我該如何解決這個問題?
可能是與receiveFrame
讀取循環中的錯誤有關。 當收到的數據少於所需的數據量時,將減少循環中下次要接收的數據量,但是當使用與上一個循環相同的指針時,將覆蓋讀取的第一個數據。 您需要增加指針並減小大小:
bytesReceived = read( serHandle_, _frame, bytesToReceive );
if (bytesReceived > 0)
{
bytesToReceive -= bytesReceived;
_frame += bytesReceived;
}
您在發送數據時遇到類似的問題,一次又一次地發送相同的數據,每次發送的次數都更少。
我還建議您實際檢查錯誤(當bytesReceived < 0
),並適當地處理這些情況。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.