Pull to refresh

Comments 6

UFO just landed and posted this here
Рекомендую быть осторожным при работе с Coils. В FreeModbus-1.5.0 неправильно реализованы функции xxxGetBits и xxxSetBits (xxx — не помню точно префикс). Согласно спецификации Coils располагаются по возрастанию, а возвращаются по убыванию (старший бит в байте == старшему номеру Coil). А в FreeModbus они возвращаются как есть. Пример.

Исходные Coils: N0...N7 = 01001101

Требуется получить Coils с 4 по 7. Правильный результат должен быть следующим:

Байт состояния Coils: 00001011
Старшие 4 бита не используются, далее состояние Coil7...Coil4


А по версии FreeModbus получается

00001101 (или даже 11010000 - точно не помню, а проверить сейчас не могу)

Запись пока не проверял, но думаю, что аналогичная бяка.
Странно. А как у вас колбэк функция реализована? Пользуетесь ли утилитой 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;
}


Я про GetBits и SetBits и написал. Они неправильные. Все колбэки и сопутствующий код брал исключительно из исходников FreeModbus.

Более того, эти самые функции устанавливают макс 8-бит за раз, но для этого используют переменную типа USHORT. Получается что-то вроде
usWordBuf = ucCoilsBuf[ usByteOffset ] << BITS_UCHAR;
usWordBuf != ucCoilsBuf[ usByteOffset + 1 ];

Аналогично для записи. Т.е. можно выйти за границы. Возможно, ничего и не произойдёт, но как-то неуютно :)
дополнил записью
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;
}

Sign up to leave a comment.

Articles

Change theme settings