MODBUS TCP ответ конвертировать в плавающий C ++ - PullRequest
0 голосов
/ 10 октября 2011

У меня проблема. У меня есть ответ MODBUS TCP, который в шестнадцатеричном формате выглядит следующим образом: 0 0 0 0 0 7 1 4 4 41 B8 66 64. Для пояснения: первые пять нулей - это спецификация Modbus, 7 - это количество байтов следуя за ним. 1 - это адрес клиента в сети Modbus и не имеет значения. первые 4 - это код функции, который используется. вторая 4 - это число следующих байтов. Последние четыре байта - это шестнадцатеричный ответ, который следует преобразовать в двойной. Массив, в котором это хранится, является массивом без знака. Вот несколько примеров, как я это попробовал. Вот первый пример:

value = (ibuf[9]<<24) + (ibuf[10]<<16) + (ibuf[11]<<8) + ibuf[12];

Значение - используемая переменная типа double и ibuf используемого массива char. Вот второй:

for(i = 0; i < k; i++)
{
    if (i==0)
    {
        sprintf(ergebnis, "%x%x", ibuf[9], ibuf[10]);
    }
    else
    {
        //sprintf(buffer,"%x%x",ibuf[9+i+i], ibuf[10+i+i]);
        //strcat( ergebnis, buffer );
        sprintf(ergebnis, "0x41b451e8");
        sscanf(ergebnis, "%l %lf ", &Value);
    }
    printf("Ergebnis %s\n", ergebnis);
}

Здесь я использовал фиксированное значение, но проблема всегда в преобразовании из шестнадцатеричного в двойное. Я рад любой помощи, которую я мог получить.

Ответы [ 2 ]

2 голосов
/ 10 октября 2011

Ты почти у цели.К сожалению, преобразование происходит автоматически во время продвижения по службе - самый «простой» способ обойти это - разыменовать указатель с плавающей точкой на тип int, например:

int ival = (ibuf[9]<<24)+(ibuf[10]<<16)+(ibuf[11]<<8)+ibuf[12];
float fval = *(float*)&ival;

Для предоставленных данных это дает 23.049995 вместо1.1026039e + 009, который вы получаете из конверсии.

РЕДАКТИРОВАТЬ:

Как отметил Майк Сеймур в комментарии ниже, предпочтительный способ написать это:

float fval = *reinterpret_cast<float*>(&ival);

Обратите внимание, что вы не можете сделать это:

float fval = reinterpret_cast<float>(ival);

Это вызовет ошибку (как показано здесь в VS2005):

error C2440: 'reinterpret_cast' : cannot convert from 'int' to 'float'
0 голосов
/ 10 октября 2011

Я бы использовал побитовый или оператор для воссоздания значения с плавающей запятой.

unsigned int value = 0x00000000 | ibuf[9]  << 24
                                | ibuf[10] << 16
                                | ibuf[11] << 8
                                | ibuf[12];
float floatValue = (float)value;

В этом коде предполагается, что unsigned int имеет размер четыре байта на вашей платформе.

...