Форум РадиоКот https://radiokot.ru/forum/ |
|
dword https://radiokot.ru/forum/viewtopic.php?f=66&t=197902 |
Страница 1 из 1 |
Автор: | airnbrew [ Пт май 09, 2025 01:04:42 ] |
Заголовок сообщения: | dword |
Tiny88. Нужно отмасштабировать сигнал с АЦП с коэффициентом 0..1. Коэффициент 16-битный, точности достаточно. Ну и разобраться, как оно вообще работает. Думаю, должно быть быстрее и короче, чем через float. Имею примерно следующее. uint16_t result,k; uint32_t x; x=analogRead(an0)*k; x=x>>16; result=x; С любого разворота умножение даёт ноль. У большинства потребителей вход максимум 16-битный, не понял, как присвоить известно какую часть uint32 в uint16, младшую или старшую, где почитать? Что присваивается при обычном присвоении? И вообще, такой вариант должен работать тупо в лоб, или нужно искать какие-то доп. библиотеки? |
Автор: | Уош [ Пт май 09, 2025 01:07:20 ] |
Заголовок сообщения: | Re: dword |
да, я смотрел одно, видел другое, думал о третьем, поэтому, удалил свой ответ, как вводящий в заблуждение, прошу прощения. Добавлено after 1 minute 7 seconds: присваиваются, разумеется, одинаковые разряды. То есть, начиная со младших. А если явно указать приведение? например: Код: uint16_t result, k;
result= (uint16_t)((uint32_t)analogRead(an0) * k) >> 16); |
Автор: | muravei_ [ Пт май 09, 2025 12:14:06 ] |
Заголовок сообщения: | Re: dword |
Может Код: result = reinterpret_cast <uint16_t> x; так? |
Автор: | BOB51 [ Пт май 09, 2025 12:35:03 ] |
Заголовок сообщения: | Re: dword |
Для преобразования диапазона/масштабирования в референсе есть функции constrain(x,a,b) и map(value, fromLow, fromHigh, toLow, toHigh) другое делаем в случае, ежли ресурса тех функций недостаточно будет. ![]() |
Автор: | uldemir [ Пт май 09, 2025 12:53:59 ] |
Заголовок сообщения: | Re: dword |
да вы что. Если аналогРид даёт 16 бит и умножаете на K, который 16 бит - в результат получаете 16 бит (и, возможно, теряете данные если происходит переполнение), который потом записываете в 32 битную переменную. Но там всё-равно будет только 16 бит, которые операцией x>>16 уйдут прочь и останется 0. Чтобы при умножении не потерять точность, либо объявите k как 32битную или приведите её к 32 битам: x = Analogread() * (uint32_t)k; или аналогично приведите результат аналогрида к 32 битам. |
Автор: | BOB51 [ Пт май 09, 2025 13:02:59 ] |
Заголовок сообщения: | Re: dword |
Это при масштабировании "вверх". Там соответствующий размер результата надо с самого начала выбирать. Да и решений гораздо больше. Только где у АВРок АЦП более 12 бит то? ![]() Или таки задача состоит в получении младшего байта(слова) из более "крупноформатного" значения? Тогда или lowByte()/highByte() обратно им свертка l и h байт в word - word(h,l) или "фокусы" с union/struct lдля более "крупнразмерных" данных... ![]() |
Автор: | airnbrew [ Пт май 09, 2025 18:13:21 ] |
Заголовок сообщения: | Re: dword |
x=(long)analogRead(an0)*k; Правильно так. Оказывается, его нужно явно ткнуть носом, сам не умеет при умножении, когда в операндах 32 бита, к ним приводить. |
Автор: | HardWareMan [ Пт май 09, 2025 18:19:46 ] |
Заголовок сообщения: | Re: dword |
x=(long)analogRead(an0)*k; Правильно так. Оказывается, его нужно явно ткнуть носом, сам не умеет при умножении, когда в операндах 32 бита, к ним приводить. Вы будете смеяться, но даже gcc для ARM так не умеет. Сам наступил на эти грабли при работе с STM32, который далеко не 8 бит. |
Автор: | BOB51 [ Пт май 09, 2025 18:22:02 ] |
Заголовок сообщения: | Re: dword |
А кто мешает обьявить k как long? ![]() |
Автор: | Уош [ Пт май 09, 2025 18:35:58 ] |
Заголовок сообщения: | Re: dword |
смотря где объявить. |
Автор: | uldemir [ Пт май 09, 2025 19:02:44 ] |
Заголовок сообщения: | Re: dword |
BOB51 писал(а): А кто мешает обьявить k как long Жадность. Но...Если мы в теме про ардуину, можно допустить, что речь идёт о 8 битных контроллерах, так избыточная разрядность может выйти боком. Например, если эта переменная будет использоваться в прерывании, то надо будет заботиться о блокировке прерываний на время каждого её изменения в теле программы. Впрочем, на восьмибитках так же надо поступать и с 16 битными переменными. |
Автор: | BOB51 [ Пт май 09, 2025 19:57:31 ] |
Заголовок сообщения: | Re: dword |
Так в прерываниях свои правила. Да и регистровые пары довольно частое явление во многих 8-битных МК. Как там ресурсами компилятор распоряжается то только предположить можно (Си в этом смысле не ассемблер). При том, что предположить формат результата вполне доступное дело. Размерность результата АЦП известна, размерность коэффициента и конечного результата также. Только функция чтения АЦП уже имеет свой формат возвращаемых данных. Следовательно или результат надо приводить к наибольшему возможному или вторую участвующих в вычислениях переменную (константу) заранее с максимальным форматом объявлять. То уже зависит от конкретики(где чего удобнее). ![]() |
Автор: | Уош [ Пт май 09, 2025 19:58:38 ] |
Заголовок сообщения: | Re: dword |
uldemir, полагаю, речь лишь о тех переменных, которые и вне и внутри прерывания? |
Автор: | veso74 [ Пт май 09, 2025 20:31:48 ] |
Заголовок сообщения: | Re: dword |
Умножите ваш коэффициент 0..1 на 10, 100, 1000 (или больше), а в полученном результате просто напр. на дисплее переместите десятичную точку (столько раз, сколько нулей). Пример: 567 * 0.123 = 69.741 -> 69.741V будет 567 * 123 = 69741 -> 69.741V |
Автор: | uldemir [ Пт май 09, 2025 20:41:28 ] |
Заголовок сообщения: | Re: dword |
ну да. Обычно те, что обзывают волатильными. Компилятор может позаботиться, чтобы её "не соптимизировали", но позаботиться, чтобы при присваивании этой переменной какой-то другой не оказалось, так, что часть из этой жизни, а часть из другой - не всегда. СпойлерКод: /****************************************************************************** * 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 из 1 | Часовой пояс: UTC + 3 часа |
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group http://www.phpbb.com/ |