Получение шестнадцатеричных данных с терминала

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

Я пытался написать это двумя разными способами, но ни один из них не сработал.

Первая попытка:

byte thisByte[]={0xAA, 0xBB, 0x06, 0x00, 0x00, 0x00, 0x01, 0x01, 0x03, 0x03};
void setup()
{
  // запуск последовательного порта со скоростью 9600 бит/с:
  Serial.begin(9600);
}

void loop()
{
  while (Serial.available())
  {
    delay(250);
    // получить новый байт:
    byte thisByte = Serial.read();
    // добавьте его во входную строку:
    //inputString += символ (intChar);

    if(thisByte == 0x03 || thisByte == 0x03)
    {
      Serial.print(thisByte, 'Hello');
      // digitalWrite (13, ВЫСОКИЙ); // включите светодиод (ВЫСОКИЙ - уровень напряжения)
      delay(50);             // подождите секунду
      Serial.print(thisByte, 'Nothing');
      // digitalWrite (13, НИЗКИЙ); // выключите светодиод, установив низкое напряжение
    }
    Serial.print(thisByte,HEX);
    Serial.print(" | ");
  }
}

Вторая попытка:

постоянное байтовое сообщение[]={0xAA, 0xBB, 0x06, 0x00, 0x00, 0x00, 0x01, 0x01, 0x03, 0x03};
найдено логическое значение = false;

байт byte1 = 0xAA;
байт byte2 = 0xBB;
байт byte3 = 0x06;
байт byte4 = 0x00;
байт byte5 = 0x00;
байт byte6 = 0x00;
байт byte7 = 0x01;
байт byte8 = 0x01;
байт byte9 = 0x03;
байт byte10 = 0x03;

постоянный байт Привет;
//недействительные правила();
настройка void() {
  // поместите сюда свой установочный код, чтобы запустить его один раз:
  Serial.begin (9600);
}

void loop() {
  // поместите сюда свой основной код для повторного запуска:
  // поместите сюда свой основной код для повторного запуска:
  //int hexIn = Serial.read();
  //Serial.write(сообщение, 2);
  //Serial.write(сообщение,sizeof(сообщение));
  //задержка (500000);
  пока(Serial.available())
  {
    delay(10); //небольшая задержка для заполнения входного буфера
    байт c = Последовательный.чтение();
    байтовое сообщение = c;

    //Serial.print(c,ШЕСТНАДЦАТЕРИЧНЫЙ);
    //Serial.print (" | ");

    //если (c =!байт 0xAA && c =!байт 1 0xAA && c =!байт 0xAA && c =!байт 0xAA && c =!байт 0xAA && c =!байт 0xAA && c =!байт 0xAA && c =!байт 0xAA && c =!байт 0xAA && c =!байт 0xAA);

    если (c == сообщение);
    //Serial.print("Я получил: ");
    Serial.println(c);

    // байт c = Serial.read(); // получает один байт из последовательного буфера
    // readmessage += c;
  } //делает строку ReadString читаемой
  //Serial.print(сообщение);
  //ReadString=""; //очищает переменную для нового ввода
}

, 👍1

Обсуждение

Что именно вводится в последовательную консоль? Вы вводите буквальное значение "0x03" или что-то подобное? Или вы каким-то образом вводите 8-битное значение 0x03?, @jose can u c

Я хочу, чтобы данные были шестнадцатеричными ... я не думаю, что вы понимаете, что на самом деле означает hex, @jsotola

что означает правильный ответ? ... пока только вы знаете , что ожидаете увидеть ... нам тоже нужно знать, прежде чем мы сможем вам помочь., @jsotola

Спасибо вам за ваш ответ. Я предоставлял данные с терминала, но не такие, как 0x03. Но AA BB 00 03 так. Но теперь ваш код дал мне представление о том, как это работает. Еще раз спасибо, @Gaurav Wagh

Плюс еще одна вещь, о которой я хотел вас спросить, это то, что я пытаюсь отправить пакет данных полностью, а не один байт. Итак, что я на самом деле хочу сделать или моя работа, например: 0xAA, 0xBB, 0x06, 0x00, 0x00, 0x00, 0x01, 0x01, 0x03, 0x03, @Gaurav Wagh

Плюс еще одна вещь, о которой я хотел вас спросить, это то, что я пытаюсь отправить пакет данных полностью, а не один байт. Итак, что я на самом деле хочу сделать или моя работа заключается в том, чтобы, например: 0xAA, 0xBB, 0x06, 0x00, 0x00, 0x00, 0x01, 0x01, 0x03, 0x03 данные в 8-й и 10-й позиции / байт изменялись. Но чего я не могу понять, так это того, как проверить их и получить обратную связь об измененных байтах. На самом деле это выходы с дисплея на arduino. Пожалуйста, если вы можете просто дать мне идею или какую-то помощь, чтобы написать ее. Заранее спасибо, @Gaurav Wagh


1 ответ


2

Во-первых, вы должны понять, что означает “hex”. По сути, вы представляете двоичные данные в виде текста, где каждый байт представлен в виде двух символов. Например, число 42 представлено либо как “2A” , либо как “2a". В C и C ++ вы можете записать это число как 0x2a, но я предполагаю , что ваш последовательный поток отправляет необработанные шестнадцатеричные данные без префикса “0x”. Таким образом, в последовательном потоке вы можете получить символ “2” ( код символа 0x32 = 50 в десятичной системе счисления), за которым некоторое время спустя следует “a” (код символа 0x61 = 97).

Что вам нужно, так это процедура преобразования, которая берет эти символы и восстанавливает из них двоичные данные. Вот одна из таких процедур, которую я использую. Вы должны предоставить ему входную строку in и выходной массив out, достаточно большой для хранения результирующих двоичных данных. Функция вернет количество байтов, заполненных в *size:

/*
 * Преобразование шестнадцатеричной строки в двоичную. Между байтами допускаются пробелы.
 * Предполагается, что выходной массив должен быть достаточно большим.
 * При возврате *size - это размер массива байтов.
 */
static void hex2bin(uint8_t *out, const char *in, size_t *size)
{
    size_t sz = 0;
    while (*in) {
        while (*in == ' ') in++;  // пропускать пробелы
        if (!*in) break;
        uint8_t c = *in>='a' ? *in-'a'+10 : *in>='A' ? *in-'A'+10 : *in-'0';
        in++;
        c <<= 4;
        if (!*in) break;
        c |= *in>='a' ? *in-'a'+10 : *in>='A' ? *in-'A'+10 : *in-'0';
        in++;
        *out++ = c;
        sz++;
    }
    *size = sz;
}

Для простого удобства приведенная выше функция принимает пробелы внутри строки, но только между байтами. Обратите внимание, однако, что он не пытается выполнить какую-либо проверку ошибок. Возможно, вы захотите улучшить его в этом отношении.

Далее вам нужно придумать способ размещения ваших сообщений в последовательной строке. Serial не обеспечивает никакого кадрирования как такового: он передает только байт один за другим. При работе с текстом обычной схемой является отправка возврата каретки (\r) для указания конца сообщения. Согласно этому соглашению, ваш скетч должен буферизировать байты, которые он получает, до тех пор, пока не увидит возврат каретки. Затем он может обработать все сообщение целиком. Этот подход хорошо объяснен в сообщении в блоге. Serial на Arduino, автор Majenko, постоянный участник этого сайта.

Вот пример, который считывает шестнадцатеричную строку, преобразует ее в двоичную, а затем снова отправляет ее обратно в шестнадцатеричном виде:

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

void loop()
{
    static char buffer[1024];
    static size_t length = 0;

    if (Serial.available()) {
        char c = Serial.read();

        // При возврате каретки обработайте полученные данные.
        if (c == '\r') {
            Serial.println();  // echo

            // Правильно завершите строку.
            buffer[length] = '\0';

            // Преобразуйте шестнадцатеричные данные в массив байтов.
            size_t byte_count = length/2;
            uint8_t data[byte_count];
            hex2bin(data, buffer, &byte_count);

            // Эхо возвращает массив байтов в шестнадцатеричном формате.
            for (size_t i = 0; i < byte_count; i++) {
                Serial.print(data[i], HEX);
                Serial.print(" ");
            }
            Serial.println();

            // Сбросьте буфер для следующей строки.
            length = 0;
        }

        // В противном случае буферизуйте входящий байт.
        else if (length < sizeof buffer - 1) {
            Serial.write(c);  // echo
            buffer[length++] = c;
        }
    }
}

Обратите внимание на строки с комментарием “echo”: они предназначены для того, чтобы помочь вам увидеть в терминале то, что вы вводите. Вы можете удалить их, если вы не хотите, чтобы Arduino повторял ваш ввод. Я проверил это, отправив

AA bb06 000000 0101 03 03

и оно ответило

AA BB 6 0 0 0 1 1 3 3 
,

Большое вам спасибо за ваш ответ. Это сработало действительно хорошо. Я постараюсь больше писать на эту тему, чтобы полностью понять ее., @Gaurav Wagh