Главная страница
Библиотека (скачать книги)
Скачать софт
Введение в программирование
Стандарты для C++
Уроки по C#
Уроки по Python
HTML
Веб-дизайн
Ассемблер в среде Windows
ActiveX
Javascript
Общее о Линукс
Линукс - подробно
Линукс - новое
Delphi
Паскаль для начинающих
Турбопаскаль
Новости
Партнеры
Наши предложения
Архив новостей





Заметки на полях
Традиционная область применения команд двоично-десятичной коррекции, в том числе и в процессорах х86— манипуляции со значением времени, полученным из микросхем RTC, в которых часы, минуты и секунды всегда хранятся в упакованном BCD-формате. Как вы увидите далее, такой формат хранения довольно удобен на практике. Однако область применения микроконтроллерных систем далеко не исчерпывается подсчетом и демонстрацией времени, потому нам придется выйти за рамки однобайтовых кодов, для которых, собственно, инструкция коррекции и создавалась. Уже для двухбайтовых чисел ее применение вызывает только лишние сложности.

В области BDC-преобразований есть три основные задачи:
□ преобразование двоичного/шестнадцатеричного числа в упакованный BCD-формат;
□ распаковка упакованного BCD-формата для непосредственного представления десятичных чисел, например, с целью их вывода на дисплей;
□ обратное преобразование упакованного BCD-формата в двоичный/шестнадцатеричный с целью, например, произведения арифметических действий над ним.

Некоторые процедуры для этой цели приведены в фирменной Application notes AVR204. При работе с ними нужно учесть ряд моментов. Так, процедура bin2BCD8 для преобразования однобайтового числа в BCD работает только для чисел от 0 до 99 (для больших чисел нужен еще один байт, точнее, тетрада— в ней будет храниться старший разряд). В "аппноте" процедура представлена в универсальном виде, пригодном (при небольшой модификации) и для получения упакованного BCD, и для сразу распакованного (результат в двух отдельных байтах). Чтобы не путаться, приведу здесь ее вариант для получения распакован нога формата, заодно более экономно задействующий регистры (листинг 7.10). Исходное hex-число содержится в регистре temp, распакованный результат— в tempi:temp. Как и в предыдущих случаях, комментарии сохранены из исходного текста.

Листинг 7.10
/преобразование 8-разрядного hex в неупакованный BCD /вход hex = temp, выход BCD tempi — старший, temp — младший ;эта процедура работает только для чисел от 0 до 99 bin2bcd8:
clr tempi /clear result MSD
bBCD8_l:subi temp,10 /input = input - 10
brcs bBCD8_2 /abort if carry set
inc tempi /inc MSD
rjmp bBCD8 1 /loop again
bBCD8_2:subi temp,-10 ;compensate extra subtraction ret

А вот одно из решений обратной задачи— преобразования упакованного BCD (например, тех же значений часов, минут и секунд из RTC) в hex-число, после чего с ним можно производить арифметические действия (листинг 7.11). По сравнению с "фирменной" BCD2bin8 эта процедура хоть и немного длиннее, но понятнее и более предсказуема по времени выполнения ("фирменная" может занимать от 3 до 48 тактов).

;на входе в temp упакованное BCD-значение ;на выходе в temp hex-значение ;tempi — вспомогательный регистр /действительна только для семейства Меда HEX_BCD:
ldi multl0,10
;если multlO из числа регистров г0-г15, то заменяется на пару
; ldi tempi,10
; mov multlO,tempi
mov tempi,temp
andi temp, 0Ы1110000 ;вьщеляем старший
swap temp ;старший в младшей тетраде
mul temp,multlO /умножаем на 10, в гО результат умножения mov temp,tempi
/возвращаемся к исходному andi temp,ObOOOOllll ;выделяем младший add temp,гО /получили hex
ret

Более громоздкая задача— преобразование многоразрядных чисел. Преобразовывать BCD-числа, состоящие более чем из одного байта, обратно в hex-формат приходится крайне редко, зато задача прямого преобразования возникает на каждом шагу.
Я здесь приведу отсутствующую в "аппноте" 204 процедуру конвертации чисел, выходящих за рамки 16-разрядного диапазона. Например, такая задача может возникнуть при конструировании многоразрядных счетчиков. Ограничимся диапазоном в 7 десятичных знаков (9 999 999), тогда исходное число будет укладываться в три байта (24 разряда). В целях универсальности в процедуре, которая приводится далее в листинге 7.12, на выходе получается отдельно неупакованный (сразу для индикации) и упакованный десятичный формат. Сократить количество необходимых регистров можно, если большую часть результатов сразу записывать в SRAM — в дальнейшем мы так и будем поступать, а здесь для наглядности используем только регистры.

Отметим, что процедура bin2BCD24 сделана на основе "фирменной" bin2BCDi6 и, как и последняя, содержит хитрый прием с записью значений в регистры по адресам памяти — так можно производить над адресами разные манипуляции, меняя регистры (аналогично адресной арифметике в языке С). Как и в других случаях, сохранена часть оригинальных комментариев из исходной "фирменной" процедуры.

Листинг 7.12
/процедура преобразования трехбайтового hex в упакованный (4 регистра) ;и неупакованный (7 регистров) BCD
/исходное значение в регистрах
.def CountO = r25
.def Count1 = r26
.def Count2 = r27
/на выходе упакованный BCD в регистрах
def tBCDO =rl3 BCD value digits 1 and
def tBCDl =rl4 BCD value digits 3 and
def tBCD2 =rl5 BCD value digit 4,5
def tBCD3 =rl6 BCD value digit 6
на выходе неупакованный BCD в регистрах
def N1 = rl /младший
def N2 = r2
def N3 = r3
def N4 = r4
def N5 = r5
def N6 = гб
def N7 = r7 /старший
/вспомогательные регистры
.def cntl6a =rl8 /счетчик цикла .def tmpl6a =rl9 /временное
значение /адреса регистров в памяти
.equ AtBCDO =13 /address of tBCDO
.equ AtBCD3 =16 /address of tBCD3
bin2BCD24:
ldi cnt16a,24 /Init loop counter
clr
tBCD3
clr
tBCD2
/clear result (4 bytes)
clr
tBCDl
clr
tBCDO
clr
ZH
clear ZH (not needed for AT90Sxx0x)
;_l:lsl Count0 ;shift input value
rol Count1 ;through all bytes
rol Count2 /through all bytes
rol tBCDO
rol tBCDl
rol tBCD2
rol tBCD3
dec cntl6a /decrement loop counter
brne bBCDx 2 , :if counter not zero
/распаковка
ldi temp,0b00001111
mov N1,tBCDO
and N1,temp
mov N2,tBCDO
swap N2
and N2,temp
mov N3,tBCDl
and N3,temp
mov N4,tBCDl
swap N4
and N4,temp
mov N5,tBCD2
and N5,temp
mov N6,tBCD2
swap N6
and N6,temp
mov N7,tBCD3
;Z points to result MSB + 1
Id subi sbrc st Id subi sbrc st cpi brne rjmp
ret / return
bBCDx_2:ldi r30,AtBCD3+l
bBCDx_3:
tmpl?a,7 Z,tmpl6a ZL,AtBCDO bBCDx_3 bBCDx 1
tmpl6a,-Z /get (Z) with pre-decrement tmpl6a,-$03 /add 0x03 tmpl6a,3 /if bit 3 not
clear Z,tmpl6a /store back tmpl6a,Z /get (Z)
tmpl6a,-$30 /add 0x30
/if bit 7 not clear ;store back
/done all three? /loop again if not
=конец bin2BCD24



     
 

Библиотека программиста. 2009.
Администратор: admin@programmer-lib.ru