âÌÉÎ! é ×ÅÄØ ÐÁÛÅÔ. á ÎÁÚ×ÁÎÉÅ Õ ÜÔÏÇÏ ÁÌÇÏÒÉÔÍÁ ÅÓÔØ? é ÓÕÝÅÓÔ×ÕÅÔ ÌÉ ÞÔÏ-ÔÏ ÐÏÄÏÂÎÏÅ ÄÌÑ ÐÒÅÏÂÒÁÚÏ×ÁÎÉÑ ÄÒÏÂÎÏÊ ÞÁÓÔÉ ÞÉÓÌÁ (ÂÉÔÏ× ÐÏÓÌÅ ÚÁÐÑÔÏÊ)?
ðÏÐÒÏÂÏ×ÁÌ ÄÌÑ 32-È ÒÁÚÒÑÄÏ×. ðÏÌÕÞÉÌÓÑ ÔÁËÏÊ ÔÅÓÔÉË:
unsigned long long bin2bcd(unsigned int n) { int i; unsigned long long l = 0ULL; for(i=0; i<32; i++) { l <<= 1; if(n&0x80000000) l |= 0x00000001; n <<= 1;
if(i==31) break;
if( (l & 0x000000000FULL) > 0x0000000004ULL) l += 0x0000000003ULL; if( (l & 0x00000000F0ULL) > 0x0000000040ULL) l += 0x0000000030ULL; if( (l & 0x0000000F00ULL) > 0x0000000400ULL) l += 0x0000000300ULL; if( (l & 0x000000F000ULL) > 0x0000004000ULL) l += 0x0000003000ULL; if( (l & 0x00000F0000ULL) > 0x0000040000ULL) l += 0x0000030000ULL; if( (l & 0x0000F00000ULL) > 0x0000400000ULL) l += 0x0000300000ULL; if( (l & 0x000F000000ULL) > 0x0004000000ULL) l += 0x0003000000ULL; if( (l & 0x00F0000000ULL) > 0x0040000000ULL) l += 0x0030000000ULL; if( (l & 0x0F00000000ULL) > 0x0400000000ULL) l += 0x0300000000ULL; if( (l & 0xF000000000ULL) > 0x4000000000ULL) l += 0x3000000000ULL; }
return l; }
HÕ Á ÄÌÑ ÍÎÏÇÏÒÁÚÒÑÄÎÙÈ ÐÒÏÃÅÓÓÏÒÏ× ×ÙÇÏÄÎÅÅ ×ÉÄÉÍÏ ÔÁË:
unsigned long long bin2bcd(unsigned int n) { int i; unsigned long long l = 0ULL; for(i=0; i<32; i++) { l <<= 1; if(n&0x80000000) l |= 0x00000001; n <<= 1;
if(i==31) break;
unsigned long long ll = ( (l>>3) | ((l>>2) & ((l>>1)|l) ) ) &
åÓÌÉ ÎÁ ÎÅÇÏ ÕÖÅ ÎÁ×ÅÓÉÌÉ ÔÅËÓÔÏ×ÙÅ ÐÒÏÔÏËÏÌÙ Ó ÄÅÓÑÔÉÞÎÙÍÉ ÞÉÓÌÁÍÉ ÐÏ×ÅÒÈ tcp/ip, sprintf ÕÖÅ ÎÉÞÅÇÏ ÎÅ ÐÒÉÂÁ×ÉÔ É ÎÅ ÕÂÁ×ÉÔ, ÎÏ ÂÕÄÅÔ ÐÒÉ×ÙÞÎÅÅ É ÐÒÏÝÅ ÞÉÔÁÔØ.
ó Õ×ÁÖÅÎÉÅÍ, äÉÍÁ ïÒÌÏ×.
H
Harry Zhurov
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'овского ассемблера) выглядит так:
Сама реализация алгоритма очень короткая и эффективная благодаря наличию арифметических команд с десятичной коррекцией (то самое прибавление по условию).
Потом, правда, нашел похожую реализацию в одной из аппликух, но не жалею о проделанной работе, было интересно разобраться. :)
Для AVR есть у Atmel подобная функция, написанная на асме. Адаптированная под IAR она выглядит так:
;--------------------------------------------------------------------------- ;* ;* "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 ;* ;---------------------------------------------------------------------------
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), а только последовательность действий.
Join the Discussion
Have something to add? Share your thoughts — no account required.
Didn't find your answer?
Ask the community — no account required
Report Content
You are reporting this content to the moderators. They will look at it
ASAP.