Управляющие символы ASCII - хаос!))

Всем привет!
Очередной раз пытаюсь задать вопрос на форуме, но по мере подготовки материала, ответ находится, и спрашивать уже нечего))
Так же и в этот раз. Долго я возился с написанием “ногодрыга” для передачи по UART , не понимая, где моя ошибка, и почему в разных эмуляторах терминала получаю разные данные. Но всё оказалось проще:
разные программы для работы с последовательным портом воспринимают некоторые управляющие символы по разному, и никакие настройки здесь не помогут! (Если я не прав, прошу меня опровергнуть)
В общем, здесь я изобрёл велосипед, но всё же решил выложить свой “горький опыт”, может кому и пригодится.

Например, вот код:

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


void loop() {
  static byte chislo = 0;
  Serial.print(chislo);
  Serial.print('\n'); // перенос строки
  chislo++;
  delay(500);

}

А вот скрины его выполнения в Proteus, Arduino IDE, Terminal v1.9b и Putty
Screenshot_Proteus_ASII
Screenshot_IDE_ASII


Screenshot_PUTTY_ASII

Настройки, насколько они доступны, одинаковые
Подобный разнобой замечен с символами ‘\0’ и ‘\t’ . Больше проверять не стал, т.к. три - это уже “система”))

Да. Не все эмуляторы терминалов правильно отрабатывают /t, /r, /n. Кроме PuTTY.

1 лайк

Я переформулирую это утверждение так, чтобы оно было верным:
В разных ОС для обозначения конца строки используются разные комбинации символов, программы, предназначенные для работы в разных ОС, соответственно, ведут себя по-разному.
В ASCII традиционно использовалось два символа:
CR (13) - возврат каретки - для перевода каретки к началу текущей строки,
LF (10) - перевод строки - для перехода на следующую строку без изменения колонки.
В одних ОС для обозначения конца строки нужно применять оба эти символа, в других - достаточно какой-то один из них. Т.е. всего три варианта: CRLF(DOS/Win), CR(старые версии MAC OS) и LF(Unix).

А что не так с 0 и табуляцией?

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

На самом деле все проще.
Пользуйся println вместо того, чтобы вручную вводить управляющие последовательности (особенно когда не очень представляешь, как они работают), и будет тебе счастье.

Да ладно! А если нужен только /r, а вместо этого отрабатывает /r/n?

1 лайк

Символ ‘\0’ в Arduino IDE и Terminal 1.9b:
Screenshot_0png
Screenshot_01

Табуляция в Proteus:
Screenshot_10png

Чего-то вообще не видно))

Да, можно принудительно добавить, скажем возврат каретки, и новую строку после каждого символа . Но не получится заставить
прочитать ‘\n’ , если программа его в упор не видит как отдельный упр. символ

Принимайте в HEX и не будет разночтений !!!

Да, это так. А если ASCII нужен?
И не все программы позволяют прочитать HEX

Да, началось с того, что решил написать себе “ногодрыг” для Тинек( и не только), чтобы экономно выводить данные . Поэтому и пришлось разбираться))

Пока что мы видим обратное: нужно CRLF, а вместо этого вручную вставляется только LF.
Если бы ТС понимал, что для чего нужно, этой темы бы не появилось.

Кто никогда не печатал на печатной машинке - не поймёт этого …

Единственный символ \0 превращается в длинную цепочку символов?
Что-то Вы явно не то делаете.

Вообще по стандарту ASCII нулевой символ должен игнорироваться. Это еще со времен перфоленты - чистая лента без дырочек - это отсутствие каких-либо символов.

Не надо преувеличивать: достаточно понимать, что движение курсора по горизонтали (CR) и по вертикали (LF) - это разные команды.

Да нет конечно. Это всё тот же код из “шапки” темы. Только вместо ‘\n’ стоит ‘\0’

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


void loop() {
  static byte chislo = 0;
  Serial.print(chislo);
  Serial.print('\0'); // перенос строки
  chislo++;
  delay(500);

}

Можете убедиться, что этого не происходит, например в Arduino IDE

В HEX всё нормально с этим кодом
30 00 31 00 32 00 33 00 34 00 35 00 36 00 37 00
38 00 39 00 31 …

Да, за HEX речи нет, на тех программах, что позволяют, я тоже проверил

Вывод, мне кажется, простой: нефиг пользоваться программами, которые не понимаешь, как работают.
В частности, вообще не нужно пользоваться эмуляторами Ардуино.

Ну а по части соблюдения стандарта:
Полностью выполняет стандарт ASCII putty.
Arduino IDE работает в стандарте unix.
Остальные программы работают неверно (вероятно реакция заимствована из “упрощенной” для DOS) .

1 лайк

Может, не надо переваливать на Arduino IDE свои ошибки?
Символ с кодом 0 вообще не должен появляться в передаваемом сообщении. Притом, сразу по двум причинам:

  1. Этот код является в языке Си служебным - сигнализирует о конце строки. И в этом качестве передаваться никак не должен.
  2. В ASCII это означает отсутствие символа.

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