BIN 2 BCD for AVR

Loading thread data ...
Reply to
Alexey V Bugrov
Reply to
Unrau Alexander
Reply to
Alexey V Bugrov
Reply to
Unrau Alexander
Reply to
Unrau Alexander
Reply to
Alexey V Bugrov
Reply to
Vladimir Vassilevsky
Reply to
Alexey V Bugrov
Reply to
Alexander Derazhne

Wed, 03 Nov 2004 20:25:34 +0300 Unrau Alexander wrote to All:

UA> Блин! И ведь пашет. UA> А название у этого алгоритма есть? UA> И существует ли что-то подобное для преобразования дробной части числа UA> (битов после запятой)?

Может кому-то пригодится. Как-то попались две мессаги на эту тему, я их затарил. А позже они очень пригодились, когда пришлось реализовывать подобное на MSP430 - помогли быстро разобраться с алгоритмом. Мессаги следующие:

Первая.

=========Beginning of the citation============== From: "Alexander Volkov" snipped-for-privacy@p55.f.n5051.z2.fidonet.org>

Subject: Re: BinBcd Date: 18 февраля 2002 г. 13:10

Привет, Mihail! MP> Подскажите алгоритм сабжа для 16 разрядного числ. MP> Hужно реализовать на 8051. Алгоритм простой: сначала определяется цифра десятков тысяч вычитанием 10000 из исходного числа, затем цифра тысяч последовательным вычитанием 1000, затем цифры сотен, десятков. Остаток дает цифру единиц. Алгоритм менее простой:десятичный эквивалент числа Х можно получить, сдвигая двоичное число влево и подавая выдвигаемые двоичные цифры в младший разряд десятичного регистра. Одновременно со сдвигом двоичного регистра необходимо удваивать содержимое десятичного регистра. Метод основан на представлении числа в виде полинома Горнера: Х=Xn-1*2^(n-1)+Xn-2*2^(n-2)+...+X1*2+X0 - это дв.представление X=(...(Xn-1*2+Xn-2)*2+...+X1)*2+X0 - это по Горнеру

PS: А исходник у меня есть в кодах К580ИК80(это не одно и тоже с 8051 ?)

С наилучшими пожеланиями. Alexander. =========The end of the citation================

Вторая.

=========Beginning of the citation============== From: "Alexander Volkov" snipped-for-privacy@p55.f.n5051.z2.fidonet.org>

Subject: Re: BinBcd Date: 20 февраля 2002 г. 1:16

Привет, Roman!

RS> сдвигая

RS> необходимо

RS> числа RS> непонятно. точнее то, что тут написано никак не является сабжем. Абисняю на примере. Имеем дв.код 1111 , т.е. 15 1) выдвигаем влево 1-ю ед. из дв.рг 2) удваиваем сод. дес.рг (0*2=0000_0000) не забываем, что удвоение - десятичное, т.е. с коррекцией 3) вдвигаем выдв.1 в дес.рг(0000_0001) 4) шаг 1 5) шаг 2 (1*2=0000_0010) 6) шаг 3 (0000_0011) 7) шаг 1 8) шаг 2 (3*2=0000_0110) 9) шаг 3 (0000_0111) 10) шаг 1 11) шаг 2 Внимание! Самое интересное: в данном случае удвоение происходит так: т.к. исх.число >= 5 , то вводим коррекцию +3 получаем 0000_1010, удваиваем ЭТО число (0001_0100) 12)шаг 3 (0001_0101) Это что? Вроде бы дв/дес. 15. Hе так ли ?

С наилучшими пожеланиями. Alexander. =========The end of the citation================

На основе этого код для MSP430 (для IAR'овского ассемблера) выглядит так:

****************************************************** module bin2BCD

public bin2BCD16

; r11 - bit counter

; r12 - input binary number ; r13 - result (low: 4 digits) ; r14 - addr ; r15 - result (high: 1 digit)

rseg CODE(1)

;---------------------------------------------------- bin2BCD16: push r11 push r10

mov.w #16,r11 ; bit count clr r13 clr r15

;----------------------------------- ; ; собственно преобразование ; convert: clr r10 rla r12 rlc r10

dadd.w r13,r13 dadd.w r15,r15 dadd.w r10,r13 dadd.w #0,r15

dec r11 jne convert ;-----------------------------------

; ; дальше просто распаковка десячисных цифр каждую в отдельный байт, ; к самому алгоритму отношения не имеет. ; ;

unpack: call #extract_byte swpb r13 call #extract_byte mov.w r15,r12 call #store_byte

pop r10 pop r11 ret ;----------------------------------- extract_byte: mov.w r13,r12 call #store_byte mov.w r13,r12 call #get_high_nibble call #store_byte ret ;----------------------------------- store_byte: bic.w #0xfff0,r12 mov.b r12,0(r14) inc r14 ret ;----------------------------------- get_high_nibble: rlc.b r12 rlc.b r12 rlc.b r12 rlc.b r12 rlc.b r12 ret ;------------------------------------------------------------

end

******************************************************

Сама реализация алгоритма очень короткая и эффективная благодаря наличию арифметических команд с десятичной коррекцией (то самое прибавление по условию).

Потом, правда, нашел похожую реализацию в одной из аппликух, но не жалею о проделанной работе, было интересно разобраться. :)

Для AVR есть у Atmel подобная функция, написанная на асме. Адаптированная под IAR она выглядит так:

Сишный прототип: void bin2BCD16(word num, byte* Buf);

****************************************************** module Num_2_BCD_Module

public bin2BCD16

rseg CODE:CODE:NOROOT(1)

;--------------------------------------------------------------------------- ;* ;* "bin2BCD16" - 16-bit Binary to BCD conversion ;* ;* This subroutine converts a 16-bit number (fbinH:fbinL) to a 5-digit ;* packed BCD number represented by 3 bytes (tBCD2:tBCD1:tBCD0). ;* MSD of the 5-digit number is placed in the lowermost nibble of tBCD2. ;* ;* Number of words :25 ;* Number of cycles :751/768 (Min/Max) ;* Low registers used :3 (tBCD0,tBCD1,tBCD2) ;* High registers used :4(fbinL,fbinH,cnt16a,tmp16a) ;* Pointers used :Z ;* ;---------------------------------------------------------------------------

;***** Subroutine Register Variables #define zl r30 #define zh r31

#define AtBCD0 0 // address of tBCD0 #define AtBCD2 1 // address of tBCD2

#define tBCD0 r0 // BCD value digits 1 and 0 #define tBCD1 r1 // BCD value digits 3 and 2 #define tBCD2 r2 // BCD value digit 4 #define fbinL r16 // binary value Low byte #define fbinH r17 // binary value High byte #define cnt16a r20 // loop counter #define tmp16a r21 // temporary value

#define rtmp tmp16a #define BCD_AddrLow r18 #define BCD_AddrHigh r19

bin2BCD16: ldi cnt16a,16 ;Init loop counter clr tBCD2 ;clear result (3 bytes) clr tBCD1 clr tBCD0 clr zh ;clear ZH (not needed for AT90Sxx0x)

bBCDx_1: lsl fbinL ;shift input value rol fbinH ;through all bytes rol tBCD0 ; rol tBCD1 rol tBCD2 dec cnt16a ;decrement loop counter brne bBCDx_2 ;if counter not zero

;fill array and ... mov zl,BCD_AddrLow mov zh,BCD_AddrHigh mov rtmp,tBCD0 andi rtmp,0x0f st z+,rtmp ;BCD[0] = value0 (LSD) swap tBCD0 mov rtmp,tBCD0 andi rtmp,0x0f st z+,rtmp ;BCD[1] = value1 mov rtmp,tBCD1 andi rtmp,0x0f st z+,rtmp swap tBCD1 ;BCD[2] = value2 mov rtmp,tBCD1 andi rtmp,0x0f st z+,rtmp ;BCD[3] = value3 st z,tBCD2 ;BCD[4] = value4 (MSD) ret ; ... return

bBCDx_2: ldi r30,AtBCD2+1 ;Z points to result MSB + 1

bBCDx_3: ld tmp16a,-z ;get (Z) with pre-decrement subi tmp16a,-$03 ;add 0x03 sbrc tmp16a,3 ;if bit 3 not clear st z,tmp16a ; store back ld tmp16a,z ;get (Z) subi tmp16a,-$30 ;add 0x30 sbrc tmp16a,7 ;if bit 7 not clear st z,tmp16a ; store back cpi zl,AtBCD0 ;done all three? brne bBCDx_3 ;loop again if not rjmp bBCDx_1

end

Это, кстати, обсосано в соответствующей аппликухе. Только там принцип не объяснен (afair), а только последовательность действий.

Reply to
Harry Zhurov

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.