Юрий Ревич - Занимательная микроэлектроника
- Название:Занимательная микроэлектроника
- Автор:
- Жанр:
- Издательство:БХВ-Петербург
- Год:2007
- Город:Санкт-Петербург
- ISBN:978-5-9775-0080-7
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Юрий Ревич - Занимательная микроэлектроника краткое содержание
Для широкого круга радиолюбителей
Занимательная микроэлектроника - читать онлайн бесплатно ознакомительный отрывок
Интервал:
Закладка:
Улавливаете, к чему я клоню? С числами в десятичном виде хорошо работать руками, просто отсчитывая разряды. Нам же делить на сто тысяч в 8-разрядном МК крайне неудобно — представляете, насколько громоздкая процедура получится? Наше ноу-хау будет состоять в том, что мы для того, чтобы «вогнать» дробное число в целый диапазон, будем использовать не десятичную дробь, а двоичную — деление тогда сведется к описанной «механической» процедуре сдвига, аналогичной переносу запятой в десятичном виде.
Итак, чтобы умножить 976 на коэффициент 0,48576, следует сначала последний вручную умножить, например, на 2 16= 65 536, и тем самым получить числитель соответствующей двоичной дроби (у которой знаменатель равен 65 536) — он будет равен 31834,76736, или, с округлением до целого 31 835. Такой точности хватит, если исходные числа не выходят, как у нас, за пределы трех-четырех десятичных разрядов. Теперь мы в контроллере должны умножить исходную величину 976 на константу 31 835 и полученное число 31 070 960 (оно оказывается 4-байтовым — S01DA1AF0, потому нашу Mui6i6 придется чуть модифицировать, как сказано при ее описании ранее) сдвигаем на 16 разрядов вправо:
;в ddHH: ddH: ddM: ddL число $01DA1AF0,
;его надо сдвинуть на 16 разрядов
сlrг cnt
div16L: ;деление на 65536
lsr ddHH ;сдвинули старший
ror ddH ;сдвинули 3-й
rоr ddM ;сдвинули 2-й
rоr ddL ;сдвинули младший
inc cnt
cpi cnt,16
brne divl6L ;сдвинули-поделили на 2 в 16
В результате, как вы можете легко проверить, старшие байты будут нулевыми, а в ddM:ddL окажется число 474 — тот же самый результат. Но и это еще не все, такая процедура приведена скорее для иллюстрации общего принципа. Ее можно еще больше упростить, если обратить внимание на то, что сдвиг на восемь разрядов есть просто перенос значения одного байта в соседний (в старший, если сдвиг влево, и в младший — если вправо). Итого получится, что для сдвига на 16 разрядов вправо нам надо всего-навсего отбросить два младших байта, и взять из исходного числа два старших ddHH:ddH— это и будет результат. Проверьте — S01DA и есть 474. Никаких других действий вообще не требуется!
Если степень знаменателя дроби, как в данном случае, кратна 8, то действительно никакого деления, даже в виде сдвига, не требуется, но чаще всего это не так. Однако и тут приведенный принцип может помочь: например, при делении на 2 15(что может потребоваться, если, например, в нашем примере константа больше единицы) вместо пятнадцати кратного сдвига вправо результат можно сдвинуть на один разряд влево (фактически умножив число на два), а потом уже выделить из него старшие два байта. Итого процедура будет состоять из четырех операций сдвига и займет четыре такта. А в виде циклического сдвига на 15, как ранее, нам требуется в каждом цикле сделать четыре операции сдвига и одну увеличения счетчика: 15 х 5 = 75 простых однотактных операций, и еще 15 операций сравнения, из которых 14 займут два такта — итого 104 такта. А решение «в лоб» на основе операций целочисленного деления в несколько раз превышало бы и эту величину. Существенная разница, правда? Вот такая специальная арифметика в МК.
Это важная группа операций, ведь значительная часть устройств на основе МК предназначена для демонстрации чисел в том или ином виде. Это, естественно, можно делать только в десятичном формате, в то время как внутреннее представление чисел в регистрах двоичное. В некоторых микропроцессорных системах (в их число входит семейство x 51 от Intel и, кстати, x86) даже имеется специальная инструкция для т. н. двоично-десятичной коррекции , которая позволяет получить верный результат при сложении двоично-десятичных чисел в упакованном формате (о BCD-форматах см. главу 7 ). Но в системе команд AVR такой инструкции нет, и, в общем-то, она все равно не очень-то полезна, т. к. математические операции в любом случае удобнее выполнять в «родной» двоичной форме, а для представления на дисплее числа так или иначе приходится «распаковывать». В ПК этим незаметно для пользователя занимаются процедуры на языках высокого уровня (да так успешно, что приходится скорее озадачиваться обратной проблемой — представлением десятичных чисел в двоичной/шестнадцатеричной форме), ну а на уровне ассемблера десятичные преобразования приходится делать, что называется, ручками.
Заметки на полях
Традиционная область использования команд двоично-десятичной коррекции, в том числе и в процессорах х 86 — манипуляции со значением времени, полученным из микросхем RTC, в которых часы, минуты и секунды всегда хранятся в упакованном BCD-формате. Как вы увидите далее, такой формат хранения довольно удобен на практике. Однако область применения микроконтроллерных систем далеко не исчерпывается подсчетом и демонстрацией времени, потому нам придется выйти за рамки однобайтовых кодов, для которых, собственно, инструкция коррекции и создавалась. Уже для двухбайтовых чисел ее применение вызывает только лишние сложности.
В области BCD-преобразований есть три основные задачи:
• Преобразование двоичного/шестнадцатеричного числа в упакованный BCD-формат.
• Распаковка упакованного BCD-формата для непосредственного представления десятичных чисел с целью их вывода на дисплей.
• Обратное преобразование упакованного BCD-формата в двоичный/шестнадцатеричный для выполнения над ним, например, арифметических действий.
Некоторые процедуры для этой цели приведены в фирменной Application notes 204. При их использовании нужно учесть ряд моментов. Так, процедура bin2BCD8 для преобразования однобайтового числа в BCD работает только для чисел от 0 до 99 (для больших чисел нужен еще один байт, точнее, тетрада — в ней будет храниться старший разряд). В «аппноте» процедура представлена в универсальном виде, пригодном (при небольшой модификации) и для получения упакованного BCD, и для изначально распакованного (результат в двух отдельных байтах). Чтобы не путаться, приведу здесь ее вариант (листинг 15.3), который заодно более экономичный по количеству используемых регистров. Исходное hex-число содержится в регистре temp, распакованный результат — в temp1: temp. Как и в предыдущих случаях, комментарии сохранены из исходного текста.
Листинг 15.3
;преобразование 8-разрядного hex в неупакованный BCD
;вход hex= temp, выход BCD temp1-старший; temp — младший
;эта процедура работает только для исходного hex от 0 до 99
bin2bcd8:
clr temp1 ;clear result MSD
bBCD8_1: subi temp,10 ;input = input — 10
brcs bBCD8_2 ;abort if carry set
inc temp1 ;inc MSD
rjmp bBCD8_1 ;loop again
bBCD8_2:subi temp, — 10 ;compensate extra subtraction
Читать дальшеИнтервал:
Закладка: