Преобразование 32-битного числа в 16-битное

Мне нужно преобразовать число в процент от максимального значения моего ЦАП (0x0FFF), чтобы мой код для этого был таким:

double percent;
short pct;

percent = (0x0FFF * pct)/100;

но мне нужно 16-битное значение для отправки в ЦАП, а не 32-битное. Как быстрее всего преобразовать его в 16-битное число? Могу я его сдвинуть?


person Jedi Engineer    schedule 13.05.2013    source источник
comment
Просто объявите percent как uint16_t? Вычисления выполняются для типа int, поэтому, если ваши int не имеют ширины менее 20 бит, переполнение не будет. Для 16-битных ints вы можете использовать 0x0FFFul, чтобы избежать переполнения.   -  person Daniel Fischer    schedule 13.05.2013
comment
@DanielFischer, они вполне могут быть 16-битными (и фактически, на большинстве платформ, где имеет смысл говорить о ЦАП, так и есть).   -  person avakar    schedule 13.05.2013
comment
@phuclv, почему вы редактируете этот пост после того, как он уже был отредактирован один раз через 6 лет после того, как я его разместил? Вы полностью исказили мой вопрос ...   -  person Jedi Engineer    schedule 23.02.2019
comment
Я как раз исправлял орфографические / грамматические ошибки. Как это искажено?   -  person phuclv    schedule 23.02.2019
comment
Ни за что, но похоже, что люди просто пытаются набрать опыт, редактируя сообщения. Нет никакой пользы от этой публикации, 6 лет спустя, для исправления грамматики.   -  person Jedi Engineer    schedule 24.02.2019
comment
@JediEngineer: нет ничего плохого в удалении старых постов, особенно если, как эта, они набирают много просмотров.   -  person Paul R    schedule 24.02.2019


Ответы (3)


Для этого нет необходимости использовать плавающую точку:

uint16_t val = 0x0fffU * pct / 100U; // convert 0..100 value to 0..4095
person Paul R    schedule 13.05.2013
comment
Спасибо!! Это галочка! - person Jedi Engineer; 13.05.2013

Если ваш процент имеет всего 101 значение от 0 до 100, тогда гораздо быстрее использовать справочную таблицу, чем выполнять умножение / деление, особенно в микроконтроллерах, где аппаратные инструкции mul / div недоступны.

Большинство микроконтроллеров имеют много доступной флэш-памяти / EEPROM, но не имеют оперативной памяти, поэтому таблицу можно просто сохранить в ПЗУ. Чтение таблицы из ПЗУ, вероятно, медленнее, чем из ОЗУ, но все же намного быстрее, чем выполнение деления. Однако у некоторых микроконтроллеров есть длинные циклы чтения, поэтому вам может потребоваться предварительная выборка или загрузка таблицы в ОЗУ, если ее достаточно, или просто использовать метод умножения и деления, описанный выше. Вы также можете упаковать стол (потому что вам нужно всего 12 бит) или проделать другие трюки

#define PCT(n) (0x0fffU * (n) / 100U)

#define PCTROW(n) (PCT(10*n),   PCT(10*n+1), PCT(10*n+2), PCT(10*n+3), PCT(10*n+4),\
                   PCT(10*n+5), PCT(10*n+6), PCT(10*n+7), PCT(10*n+8), PCT(10*n+9))

const uint16_t percent_tbl[] = {
    PCTROW(0), PCTROW(1), PCTROW(2), PCTROW(3), PCTROW(4),
    PCTROW(5), PCTROW(6), PCTROW(7), PCTROW(8), PCTROW(9), 0x0fffU
}

return percent_tbl[pct];
person phuclv    schedule 04.08.2013

person    schedule
comment
Хотя этот код может дать ответ на вопрос, лучше объяснить, как решить проблему, и предоставить код в качестве примера или справки. Ответы, состоящие только из кода, могут сбивать с толку и не иметь контекста. - person Robert Columbia; 03.07.2018
comment
Чем это отличается от ответа Пола Р. выше? - person phuclv; 19.02.2019