собрать unsigned long из Serial.read();
- Войдите на сайт для отправки комментариев
Чт, 21/01/2016 - 17:36
Доброго времени суток!
Есть входящий поток данных , мне необходимо "поймать" 4 первых байта и собрать в unsigned long
например так:
byte i = 0:
unsigned long *ptrVar;
while (Serial.available()) {
if (i < 4) ptrVar[i] = Serial.read();
i ++;
}
Serial.println(*ptrVar);
В итоге получаю 10, хотя при чтении идут сплошные нули. Что делаю не так?
Надо объявить массив символов char arr[4] заполнить его данными из порта и после этого смотреть на него как на unsigned long. Либо полученные данные сразу класть в unsigned long переменную со сдвигом.
Надо объявить массив символов char arr[4] заполнить его данными из порта и после этого смотреть на него как на unsigned long. Либо полученные данные сразу класть в unsigned long переменную со сдвигом.
Ну с первым понятно, хотелось бы второй вариант, можете поподробнее?
типа такого:
типа такого:
А Вы это пробовали, прежде, чем человеку предлагать? Оно ж в таком виде не работает ни фига.
Да, действительно не работает, вот например:
void setup() { Serial.begin(9600); char a[4]= {0,1,0,0}; unsigned long ptrVar; for (byte i = 0; i < 4; i ++) { ptrVar |= a[i] << (i*8); } Serial.println(ptrVar); } void loop() { }Вроде как 256 должно быть, а получаю 1310785793
Вроде как 256 должно быть, а получаю 1310785793
Ну, во-первых, Вы забыли проинициализировать ptrVar.
Во-вторых, для корректности эксперимента Вам следует в строке 3 вместо
chara[4]использоватьinta[4], т.к. метод read() возвращает именно int.Но работать всё равно не будет.
Переопределить тип переменным не судьба? ptrVar |= (long)a[i] << (i*8);
Переопределить тип переменным не судьба? ptrVar |= (long)a[i] << (i*8);
Не знаю, Вам виднее судьба Вам или не судьба. Видимо, не судьба, раз дали начинающему коллеге неработающий код.
Да и сейчас signed с unsigned в одну кучу свалили, что тоже не самая лучшая практика.
Из чего следует что я что-то с чем-то свалил в одну кучу? Я так понимаю на этом возражения закончились....
Почитал о регистровом сдвиге, наваял такой код:
void setup() { Serial.begin(9600); byte a[4] = {1, 0, 0, 0}; unsigned long ptrVar = 0; for (byte i = 0; i < 4; i ++) { ptrVar <<= 8; ptrVar += a[i]; } Serial.println(ptrVar); } void loop() { }Работает, только задом на перед, младшие байты попадают на место старших. Как это сделать правильно?
Код ptrVar |= (long)a[i] << (i*8); я не совсем понимаю, это получается мы сдвигаем биты элемента массива a[i], а потом проводим логическую операцию ИЛИ этого сдвинутого элемента и переменной ptrVar?
И по поводу приведения char в long, разве так можно? Мы же так код символа получим вместо самого числа?
Ну, во-первых, Вы забыли проинициализировать ptrVar.
Во-вторых, для корректности эксперимента Вам следует в строке 3 вместо
chara[4]использоватьinta[4], т.к. метод read() возвращает именно int.Да, увидел свою ошибку, спасибо!
Из чего следует что я что-то с чем-то свалил в одну кучу? Я так понимаю на этом возражения закончились....
prtVar какого типа? А в правой части Вы к какому приводите? Вот из этого и следует. что свалили в одну кучу.
ЕвгенийП, х...вый из тебя инженер программист, если свои сопли пытаешься на меня повесить. Я лишь кинул идею, то что новичек не разобрался это простительно, то что ты начал сопрли пузырями надувать - это говорит о том, какой ты программист. Просто помоги челу и слейся.
rene, хорошо, что разобрались, но с точки зрения эффективности и по памяти, и по времени, лучше всё-таки использовать другой способ о котором Вам говорили. Там не нужно ничего никуда сдвигать, само всё ложится.
Вот смотрите:
template <typename T> inline Print & operator << (Print &s, T n) { s.print(n); return s; } typedef union { unsigned long ulValue; unsigned char ucValue[sizeof(ulValue)]; } ULongByBytes; void setup() { Serial.begin(115200); ULongByBytes val; val.ucValue[0] = 0; val.ucValue[1] = 1; val.ucValue[2] = 0; val.ucValue[3] = 0; Serial << "Long Value = " << val.ulValue << '\n'; } void loop () {}Здесь мы присваиваем значения байтам, а потом печатаем получившийся unsigned long. Никаких сдвигов и вообще никаких дополнительных действий.
И по поводу приведения char в long, разве так можно? Мы же так код символа получим вместо самого числа?
При преобразованиях вида (<тип>)<переменная> на самом деле НИЧЕГО не преобразовывается и ничего не меняется. Просто впредь компилятор считает это новым типом. А реально в памяти остаётся ровно то, что было до этого - ничего не меняется никак.
Код ptrVar |= (long)a[i] << (i*8); я не совсем понимаю, это получается мы сдвигаем биты элемента массива a[i], а потом проводим логическую операцию ИЛИ этого сдвинутого элемента и переменной ptrVar?
1. заводим long и в младший байт помещаем значение a[i] (более грамотно здесь делать не long, а unsigned long)
2. этот long сдвигаем влево на i*8 битов
3. Переменной ptrVar присваиваем результат операции ИЛИ между её старым значением и нашим long, получившимся после сдвига.
Спасибо за помощь!