Столкнулся с проблемой нехватки машинного времени при цикличных многоэтажных математических вычислениях. Потребовалось в реал-тайм вычислять "по кругу" проценты от полусотни переменных, которые, разумеется, постоянно изменяются.
Казалось бы, простые действия: значение переменной А нужно умножить на величину процентов В, затем разделить результат умножения на 100, и получишь итоговый результат (в процентах) С.
Но контроллер умеющий аппаратно умножать (какая-нить ATMega), к сожалению, не умеет аппаратно делить...
И в итоге оказалось, что если делить программно, то для одного такого вычисления потребуется более 350 машинных тактов, а это при тактовой частоте камня 3,792 МГц почти 100 микросекунд! Соответственно, для того, чтобы вычислить проценты от 50 переменных, потребуется уже 5 миллисекунд. А все это нужно сделать за 3,5 мс, как того требует ТЗ. И за это время еще требуется опросить датчики, запустить кучу ADC, и дождаться их результаты. Короче, тупик...
Долго ломал голову в поисках решения. И таки нашел!
Нас с детства приучили вычислять проценты, как столько-то там сотых частей от целого. Но тогда нам забыли рассказать, что кроме десятичного счисления (а проценты живут именно в десятичной системе), есть еще двоичная, восьмеричная, шестнадцатиричная, и т. д. И сегодня большинство среди тут с одинаковой легкостью оперируют не только десятичными числами, но и всеми остальными. И что самое главное - все микроконтроллеры используют именно двоичную систему, а не десятичную!
Так кто нам мешает назвать одним процентом не 1/100 часть от целого, а допустим, 1/128 часть от того же самого целого? Ведь тогда описанная выше процедура вычисления новых "процентов" не потребует длительного программного деления, а сведется к восьмикратному, но быстрому аппаратному сдвигу результата умножения вправо (деление на 128). Впрочем, можно получить искомый результат еще быстрее. Достаточно результат умножения один раз сдвинуть влево (умножить еще на 2), и просто отбросить младший байт двух-байтного результата!
Замечу: этот метод применим только для одно-байтных исходных чисел, т.е. оба множителя не должны быть больше, чем 255 (в десятичной системе). Тогда результат умножения вполне себе поместится всего в двух байтах.
Я в секции распределения РОН задал такую переменную Result - r0:Word.
Новый точечный рисунок.jpg [ 9.46 КБ | Просмотров: 12475 ]
В итоге конечный результат вычисления новых "процентов" автоматически оказывается в регистре r1, сам программный код занимает не пол-страницы Алгоритм Буилдера, а всего 4 строки, две из которых предназначены для ввода множителей (исходное значение и требуемые проценты), а время одного вычисления сокращается с трехсот пятидесяти машинных тактов до всего лишь шести машинных тактов, или почти в 600 раз!
Не знаю, возможно кто-то уже предлагал подобное решение, но я такого еще на встречал, и допер до него сам. Поэтому надеюсь, что моя математическая зарисовка пригодится еще кому-нибудь.