Tiny88. Нужно отмасштабировать сигнал с АЦП с коэффициентом 0..1. Коэффициент 16-битный, точности достаточно. Ну и разобраться, как оно вообще работает. Думаю, должно быть быстрее и короче, чем через float.
Имею примерно следующее.
uint16_t result,k; uint32_t x;
x=analogRead(an0)*k; x=x>>16; result=x;
С любого разворота умножение даёт ноль.
У большинства потребителей вход максимум 16-битный, не понял, как присвоить известно какую часть uint32 в uint16, младшую или старшую, где почитать? Что присваивается при обычном присвоении? И вообще, такой вариант должен работать тупо в лоб, или нужно искать какие-то доп. библиотеки?
Для преобразования диапазона/масштабирования в референсе есть функции constrain(x,a,b) и map(value, fromLow, fromHigh, toLow, toHigh) другое делаем в случае, ежли ресурса тех функций недостаточно будет.
Использование модульных источников питания открытого типа широко распространено в современных устройствах. Присущие им компактность, гибкость в интеграции и высокая эффективность делают их отличным решением для систем промышленной автоматизации, телекоммуникационного оборудования, медицинской техники, устройств «умного дома» и прочих приложений. Рассмотрим подробнее характеристики и особенности трех самых популярных вариантов AC/DC-преобразователей MW открытого типа, подходящих для применения в промышленных устройствах - серий EPS, EPP и RPS представленных на Meanwell.market.
да вы что. Если аналогРид даёт 16 бит и умножаете на K, который 16 бит - в результат получаете 16 бит (и, возможно, теряете данные если происходит переполнение), который потом записываете в 32 битную переменную. Но там всё-равно будет только 16 бит, которые операцией x>>16 уйдут прочь и останется 0.
Чтобы при умножении не потерять точность, либо объявите k как 32битную или приведите её к 32 битам: x = Analogread() * (uint32_t)k;
или аналогично приведите результат аналогрида к 32 битам.
Это при масштабировании "вверх". Там соответствующий размер результата надо с самого начала выбирать. Да и решений гораздо больше. Только где у АВРок АЦП более 12 бит то? Или таки задача состоит в получении младшего байта(слова) из более "крупноформатного" значения? Тогда или lowByte()/highByte() обратно им свертка l и h байт в word - word(h,l) или "фокусы" с union/struct lдля более "крупнразмерных" данных...
Правильно так. Оказывается, его нужно явно ткнуть носом, сам не умеет при умножении, когда в операндах 32 бита, к ним приводить.
Вы будете смеяться, но даже gcc для ARM так не умеет. Сам наступил на эти грабли при работе с STM32, который далеко не 8 бит.
_________________ Репозиторий STM32: https://cloud.mail.ru/public/2i19/Y4w8kKEiZ Актуальность репозитория: 1 июля 2025 года Если чего-то не хватает с сайта st.com - пишите, докачаю.
Если мы в теме про ардуину, можно допустить, что речь идёт о 8 битных контроллерах, так избыточная разрядность может выйти боком. Например, если эта переменная будет использоваться в прерывании, то надо будет заботиться о блокировке прерываний на время каждого её изменения в теле программы. Впрочем, на восьмибитках так же надо поступать и с 16 битными переменными.
Так в прерываниях свои правила. Да и регистровые пары довольно частое явление во многих 8-битных МК. Как там ресурсами компилятор распоряжается то только предположить можно (Си в этом смысле не ассемблер). При том, что предположить формат результата вполне доступное дело. Размерность результата АЦП известна, размерность коэффициента и конечного результата также. Только функция чтения АЦП уже имеет свой формат возвращаемых данных. Следовательно или результат надо приводить к наибольшему возможному или вторую участвующих в вычислениях переменную (константу) заранее с максимальным форматом объявлять. То уже зависит от конкретики(где чего удобнее).
Умножите ваш коэффициент 0..1 на 10, 100, 1000 (или больше), а в полученном результате просто напр. на дисплее переместите десятичную точку (столько раз, сколько нулей).
ну да. Обычно те, что обзывают волатильными. Компилятор может позаботиться, чтобы её "не соптимизировали", но позаботиться, чтобы при присваивании этой переменной какой-то другой не оказалось, так, что часть из этой жизни, а часть из другой - не всегда.
Спойлер
Код:
/****************************************************************************** * ATOMIC OPERATIONS for ATMEGA328 ONLY * Since the ATMega328 is an 8 bit processor it is possible that you will end * up trying to read a multi-byte quantity that is modified in an interrupt while * you are doing the read or write. The result is a corrupt value. 32 bit processors * are unlikely to suffer from this since quantities are read in a single operation. * * The AVR compiler provides a method for you to disable interrupts for the * duration of a block of code and then restore the state at the end of the block. * * It is not enough to simply turn off interrupts and then turn them back on because * you need to remember the state of the interrupt enable flag at the start of the * block. * * These macros do this for you and should be either modified for different processors * or bypassed if needed. * * Use like this: * ATOMIC { * // code to protect * } * */
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 1
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения