Комментарии 6
НЛО прилетело и опубликовало эту надпись здесь
Рекомендую быть осторожным при работе с Coils. В FreeModbus-1.5.0 неправильно реализованы функции xxxGetBits и xxxSetBits (xxx — не помню точно префикс). Согласно спецификации Coils располагаются по возрастанию, а возвращаются по убыванию (старший бит в байте == старшему номеру Coil). А в FreeModbus они возвращаются как есть. Пример.
Требуется получить Coils с 4 по 7. Правильный результат должен быть следующим:
А по версии FreeModbus получается
Запись пока не проверял, но думаю, что аналогичная бяка.
Исходные Coils: N0...N7 = 01001101
Требуется получить Coils с 4 по 7. Правильный результат должен быть следующим:
Байт состояния Coils: 00001011
Старшие 4 бита не используются, далее состояние Coil7...Coil4
А по версии FreeModbus получается
00001101 (или даже 11010000 - точно не помню, а проверить сейчас не могу)
Запись пока не проверял, но думаю, что аналогичная бяка.
+1
Странно. А как у вас колбэк функция реализована? Пользуетесь ли утилитой xMBUtilGetBits?
у меня так
eMBErrorCode
eMBRegCoilsCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNCoils,
eMBRegisterMode eMode )
{
eMBErrorCode eStatus = MB_ENOERR;
int iCoilIndex;
if( ( usAddress >= REG_COIL_START )
&& ( usAddress + usNCoils <= REG_COIL_START + REG_COIL_NREGS ) )
{
iCoilIndex = ( int )( usAddress - REG_COIL_START );
if (eMode == MB_REG_READ)
{
while( usNCoils > 7 )
{
*pucRegBuffer++ = xMBUtilGetBits( usRegCoilBuf, iCoilIndex, 8 );
iCoilIndex+=8;
usNCoils-=8;
}
if (usNCoils) *pucRegBuffer = xMBUtilGetBits( usRegCoilBuf, iCoilIndex, usNCoils );
}
}
else
{
eStatus = MB_ENOREG;
}
return eStatus;
}
0
Я про GetBits и SetBits и написал. Они неправильные. Все колбэки и сопутствующий код брал исключительно из исходников FreeModbus.
Более того, эти самые функции устанавливают макс 8-бит за раз, но для этого используют переменную типа USHORT. Получается что-то вроде
Аналогично для записи. Т.е. можно выйти за границы. Возможно, ничего и не произойдёт, но как-то неуютно :)
Более того, эти самые функции устанавливают макс 8-бит за раз, но для этого используют переменную типа USHORT. Получается что-то вроде
usWordBuf = ucCoilsBuf[ usByteOffset ] << BITS_UCHAR;
usWordBuf != ucCoilsBuf[ usByteOffset + 1 ];
Аналогично для записи. Т.е. можно выйти за границы. Возможно, ничего и не произойдёт, но как-то неуютно :)
0
дополнил записью
eMBErrorCode
eMBRegCoilsCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNCoils,
eMBRegisterMode eMode )
{
eMBErrorCode eStatus = MB_ENOERR;
int iCoilIndex;
if( ( usAddress >= REG_COIL_START )
&& ( usAddress + usNCoils <= REG_COIL_START + REG_COIL_NREGS ) )
{
iCoilIndex = ( int )( usAddress - REG_COIL_START );
if (eMode == MB_REG_READ)
{
while( usNCoils > 7 )
{
*pucRegBuffer++ = xMBUtilGetBits( usRegCoilBuf, iCoilIndex, 8 );
iCoilIndex+=8;
usNCoils-=8;
}
if (usNCoils) *pucRegBuffer = xMBUtilGetBits( usRegCoilBuf, iCoilIndex, usNCoils );
}
else if (eMode == MB_REG_WRITE)
{
while( usNCoils > 7 )
{
xMBUtilSetBits( usRegCoilBuf, iCoilIndex, 8, *pucRegBuffer++ );
iCoilIndex+=8;
usNCoils-=8;
}
if (usNCoils) xMBUtilSetBits( usRegCoilBuf, iCoilIndex, usNCoils, *pucRegBuffer);
}
}
else
{
eStatus = MB_ENOREG;
}
return eStatus;
}
0
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Портирование FreeModbus под STM32. Версия от Динара