Отправить шестнадцатиричное HEX число по Serial

uart hex

У меня есть устройство RS232, с которым я могу связаться с помощью RealTerm на ПК с Windows.

Устройство ожидает шестнадцатеричную строку, например AA BB 03 01 03 EE


Как мне отправить эквивалентную строку с Arduino? (Я уверен, что Arduino подключен правильно, так как я вижу входящие данные uart)

Что я пробовал

void setup() {
  Serial.begin(9600); // открывает последовательный порт, устанавливает скорость передачи данных 9600 бит/с
}

void loop() {
      Serial.println('AA BB 03 01 01 EE', "OCT");
      delay(3000);
      Serial.println('0xAA 0xBB 0x03 0x01 0x01 0xEE', "DEC");
      delay(3000);
      Serial.println('AA BB 03 01 01 EE', "DEC");
      delay(3000);
      Serial.println('AA BB 03 01 01 EE', "DEC");
      delay(3000);
      Serial.println('AA BB 03 01 01 EE', "DEC");
      delay(3000);
      Serial.print('0xAA 0xBB 0x03 0x01 0x01 0xEE', "DEC");
      delay(3000);
      Serial.print('AA BB 03 01 01 EE', "DEC");
      delay(3000);
      Serial.print('AA BB 03 01 01 EE', "DEC");
      delay(3000);
      Serial.print('AA BB 03 01 01 EE', "DEC");
      delay(3000);
      Serial.println('AA BB 03 01 01 EE', HEX);
      delay(3000);
      Serial.println('0xAA 0xBB 0x03 0x01 0x01 0xEE', HEX);
      delay(3000);
      Serial.println('0xAA 0xBB 0x03 0x01 0x01 0xEE');
      delay(3000);
      Serial.println('0xAA 0xBB 0x03 0x01 0x01 0xEE', HEX);
      delay(3000);
      Serial.write('AA BB 03 01 01 EE');
      delay(3000);
      Serial.write('0xAA 0xBB 0x03 0x01 0x01 0xEE');
      delay(3000);
}

Я также пытался использовать двойные кавычки, как упоминалось в комментариях

     Serial.write("AA BB 03 01 01 EE");
     delay(3000);
     
     Serial.write("0xAA 0xBB 0x03 0x01 0x01 0xEE");
     delay(3000);

     Serial.write("101010101011101100000011000000010000000111101110");
     delay(2000);

Кроме того, я пробовал писать сериал построчно

  Serial.write(0xaa); // AA
  Serial.write(0xbb); // BB
  Serial.write(0x03); // 03
  Serial.write(0x01); // 01
  Serial.write(0x01); // 01
  Serial.write(0xee); // EE
  Serial.write(0x0d); // \r
  Serial.write(0x0a); // \n
  delay(3000);

Дополнительная информация

  • управление проектором с помощью Arduino
  • Добавление \r\n в шестнадцатеричный код, отправленный через Arduino

, 👍-1

Обсуждение

'AA BB 03 01 01 EE' Это многосимвольный литерал (отличается от строкового литерала) и не будет играть роли в вашем ответе. Я не знаю, имеет ли это отношение к вопросу. Если нет, вы, вероятно, хотели использовать здесь двойные кавычки., @timemage

Устройство ожидает шестнадцатеричную строку... первый снимок экрана показывает, что отправляются двоичные значения, а не строки... шестнадцатеричные числа представляют собой удобочитаемое представление двоичных значений, @jsotola

какую проблему вы видите?, @jsotola

Есть 2 проблемы. 1, как записать с помощью Serial.write(). 2. Как понять, что делает RealTerm, чего не делает arduino. Я зафиксирую это в другом вопросе (здесь этот вопрос очень похож на вторую проблему https://superuser.com/questions/245926/how-does-realterm-send-numbers), @spuder

Кроме того, я обнаружил, что ожидаемые значения, которые я отправляю по серийному номеру, не соответствуют полученным результатам. Почти точно идентично этой форме https://forum.arduino.cc/t/how-to-send-hexadecimal-value-to-serial-devices/138834/15, @spuder

Проблема заключалась в том, что я не использовал адаптер RS232-TTL. Однажды я добавил, что между ардуино и устройством были получены правильные значения., @spuder


2 ответа


Лучший ответ:

3

Как заметил jsotola в комментарии, ваше устройство, похоже, не ожидая HEX вообще, а скорее простой двоичный файл. Serial.print() не подходит, так как он предназначен для отправки текста ASCII. Для двоичных данных вы должны предпочесть Serial.write(). Точнее, для отправки произвольные двоичные данные, правильный метод

size_t Print::write(const uint8_t *buffer, size_t size)

Применение этого к вашему примеру дает:

const size_t packet_length = 6;
uint8_t packet[packet_length] = {0xaa, 0xbb, 0x03, 0x01, 0x03, 0xee};
Serial.write(packet, packet_length);
,

Благодарю вас! Это приближает меня, к сожалению, устройство все еще не отвечает. Когда я слежу за кабелем uart, я вижу, что передается "~ (которое преобразуется из ascii в 7E 22, @spuder

@spuder: Что-то не так с вашей настройкой или вашим последовательным сниффером. Я только что проверил свой код с помощью hd /dev/ttyACM0, и он отправляет предполагаемую последовательность., @Edgar Bonet

Я создал симулятор здесь: https://wokwi.com/projects/337371635280511572 При преобразовании в символ выводится «ª»î, что соответствует шестнадцатеричному «AABB030103EE». Итак, ваш код кажется логически правильным, но я чего-то не понимаю в своей ситуации., @spuder

@spuder: Ваша симуляция печатает «170 187 3 1 3 238» (без пробелов), что соответствует 0xaa, 0xbb, 0x03, 0x01, 0x03, 0xee., @Edgar Bonet

Теперь я понимаю, что "ª"î" - это юникод, "170 187 3 1 3 238" - двоично-десятичный, "AABB030103EE" - шестнадцатеричный. Я был сбит с толку, потому что разные терминалы по умолчанию используют разные форматы отображения (хотя под капотом это одно и то же значение)., @spuder

Я устанавливаю отладочный кабель обратной связи, чтобы увидеть результат. При использовании RealTerm я получаю «AA BB 03 01 03 EE», но при использовании Arduino я получаю «95 91 7E 7F 7E 04 00»., @spuder

Как только я использовал подходящий адаптер RS232-TTL между Arduino и устройством, последовательные значения начали передаваться правильно. Спасибо https://www.amazon.com/dp/B07BJJ1T5G?ref=ppx_yo2ov_dt_b_product_details&th=1, @spuder


0

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

byte sequence[]={0xAA, 0xBB, 0x03, 0x01, 0x01, 0xEE};
for(byte i=0; i<sizeof(sequence);i++) Serial.write(sequence[i]);

если вам нужно отправить его в виде HEX, то, скорее всего, дело в шестнадцатеричном представлении, и вы можете использовать для этого printf

Serial.printf("0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X", 0xAA, 0xBB, 0x03, 0x01, 0x01, 0xEE);

Другое мнение заключается в том, что вы должны быть осторожны при использовании println при обмене данными с другими устройствами. println добавляет дополнительный символ (число) для новой строки после данных, которые вы хотите отправить. если вы хотите отправлять только те данные, которые хотите отправить, используйте print вместо этого

Изменить: Спасибо за примечание от Эдгара Бонета, меня предупредили, что printf по-прежнему не является стандартной инструкцией за пределами ядра ESP. Его стоит добавить самостоятельно. Ищите руководство по Arduino Playground.

,

Ваш вызов Serial.printf() может быть упрощен как Serial.print("0xAA 0xBB 0x03 0x01 0x01 0xEE");., @Edgar Bonet

да, это правильно, но я хотел подчеркнуть форматирование 0x%02X, чтобы оно всегда выводило двузначные шестнадцатеричные числа и позволяло последнему человеку изменять свои переменные после строки форматирования., @Tomas

Хорошая точка зрения! Однако вы можете добавить примечание, предупреждающее, что Serial.printf() не является стандартным методом Arduino. Он доступен на ESP, но не на стандартных ядрах Arduino., @Edgar Bonet

Чтобы процитировать вас: Хороший момент! Я слишком привык к esp core, что предположил, что core-Arduino кашлянул со своим хобби-ядром в те годы., @Tomas

Увы, похоже [основные разработчики Arduino не хотят, чтобы официальные ядра поддерживали printf()](https://github.com/arduino/ArduinoCore-API/pull/28)., @Edgar Bonet

Я бы посоветовал вам просмотреть учебник или два по шестнадцатеричным числам и тому, как они представлены., @Gil

@ Гил Что ты имеешь в виду? если вы видите что-то неправильное, укажите это. Я принимаю отзывы, но будьте конкретными, чтобы я и другие могли извлечь из них уроки. Лично я использую HEX-числа в программировании больше, чем десятичные. В моей коммуникационной библиотеке есть все инструкции в HEX. Поэтому, если вы имеете в виду какое-то конкретное улучшение моего подхода, укажите это, и я отредактирую свой ответ, цитируя вас в редактировании, как я сделал с полезным замечанием Эдгара Бонета., @Tomas