Могу ли я использовать 1-байтовые типы данных для хранения цифрового ввода?
Я читаю документы на DigitalRead() и задаюсь вопросом, почему он хранит, казалось бы, логические входные данные HIGH
и LOW
в переменной типа данных int
.
У меня есть две проблемы с этим:
int
— 2 байта, аbool
иuint8_t
— 1 байт, так что кажется, что это пустая трата памяти без какой-либо пользы. .- При чтении кода меня смущает, был ли ввод цифровым или аналоговым, поскольку
int
может иметь широкий диапазон.
Есть ли какая-либо особая причина для хранения цифровых входов как int
?
EDIT: bool
и uint8_t
не могут быть рассмотрены в соответствии с ответом ниже. Однако int8_t
по-прежнему подходит для этой цели.
@Arthur Tarasov, 👍3
Обсуждение4 ответа
Лучший ответ:
Вы получаете данные как int
, но сохраняете их как byte
.
Например, когда вы вызываете функцию последовательной библиотеки для получения байта данных, библиотека вернет либо данные, либо -1, если возникла проблема.
Двоичное значение -1 — это byte 11111111 или int 1111111111111111.
Двоичное значение 255 — это байт 11111111 или целое число 0000000011111111.
Я думаю, что вы можете увидеть проблему, если вы используете данные byte
, а данные равны 255.
Итак, если вы получаете int
-1, вы не обрабатываете данные. В противном случае вы преобразуете
int
в uint8_t
.
Вы можете получить данные byte
, но тогда значение 255 будет неопределенным.
Я подозревал, что происходит что-то скрытое. Как насчет int8_t
? Он может хранить -1, 0 и 1 и по-прежнему занимает 1 байт., @Arthur Tarasov
int8_t
хранит значения от -128 до 127.... uint8_t
хранит значения от 0 до 255... оба типа данных хранят 8 бит... они просто существуют, так что компилятор выдаст предупреждение, если пределы превышены, @jsotola
Поэтому я просто заменил все int
, хранящие цифровые входы в моей программе, на 1-байтовые int8_t
. Кажется, пока все работает нормально., @Arthur Tarasov
Ни digitalRead()
, ни analogRead()
никогда не возвращают -1
.
Нет никакой причины, по которой digitalRead()
является функцией int
, а не uint8_t
, и это действительно бесполезно тратит место. Компилятор, вероятно, оптимизирует его, если вы сохраните результат как uint8_t
или int8_t
, @towe
Я не проверял внутренности какое-то время, но в первые дни был
#define HIGH 1
это означает, что HIGH является const int
.
Возможно, кто-то изначально не хотел отключать некоторую цифровую логику TRI-STATE, и с тех пор никто не хотел менять основы.
Но, конечно, bool
является более подходящим типом данных для HIGH/LOW, и, конечно, вы всегда можете обращаться с ними таким образом, например, как
if (! digitalRead(pin) ) { // контакт НИЗКИЙ
...
}
Ответ jsotola, почему Serial.read() возвращает int
, — это другой вопрос. И правильно конечно.
Наименьшей единицей измерения в большинстве языков является байт (8 бит), независимо от того, знаковый он или беззнаковый. Таким образом, возврат байта, даже если он возвращает только три разных значения, является наименьшей и наиболее эффективной доступной единицей, о которой я знаю.
Если вы хотите сохранить позже, вы можете назначить каждому биту байта старший или младший, что даст вам 8 ячеек памяти.
Всегда можно сохранить значение digitalRead() как бит в переменной, сжимая данные, скажем, с 8 контактов до 1 байта
// прочитать ввод и сохранить его, скажем, чтение от D2 до D9 хранится в байтах bits9to2
// 9,8,7,6,5,4,3,2
// сначала очистить состояние для 2
bits9to2 = bits9to2 && 0b11111110; // два && для битовых манипуляций? Или только 1?
// затем сопоставляем новое значение
if (digitalRead(D2) == HIGH){
bits9to2 = bits9to2 || 0b00000001;// два || для битовых манипуляций? Или только 1?
}
else{
// оставляем 0
}
Затем, чтобы использовать его позже:
if ((bits9to2 && 0b00000001) != 0){
// установлен бит (ВЫСОКИЙ), делаем что угодно
}
else {
// бит сброшен (НИЗКИЙ), делайте что угодно, а может и ничего не делайте
}
Можно использовать unsigned int и сохранять таким образом 16 бит, или unsigned long для 32 бит.
- Как получить тип данных переменной?
- Преобразование в Unix Timestamp и обратно
- Невозможно создать массив типа const char*
- ардуино - миллисекунды ()
- Ошибка Cast from 'char*' to 'uint8_t {aka unsigned char}' loses precision [-fpermissive]
- Получение шестнадцатеричных данных с терминала
- Какой тип данных Arduino допускает десятичные дроби?
- Поскольку double и float представляют один и тот же тип данных (обычно), что предпочтительнее?
Обратите внимание, что значение, возвращаемое функцией, передается во внутренние регистры ЦП, поэтому здесь нет пустой траты оперативной памяти. Если бы мне когда-нибудь пришлось хранить возвращаемое значение в памяти, я бы действительно использовал
uint8_t
., @Edgar Bonet