int на Uno более 16 бит?

Итак, я играю с TFT-экраном и пытаюсь понять кодировку цветового пространства . Я написал быстрый цикл for, чтобы показывать цвета от 0 до FFFF и печатать значение отображаемого цвета:

for (int q=0; q<0xFFFF; q+=0x80) {
  tft.fillScreen(q);
  tft.setCursor(0, 0); tft.println(q, HEX);
  delay(2);
}

Я был удивлен, обнаружив отображаемые значения, превышающие FFFF, что предполагает, что int имеет длину более 16 бит. Он работает на Uno.

Что случилось?

(PS теперь я понимаю кодировку RGB565, так что это не по теме)

, 👍0

Обсуждение

Сокко, закроем этот вопрос? В следующий раз начните с того, что сообщите нам, какой у вас TFT-экран и что вы используете библиотеку adafruit gfx, и, если возможно, покажите рабочий эскиз. tft.fillScreen имеет беззнаковый 16-битный параметр. Значение выше 0xFFFF переносится и снова начинается с 0x0000., @Jot


1 ответ


1

Думаю, вы видите большие цифры, начинающиеся с FFFF...?

Вы видите не большие цифры, а искаженные цифры.

У вас есть int. Это не «16-битное число», это 15-битное число плюс знаковый бит.

При печати переменная повышается до long, а знаковый бит расширяется.

Этот long затем преобразуется (приводится) в unsigned long для печати его в шестнадцатеричном виде (в шестнадцатеричном представлении Arduino нет отрицательного значения), и это бит расширенного знака рассматривается как строка F.

Например, значение 0xABCD, хранящееся в int, имеет вид:

 1 010 1011 1100 1101

Я отломил первый бит, потому что это бит знака в знаковом целом. Фактическое десятичное значение составляет -21555.

Теперь, когда оно преобразуется в длинное значение, расширение знака копирует ведущий бит знака во все остальные 16 бит слева от него, в результате чего:

1 111 1111 1111 1111 1010 1011 1100 1101

Из-за особенностей работы дополнения до двух эта строка битов по-прежнему представляет -21555 в десятичном формате.

Однако приведите его к unsigned long для печати в формате HEX, и вы увидите, что в итоге вы получите большие числа. Это даст вам:

FFFFABCD

Итак, вы можете видеть, что 16-битное знаковое значение может быть напечатано как 8 шестнадцатеричных цифр, и все из-за того, как работает функция print() в API Arduino.

>

При работе с беззнаковыми значениями вам действительно следует работать с беззнаковой переменной, особенно если эти беззнаковые значения (0–65535) выходят за пределы диапазона типа знаковой переменной (-32768–32767). Переключитесь на использование uint16_t, и вы сможете правильно хранить и представлять значения.


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

,

Спасибо за подробное объяснение @Majko - для меня весьма информативно. (1) Однако на дисплее не отображаются ведущие FFFFF - например, теперь отображается 26C E000 . (2) Я предполагаю, что цикл for никогда не завершится, потому что 0xFFFF всегда будет больше, чем оценка максимального знакового int = 0x7FFF - (3) Но это все равно не объясняет, почему на дисплее отображаются числа, разрядность которых превышает 16 бит, это предполагает, что команде печати присвоено число больше 16 бит. (4) Uno - это китайский клон, полученный с другим железом - так может это актуально?, @Socco

Это не потому, что это китайский клон — это все равно то же программное обеспечение, работающее на том же процессоре, даже если оно из мусорной корзины. Ваш цикл определенно никогда не закончится. Вам следует перейти на беззнаковое значение, которое больше максимального значения цикла. Вместо этого используйте uint32_t для своего цикла, а затем приведите его к uint16_t для значения цвета., @Majenko