HEX to DEC

vank
Offline
Зарегистрирован: 26.10.2017

Как можно преобразовать HEX в  DEC число?
Примерно:
HEX 7E007A88D2 в DEC 541173909714

nik182
Offline
Зарегистрирован: 04.05.2015

На калькуляторе в режиме программиста.

b707
Offline
Зарегистрирован: 26.05.2017

отличный вопрос для раздела "Программирование"

А умножить 2 на 3 никому не надо? - а то я умею

Voodoo Doll
Voodoo Doll аватар
Offline
Зарегистрирован: 18.09.2016

vank,

взять первый знак в HEX

если 0-9 то скопировать как есть

Если A-F то прибавить 10, нутыпонел A=10, B=11, F=15 (мне это удалось запомнить что есть самолёт такой F-15, единственный который мне удавалось посадить в игрульке под DOS)

удалить то что брали из HEX

если чото осталось то умножить то что получилось в DEC на 16 и т. д.

пока не кончится (подсказка: цикл while).

nik182
Offline
Зарегистрирован: 04.05.2015

Эх. А если в HEX знаков 30? Никакой разрядности не хватит персчитать. Да и ТС не написал где ему надо это делать. Если в программе, которая введеный HEX должна в DEC перекинуть и вывести на экран, то если в разрядность long long укладывается, то проще собрать строку HEX, перевести её в  uint_t и напечатать DEC. Не хватает исходных данных, что бы понять где, что и как собирается конвертить ТС. 

DetSimen
DetSimen аватар
Онлайн
Зарегистрирован: 25.01.2017

если HEX у тебя в строковом представлении, то strtol(...) тебя спасёть. 

https://www.microchip.com/webdoc/AVRLibcReferenceManual/group__avr__stdlib_1gaf8ce3b8dae3d45c34c3b172de503f7b3.html

anatoli_nik
Offline
Зарегистрирован: 17.01.2019

Может нужно HEX в BCD перевести..

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Вообще-то нет HEX или DEC чисел. Есть лишь различные способы текстовой записи этих чисел.

Соответственно, если требуется одно текстовое представление числа заменить на другое, то нужно выполнить преобразование текста в число, а затем - обратно, но по другому основанию.

vank
Offline
Зарегистрирован: 26.10.2017

Я хочу читать RFID.
Я использую RFID модуль RDM6300 125kHz, UART
и Arduino Uno
Карты HEX номер 7E007A88D2, и я хочу, чтобы прочитать его
DEC номер 541173909714.
Я прочитал HEX 7E007A88D2. Преобразовать его в 541173909714DEC.
Я хочу, чтобы это число вывело на терминал
Я использую следующую часть программы:

long long x = 541173909714LL;  // note the double LL

void setup()
{
 Serial.begin(115200);
 Serial.println("I am Arduino");
 char buffer[100];
 sprintf(buffer, "%0ld", x/1000000L);
 Serial.print(buffer);  
 sprintf(buffer, "%0ld", x%1000000L);
 Serial.println(buffer);  
}

void loop() {}

Сначала нужно вывести число 541173
А потом 909714.

Но не работает.
Если у кого-то есть целая программа для тов, пожалуйста, помогите!

nik182
Offline
Зарегистрирован: 04.05.2015

Странно. У меня на блюпиле отработало. Написало то что ожидалось. А на нане вот это

long long x = 0x7E007A88D2; //541173909714LL;  // note the double LL

void setup()
{
 Serial.begin(115200);
 Serial.println("I am Arduino");
 char buffer[100];
 sprintf(buffer, "%0ld", x/1000000L);
 Serial.print(buffer);  
 sprintf(buffer, "%0ld", x%1000000L);
 Serial.println(buffer);  
 sprintf(buffer, "%0ld", (long)x);
 Serial.println(buffer); 
 Serial.println((long)x); 
 Serial.print( (long) (x/1000000L) );
 Serial.println( (long) (x%1000000L));
}
void loop (){};

 Перевело HEX в DEC и дало вывод сразу без использования буфера и sprinf.

I am Arduino
541173909714
8030418
8030418
541173909714
 
vank
Offline
Зарегистрирован: 26.10.2017

Большое спасибо @ник182
У меня теперь другая проблема.
Когда я читаю данные карты, я записываю их в стринг.
Я могу записать их в стринговом массиве.
Я не знаю, как преобразовать их в число HEX, чтобы использовать это приложение.
Я применяю свой код.

Я прошу прощения, но я новичок в Ардуино и С


#include <SoftwareSerial.h>
SoftwareSerial rdm6300(2, 3); // pin RX and pin TX

String s = "";

void setup()
{
  rdm6300.begin(9600); // SoftwareSerial to RFID reader
  Serial.begin(9600);  // serial (UART)  to computer
}

void readCard()
{
  if (rdm6300.available() > 0)
  {
    delay(100);
    char c = rdm6300.read();  //
    for (int i = 0 ; i < 10 ; i++)
    {
      char c = rdm6300.read();
      s = s + c;
      delay(10);
    }
    Serial.println(s);
    
//  здесь надо преобразовать стринг в HEX

	s = "";

    while (rdm6300.available() > 0)
    {
      rdm6300.read();
    }
  }
}
void loop()
{
  readCard();

}

 

nik182
Offline
Зарегистрирован: 04.05.2015

Дед в #5 всё дал.

b707
Offline
Зарегистрирован: 26.05.2017

vank - задержки в 16 и 22 строках уберите, с ними работать не будет.

Непонятно, зачем вы сначала переводите номер карты во стринг, если потом имеете проблему с преобразованием обратно... так не переводите.

vank
Offline
Зарегистрирован: 26.10.2017

Спасибо.
Я читал в интернете, но не могу этого сделать.
Если вы можете мне помочь.
Например, как я дал в предыдущем посте.
String s = = "7E007A88D2"
я хочу получить
long long x = 0x7E007A88D2

Спасибо за помощь!

vank
Offline
Зарегистрирован: 26.10.2017

@b707 Как Вы предлагаете это сделать?

b707
Offline
Зарегистрирован: 26.05.2017

vank пишет:

@b707 Как Вы предлагаете это сделать?

что именно?

vank
Offline
Зарегистрирован: 26.10.2017

@b707

b707 пишет:

Непонятно, зачем вы сначала переводите номер карты во стринг, если потом имеете проблему с преобразованием обратно... так не переводите.

b707
Offline
Зарегистрирован: 26.05.2017

посмотрел - был неправ, у вас RFId c UART интерфейсом, он HEX в текстовом виде выдает. Тогда да - в сообщении #5 вам дали наводку, как преобразовывать

vank
Offline
Зарегистрирован: 26.10.2017

Я сожалею, но я не знаю, как это сделать.
Если вы можете помочь!

b707
Offline
Зарегистрирован: 26.05.2017

vank пишет:

Я сожалею, но я не знаю, как это сделать.
Если вы можете помочь!

посмотрите вот эту ссылку

https://www.mschoeffler.de/2018/01/05/arduino-tutorial-how-to-use-the-rdm630-rdm6300-rfid-reader/

там есть код, а в конце кода функция hexstr_to_value() - это именно то, что вам нужно

 

vank
Offline
Зарегистрирован: 26.10.2017

Спасибо.
Я читал эту статью!.
Проблема во мне, что я хочу вывести длинный код.
Здесь выводится короткий код.
Например:
На карте записано: 7E007A88D2
И я хочу вывести монитор: 541173909714

nik182
Offline
Зарегистрирован: 04.05.2015

Это не проблема. Примите уже мысль, что это одно и то же число. Не надо его ни как преобразовывать в представлении МК. Как бы Вы не скормили его МК в его внутреннем представлении всё равно это будет двоичное число. То, что Вы видите на экране это текстовое представление. Оно может быть НЕХ, DEC, OCT, BIN - это основные виды представлений, для которых написаны конверторы и которые можно использовать не напрягаясь на писание своих программ. Дед в #5 привел пример такой функции. Если ей скормить строку символов содержащую представление числа, то она пребразует эту строку во внутренее двоичное предеставление и присвоит переменной. Дальше значение этой переменной можно вывести на экран в любом представлении. 

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

Должен заметить, что у ТС число из 5 байтов. Следовательно в long Ардуины не помещается. А для long long нет метода print. Написать его ничего не стоит, но не для ТС ;))))))

nik182
Offline
Зарегистрирован: 04.05.2015

Ну так его обходят методом печати половинок long long. 

b707
Offline
Зарегистрирован: 26.05.2017

nik182 пишет:

Ну так его обходят методом печати половинок long long. 

не только :)

Я пока искал для ТС ссылки - нашел как минимум три библиотеки ардуино для такого RFID - разной степени кривизны. Там авторы как только не изгаляются - один честно выводит только четыре байта, другой выводит больше, но читает реально тоже только четыре, а дальше добивает нулями :) только один из троих читает и выводит UID полностью

vank
Offline
Зарегистрирован: 26.10.2017

Привет!
Я выполнил свою задачу, используя специальную библиотеку для RDM6300.
Но я хочу понять, как превратить стринг в число.
Я не мог этого сделать. Я пробовал следующее, Но это не сработало.
Может ли кто-нибудь помочь мне-с учебной целью.

 long long l =  strtoul("0x7E007A88D2",NULL, 0);
 Serial.print( (long) (l/1000000L) );
 Serial.println( (long) (l%1000000L));

 получаю 4294967295  а надо 541173909714

sadman41
Онлайн
Зарегистрирован: 19.10.2016

Не сработало потому что : unsigned long int strtoul (const char* str, char** endptr, int base);

vank
Offline
Зарегистрирован: 26.10.2017

Снова так:


void setup()
{
 
 unsigned long int strtoul ("0x7E007A88D2",NULL, 0);
 Serial.print( (long) (l/1000000L) );
 Serial.println( (long) (l%1000000L));

}
void loop (){};

получаю 4294967295  а надо 541173909714

 

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

vank пишет:

Снова так:

;))))))))))

Видимо вечер пятницы удался?

b707
Offline
Зарегистрирован: 26.05.2017

vank - вместо того чтоб искать библиотеки, написанные криворукими программистами - вы бы лучше потратили время на чтения учебника по языку. Судя по всему, все ваше "решение задачи" заключается в копи-пасте стандартного примера. А то что вы тут пытаетесь писать сами для преобразования числа - чушь несусветная

vank
Offline
Зарегистрирован: 26.10.2017

Спасибо за комментарий.
Я сделал это для с++, но я не мог сделать это для Ардуино.
и я не знаю, сможет ли  вообще.
Вот почему я так заинтересован.
Ардуино-мое хобби. Мне 62 года, и я делаю все для удовольствия.
Вот почему я так много спрашиваю.
Простите, если я кого-то обидел своими вопросами.

b707
Offline
Зарегистрирован: 26.05.2017

vank пишет:

Я сделал это для с++, но я не мог сделать это для Ардуино.

не хорошо врать, особенно в 62 года.

Сможете продемонстрировать свое решение для С++ ?

vank
Offline
Зарегистрирован: 26.10.2017

@b707 пишет: Сможете продемонстрировать свое решение для С++ ?

#include <stdlib.h>
#include <stdio.h>

int main(void)
{
   char *string, *stopstring;
   long long l;

      l = strtoll("7E007A88D2", NULL, 16);
      printf("STRING = %s \n", "7E007A88D2");
      printf("DEC    = %lld \n", l);
 }

и

#include <iostream>

using namespace std;

int main()
{
    char str1[] = "7E007A88D2";
    unsigned long l =  strtoul(str1, NULL, 16);
    cout<< "7E007A88D2" <<endl;
    cout<<  l <<endl;
   
    return 0;
}

 

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

ну если 62, то круто. Мне 50, я напишу тебе этот кусочек завтра... сегодня нельзя... ;))))

vank
Offline
Зарегистрирован: 26.10.2017

@wdrakula

Спасибо.
Да я набор 1957.

b707
Offline
Зарегистрирован: 26.05.2017

vank пишет:

@b707 пишет: Сможете продемонстрировать свое решение для С++ ?

простите, но вынужден повторить - стыдно врать в 62 года. То что вы приводите как свой код - вы явно скопипастили в интернете  без малейшего понимания. Было бы это ваше - вы бы не написали той чуши. что у вас в сообщении #27

Для справки - Ардуина программируется на языке С++, если вы можете решить задачу на С++ - можете и в ардуино

DetSimen
DetSimen аватар
Онлайн
Зарегистрирован: 25.01.2017

strtol() в AVR GCC возвращает uint32_t, т.е всего 4 байта максимум.  strtoll() у AVR нет.  

мошт тебе надо разбить сначала твой uint64_t  на два uint32_t?

sadman41
Онлайн
Зарегистрирован: 19.10.2016

Так у него и uint64-то не выходит получить. 

Может я avrlib не до конца еще дочитал, но, кажется, нет там требуемых функций, оперирующих long long. Или свое изобретать надо или библиотеку rfid-а менять / править.

PS. вижу, уже выяснили, что девайс в HEX-string выдает ID. Тогда в чем проблема при шифтовании long long влево и докладывании в него очередного ниббла?

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

Вот, как бы обещал. Всё иллюстративно и "на коленке".

Десятичный вид не напечатает весь диапазон. Это тебе "домашнее задание". ;))

const char myHex[] = "0x987654ABCD";

void setup() {
  Serial.begin(57600);

  uint64_t myVal = 0;
  byte strPtr = 0;

  if ( myHex[strPtr] == '0'
       && myHex[strPtr + 1] == 'x'
       || myHex[strPtr + 1] == 'X') {
    strPtr += 2;
  }

  byte isDone = false;
  while (! isDone) {
    char ch = myHex[strPtr];
    switch (ch) {
      case '0'...'9': myVal = (myVal << 4) + ch - '0'; break;
      case 'a'...'f': myVal = (myVal << 4) + ch - 'a' + 10; break;
      case 'A'...'F': myVal = (myVal << 4) + ch - 'A' + 10; break;
      default: isDone = true;
    }
    // Это печать для иллюстрации того, что происходит ;))
    Serial.print((int)strPtr);
    Serial.print("  ");
    Serial.print(ch);
    Serial.print("  ");
    Serial.print((long)(myVal>>32), HEX);
    Serial.print((long)myVal, HEX);
    Serial.println();

    if (!isDone) strPtr++;
  }
  Serial.print("Сначало было слово:");
  Serial.println(myHex);

  Serial.println("Потом появилось число:");
  Serial.print("0x");
  Serial.print((uint32_t)(myVal >> 32), HEX);
  Serial.print((uint32_t)(myVal), HEX);
  Serial.println("  HEX");
  Serial.print((uint32_t)(myVal / 1000000), DEC);
  Serial.print((uint32_t)(myVal % 1000000), DEC);
  Serial.println("  DEC");

}

void loop() {


}

 

Green
Offline
Зарегистрирован: 01.10.2015

Без 0x, только заглавные).
 

uint64_t hex2ll(char *str)
{ 
  uint64_t result = 0; 
  for (int i = 0; str[i]; ++i) 
    result = (result<<4) + (str[i] <= '9' ? str[i] - '0' : str[i] - 'A' + 10); 
  return result; 
} 

 

DetSimen
DetSimen аватар
Онлайн
Зарегистрирован: 25.01.2017

    result = (result<<4) + (str[i] <= '9' ? str[i] - '0' : toupper(str[i]) - 'A' + 10);

Green
Offline
Зарегистрирован: 01.10.2015

Да, но у него там всё равно заглавные.

DetSimen
DetSimen аватар
Онлайн
Зарегистрирован: 25.01.2017

Green пишет:

Да, но у него там всё равно заглавные.

Сегодня да. А зафтра?:-)

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

DetSimen пишет:

Green пишет:

Да, но у него там всё равно заглавные.

Сегодня да. А зафтра?:-)

Пусть ТС сам мозг включит.

vank
Offline
Зарегистрирован: 26.10.2017

Уважаемый @wdrakula
Спасибо за программу, которую вы отправили.
Очень красиво и подробно вы все написали.
Я положил мой стринг "0х"7E007A88D2""
и теряются две нули.
Вот ответ на монитор:

2  7  07
3  E  07E
4  0  07E0
5  0  07E00
6  7  07E007
7  A  07E007A
8  8  07E007A8
9  8  07E007A88
10  D  7E007A88D
11  2  7E7A88D2
12     7E7A88D2
Сначало было слово:0x7E007A88D2
Потом появилось число:
0x7E7A88D2  HEX
541173909714  DEC

Это потому, что две нули находятся в начале и являются
незначительными нулями, и программа игнорирует их. Правда?

Но, наконец, ответ верный 541173909714
Для меня было очень полезно посмотреть, как все происходит шаг за шагом.
Еще раз спасибо, что помогли мне!

vank
Offline
Зарегистрирован: 26.10.2017

Уважаемый @Green и @DetSimen
Большое спасибо за вашу программу.
Она также прекрасно работает
 

const char str[] = "7E007A88D2";

void setup() {
  Serial.begin(57600);

  uint64_t result = 0;
  for (int i = 0; str[i]; ++i)
    result = (result<<4) + (str[i] <= '9' ? str[i] - '0' : toupper(str[i]) - 'A' + 10);

  
  Serial.print((uint32_t)(result / 1000000), DEC);
  Serial.print((uint32_t)(result % 1000000), DEC);
  Serial.println("  DEC");

}

void loop() {}

Большое спасибо за помощь всем!
 

Green
Offline
Зарегистрирован: 01.10.2015

vank пишет:
Это потому, что две нули находятся в начале и являются

незначительными нулями, и программа игнорирует их. Правда?

Без привязки к Ардуино:
 

void displayBinary(uint64_t bin, uint64_t div)
{
  char chr = ' ';
  for ( ; div > 1; div /= 10) {
    if (chr != ' ' || bin / div)
      chr = bin / div + '0';
    Serial.write(chr);
    bin %= div;
  }
  Serial.write((uint8_t)bin + '0');
}

 displayBinary(bin,100000000000); 

 

itehno
Offline
Зарегистрирован: 18.04.2015

А вот мой способ: (как пример)

String inputString = "";                    // Строка, в которую будут записываться входящие данные
boolean stringComplete = false;             // Заполнилась ли строка или нет
int16_t r = 0;
int16_t g = 0;
int16_t b = 0;

void setup() {
  Serial.begin(9600);
  inputString.reserve(200); // «Бронируем» 200 байт для inputString:
}

void loop() {
  newString();
}


int Hex2Str(String s){ // Перевод HEX в int
  return strtol(s.c_str(), 0, 16);
}

void newString() {
  if (stringComplete) { // Если прибыл символ новой строки, показываем строку:
    Serial.println(inputString);
    
  if ((inputString.indexOf("RGB:")==0)){        // Проверка, что начинается с заголовка RGB:
    if (inputString.length() >=10 ){            // Количество символов в запросе = 10 (RGB:000000)
      r = Hex2Str(inputString.substring(4,6));  // Вычленяем 2 символа после двоеточия (5 и 6)
      g = Hex2Str(inputString.substring(6,8));  // Вычленяем 2 символа после двоеточия (7 и 8)
      b = Hex2Str(inputString.substring(8,10)); // Вычленяем 2 символа после двоеточия (9 и 10)
    }
  }

    inputString = ""; // очищаем строку:
    stringComplete = false;
  }
}

void serialEvent() {
  while (Serial.available()) {
    char inChar = (char)Serial.read();        // получаем новый байт:
    inputString += inChar;                    // добавляем его к inputString:
    if ((inChar == '\n') || (inChar == 0)) {  // если получили символ новой строки, оповещаем программу об этом, чтобы она могла принять дальнейшие действия.
      stringComplete = true;
    }
  }
}

 

ua6em
ua6em аватар
Онлайн
Зарегистрирован: 17.08.2016

DetSimen пишет:

    result = (result<<4) + (str[i] <= '9' ? str[i] - '0' : toupper(str[i]) - 'A' + 10);

Дед, вот чувствуется, что написание программ ты начинал с функции обработчика ошибок )))

vank
Offline
Зарегистрирован: 26.10.2017

Привет!
Можно использовать библиотеку PriUint64.h
https://github.com/yoursunny/PriUint64

#include <PriUint64.h>

  void setup() 
{
  Serial.begin(9600);
  Serial.println();

  uint64_t x = 0x7E007A88D2;
  Serial.println(PriUint64<HEX>(x));
  Serial.println(PriUint64<DEC>(x));
  Serial.println(PriUint64<OCT>(x));
  Serial.println(PriUint64<BIN>(x));

  Serial.println();

  uint64_t y = 541173909714;
  Serial.println(PriUint64<HEX>(y));
  Serial.println(PriUint64<DEC>(y));
  Serial.println(PriUint64<OCT>(y));
  Serial.println(PriUint64<BIN>(y));
}

void loop() {}

Ответ

7E007A88D2
541173909714
7700036504322
111111000000000011110101000100011010010

7E007A88D2
541173909714
7700036504322
111111000000000011110101000100011010010