Преобразование 32-битного шестнадцатеричного значения со знаком в десятичное
Использование CAN-щита Seed Studio для чтения и преобразования данных CAN в десятичное значение.
Пример ожидаемого результата:
Полное сообщение CAN равно 70 3B F1 FF 00 00 00 00 , с использованием первых 4 байтов с прямым порядком байтов получается: FFF13B70 , что должно быть равно преобразованному десятичному значению -0,967824 (с использованием коэффициента 0,000001).
Вот код для извлечения текстового значения, которое я использую.
CAN.readMsgBuf(&len, buf);
unsigned char len = 0;
unsigned char buf[8];
{
String reg0 = String (buf[0], HEX);
String reg1 = String (buf[1], HEX);
String reg2 = String (buf[2], HEX);
String reg3 = String (buf[3], HEX);
Serial.print(reg3);
Serial.print("\t");
Serial.print(reg2);
Serial.print("\t");
Serial.print(reg1);
Serial.print("\t");
Serial.print(reg0);
Serial.print("\t");
String regsumm = (reg3 + reg2 + reg1 + reg0);
Serial.println(regsumm);
}
В результате я получил только текстовую строку, которую невозможно преобразовать в dec. Есть еще способы как это сделать?
@richard, 👍0
2 ответа
Вы выбрали совершенно неверный путь. Вы не хотите конвертировать данные в текст, а затем снова конвертировать их в данные — это уже данные.
Вы можете объединить первые четыре байта буфера в одно 32-битное целое число со знаком всего лишь:
int32_t val = ((int32_t)buf[3] << 24) | ((int32_t)buf[2] << 16) |
((int32_t)buf[1] << 8) | (int32_t)buf[0];
Это дает вам значение -967824, которое равно 0xFFF13B70 в шестнадцатеричном формате или 11111111 11110001 00111011 0111000
в двоичном формате. Все они одно и то же и представляют собой просто числа.
Затем вы можете умножить этот результат на свой «коэффициент» в переменную с плавающей запятой:
float dec = val * 0.000001;
Скорее всего, он не даст вам -0,967824 из-за природы значений с плавающей запятой, поэтому вам лучше оставить его как -967824 и работать в «микроединицах», а не в «единицах».
>Поскольку байты, полученные вами в буфере, имеют прямой порядок байтов,
и ваш Uno сам по себе имеет прямой порядок байтов, вам даже не нужно перемещать байты
вокруг: вы можете просто переосмыслить уже имеющиеся у вас байты как
int32_t
:
union {
uint8_t bytes[8];
int32_t numbers[2];
} buffer;
unsigned char len = 0;
CAN.readMsgBuf(&len, buffer.bytes);
Serial.println(buffer.numbers[0] * 1e-6, 6);
Это выведет -0.967824
на последовательный порт.
Обратите внимание, что этот код не будет работать должным образом на платформе с прямым порядком байтов. Если вам нужно что-то портативное, обычное решение — создать результат с использованием битовых сдвигов, как в ответе Маженко.
- Как использовать SPI на Arduino?
- Как решить проблему «avrdude: stk500_recv(): programmer is not responding»?
- Как создать несколько запущенных потоков?
- Как подключиться к Arduino с помощью WiFi?
- avrdude ser_open() can't set com-state
- Как узнать частоту дискретизации?
- Что такое Serial.begin(9600)?
- Я закирпичил свой Arduino Uno? Проблемы с загрузкой скетчей на плату
Комментарии не предназначены для расширенного обсуждения; этот разговор был [перенесен в чат](https://chat.stackexchange.com/rooms/87212/discussion-on-answer-by-majko-converting-of-32-bit-signed-hex-value-to- декабрь)., @Majenko