Ты предлагаешь просто сделать массив на 375 значений (375 мм. рт. ст. предел для моего датчика давления) и все.
Если идёт речь о оцифрованых данных после закрытия клапана, то 375 значений это ОЧЕНЬ мало. Усреднять-то из чего-то надо. Тем более мега легко позволяет много больше снять за это время.
Еще есть идея сделать так, что бы после каждого нового измерения обрабатывать данные и находить производные и когда они перестанут изменяться то выводить значения на экран и открывать клапан (это должно происходить как только определим нижнее давление).
Первое. Производная начального значения будет равна нулю, следует это учесть. Второе, дрейф АЦП меги будет в самом лучшем случае 1-2МЗР. Т.е. производная в ноль не установится, если не "округлить" полезное значение.
typedef enum {
show_clock,
set_hr,
set_min,
res_sec} states;
states state;
Присваивания, сравнения идут без проблем. Но надо сделать переход на "следующее" состояние. Если пишу state++ - вперед проходит нормально и... уходит куда-то дальше. Т.е. не ходит по-кругу.
Пробую написать
state = (state == res_sec) ? show_clock : ++state;
- ругается на Warning[Pa079]: undefined behavior: variable "state" (declared at line 72) (or a value reached by some form of indirection.
хм, не писать же switch для всех переходов?
p.s. пока обошелся ifом.
А люди посмотрят и скажут: "Собаки летят. Вот и осень."
uldemir писал(а):Но надо сделать переход на "следующее" состояние. Если пишу state++ - вперед проходит нормально и... уходит куда-то дальше. Т.е. не ходит по-кругу.
Пробую написать
state = (state == res_sec) ? show_clock : ++state;
- ругается на Warning[Pa079]: undefined behavior: variable "state" (declared at line 72) (or a value reached by some form of indirection.
хм, не писать же switch для всех переходов?
p.s. пока обошелся ifом.
Вдумайтесь. Вы создали перечисляемый тип. В составе которого есть перечисленные вами элементы. Вы можете при объявлении добавить или удалить сами элементы. Но для вас есть тайна великая, какие значения скрываются под перечисляемыми именами. Вам должно быть известно, что вы можете присвоить имени свое собственное значение. Тогда следующему элементу будет присвоена величина на 1 больше вашей, т.е. следующая. Что значит "по кругу"? Чем и где вы определили размерность объявленного вами типа ("замкнули круг"). Попробуйте присвоить первому перечисляемому величину 255. Потестируйте, какие будут следующие значения при автоперечислении. Поиграйте с размерностью на этот раз уже переменной с созданным вами типом. Увидите неожиданные результаты. Особенно на различных по разрядности платформах. Всегда помните, что байт не есть единственная по разрядности величина, применяемая при объявлении перечисляемых типов.
ну я примерно вдумался. вот почему ++state; корректно, а state=++state; нет? Оно возвращает данные другого типа? я то полагал, что возвратит следующий элемент списка.
А люди посмотрят и скажут: "Собаки летят. Вот и осень."
uldemir писал(а):ну я примерно вдумался. вот почему ++state; корректно, а state=++state; нет? Оно возвращает данные другого типа? я то полагал, что возвратит следующий элемент списка.
А кто сказал, что ++state корректно? Компилятор не ругнулся? Это ничего еще не значит. Не путайте элементы перечисляемого списка с указателем.
Должен принести свои извинения. Ради любопытства решил потестировать ваши примеры. И сам бул удивлен. Беру свои слова обратно и радость игрищ с перечисляемыми типами оставляю вам. Я никогда не сталкивался с необходимостью писать в таком стиле. Еще раз извините.
uldemir писал(а):ну я примерно вдумался. вот почему ++state; корректно, а state=++state; нет?
Компилятор насторожили две записи в одну переменную в промежутке между точками следования, он и выдал предупреждение об UB (порядок записей неопределён). Тут две записи: в операторе ++ и в операторе =.
должно дать то же самое предупреждение, если дало с enum.
Хотя конкретно тут результат будет одинаковый, это в i = i++; будут проблемы порядка записей.
Возможно, компилятор ворчит на то, что он при оптимизации оставил одну запись в переменную из двух имеющихся в выражении (кстати, при volatile state он обязан будет обе записи оставить — оно Вам нужен лишний код?). Возможно, просто обиделся на наличие двух записей и не стал даже анализировать корректность результата.
state = (state == res_sec) ? show_clock : state + 1;
и избавиться от предупреждения?
(в С, так как в С++ тут таки будет ошибка несовпадения типов, нужно будет явно написать приведение (states)(state+1) )
p.s.
(тут был неправильный p.s., правильный был бы с постинкрементом, но он тяжело читается и не нужен такой)
Последний раз редактировалось avreal Сб май 12, 2012 12:54:30, всего редактировалось 1 раз.
Лень в виде мании величия: «ты гений, зачем стараться?». В виде комплекса: «всё равно не выйдет, зачем упираться?». Как логика: «если достаточно, зачем знать и уметь больше?». Цель одна: остановить. Не любит тепло работающих мышц и шум работающего мозга.
Да, про конфликт порядка записи я и позабыл. А на конструкцию state+1 получал предупреждение, но не стал вникать какого типа будет результат и не додумался, что можно воспользоваться приведением типа. Спасибо за внятное разъяснение.
А люди посмотрят и скажут: "Собаки летят. Вот и осень."
Вопрос к знатокам DFT
В вики по этому поводу написано:
Прямое преобразование:
Обратное преобразование:
Обозначения:
N — количество значений сигнала, измеренных за период, а также количество компонент разложения;
xn, n=0...N-1 — измеренные значения сигнала (в дискретных временных точках с номерами n), которые являются входными данными для прямого преобразования и выходными для обратного;
Xk, k=0...N-1 — комплексные амплитуды синусоидальных сигналов, слагающих исходный сигнал; являются выходными данными для прямого преобразования и входными для обратного; поскольку амплитуды комплексные, то по ним можно вычислить одновременно и амплитуду, и фазу;
|Xk|/N — обычная (вещественная) амплитуда k-го синусоидального сигнала;
arg(Xk) — фаза k-го синусоидального сигнала (аргумент комплексного числа);
k — индекс частоты. Частота k-го сигнала равна k/T, где T — период времени, в течение которого брались входные данные.
А теперь собственно вопрос. Если n=0...N-1 и k=0...N-1(причем значения изменяются синхронно) то почему они выделяются как отдельные переменные? Т.е. скажем не n^2 вместо произведения n*k
VannO))), с чего вдруг они изменяются синхронно. Приглядитесь, в первой формуле n - это индекс суммирования, а k - внутри этой суммы константа. В нижней формуле n и k поменяны ролями.
Функции в С/С++ могут возвращать только одну переменную. Чтобы функция могла работать с массивом, нужно выделить для него память перед вызовом этой функции и передать ей указатель.
Например, эта функция заполнит три элемента массива цифрами 3, 5 и 8:
Только это неэффективно, одни и те же значения переписываются несколько раз. Первый раз при копировании в возвращаемое значение, второй раз из временного объекта в переменную в месте вызова.
Так что вопрос не в том можно ли, а надо ли? Тем более если программа пишется, скажем для контроллера с 1кБ программной памяти, 64 байта ОЗУ и 4-уровневым стеком
. Мне надо выбрать младшие два байта из ulMsgID и запихнуть их младшими в массив. Как мне выделить два байта из ulMsgID? Простите за тупость, но я сегодня торможу по полной (((
Chip115 писал(а):Мне надо выбрать младшие два байта из ulMsgID и запихнуть их младшими в массив.
А как вы определяете младший байт в двухбайтовом числе? Правильно. Берете остаток от деления этого числа на 256. А как определяете старший байт? Правильно. Берете целое от деления этого числа на 256.
Теперь определитесь с размерностью вашего лонг-числа и вычислите на какую величину надо его делить. Тут уж сами...
И еще. В массиве нет младших и старших ячеек. Они нумеруются от нулевой до максимальной. Услышав фразу "младшими в массив" хочется спросить - а с какой стороны у вас старшие? Типа "А где лево? Дак с другой стороны от право".