Читаю через библиотеку (github.com/adduc/phpmodbus) и есть эта функция для преобразования целых чисел в последовательность байтов с прямым порядком байтов или с прямым порядком байтов:
private static function endianness($value, $endianness = 0) {
if ($endianness == 0)
return
self::iecBYTE(($value >> 8) & 0x000000FF) .
self::iecBYTE(($value & 0x000000FF)) .
self::iecBYTE(($value >> 24) & 0x000000FF) .
self::iecBYTE(($value >> 16) & 0x000000FF);
else
return
self::iecBYTE(($value >> 24) & 0x000000FF) .
self::iecBYTE(($value >> 16) & 0x000000FF) .
self::iecBYTE(($value >> 8) & 0x000000FF) .
self::iecBYTE(($value & 0x000000FF));
}
iecBYTE
функция просто chr($value & 0xFF)
,
Теперь, может быть, я толстая, но строка с прямым порядком байтов выглядит неправильно.
Например, с 0xAABBCCDD
, вы получите {CC}{DD}{AA}{BB}
,
Я даже посмотрел это в Википедии. Не должно ли это быть {DD}{CC}{BB}{AA}
?
Код работает хотя, что действительно смущает меня. Это правильно, и я неправильно понимаю?
Посмотрев на IECType.php, Я заметил, что это преобразование типов PHP в типы IEC 1131.
Little endian сначала хранит младшие байты. То, что вы описали, заставит меня думать, что система использует 16-битные адреса.
Если вы посмотрите на вики для Endianess, на который ссылаются в комментариях над функцией endianess, вы увидите раздел под Little-endian, называемый размером элемента Atomic 16-bit. Один адрес содержит два байта (CCDD) и (AABB). Адрес, содержащий (CCDD), является наименее значимым, поэтому он будет указан первым.
Если бы вы работали в 8-битной системе, то каждый байт был бы упорядочен (DDCCBBAA), потому что на адрес приходился один байт.
Вики описывает то, что вы видите в функции endianess.
address1 | Адрес 2 16 бит | 16 бит CCDD | ААББ
Ты прав. Функция не правильная, хотя и близкая. Похоже, вам просто нужно поменять несколько конверсий. Логически преобразование с прямым порядком байтов ($ endianness == 0) является просто инверсией преобразования с прямым порядком байтов ($ endianness! = 0).
private static function endianness($value, $endianness = 0) {
if ($endianness == 0) //little-endian
return
self::iecBYTE($value & 0x000000FF) .
self::iecBYTE(($value >> 8) & 0x000000FF) .
self::iecBYTE(($value >> 16) & 0x000000FF) .
self::iecBYTE(($value >> 24) & 0x000000FF);
else //big-endian
return
self::iecBYTE(($value >> 24) & 0x000000FF) .
self::iecBYTE(($value >> 16) & 0x000000FF) .
self::iecBYTE(($value >> 8) & 0x000000FF) .
self::iecBYTE(($value & 0x000000FF));
}