- Vote on answer
- posted
19 years ago
BIN 2 BCD for AVR
- Vote on answer
- posted
19 years ago
- Vote on answer
- posted
19 years ago
- Vote on answer
- posted
19 years ago
- Vote on answer
- posted
19 years ago
- Vote on answer
- posted
19 years ago
- Vote on answer
- posted
19 years ago
- Vote on answer
- posted
19 years ago
- Vote on answer
- posted
19 years ago
- Vote on answer
- posted
19 years ago
- Vote on answer
- posted
19 years ago
- Vote on answer
- posted
19 years ago
- Vote on answer
- posted
19 years ago
- Vote on answer
- posted
19 years ago
- Vote on answer
- posted
19 years ago
- Vote on answer
- posted
19 years ago
- Vote on answer
- posted
19 years ago
- Vote on answer
- posted
19 years ago
- Vote on answer
- posted
19 years ago
- Vote on answer
- posted
19 years ago
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 bin2BCDpublic 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_Modulepublic 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), а только последовательность действий.