This is for a PIC, but it should be possible to translate it since it's not that complex. It converts a 16 bit unsigned binary value to 5 packed (two digits per byte) BCD digits. binH and binL contain the 16 bit binary value. count and temp are single byte work areas.
binary_to_bcd bcf STATUS, 0 ; clear the carry bit movlw .16 movwf count clrf tenthousands clrf thousands_and_hundreds clrf tens_and_ones loop16 rlf binL, F rlf binH, F rlf tens_and_ones, F rlf thousands_and_hundreds, F rlf tenthousands, F ; decfsz count, F goto adjDEC RETLW 0 ; adjDEC movlw tens_and_ones movwf FSR call adjBCD ; movlw thousands_and_hundreds movwf FSR call adjBCD ; movlw tenthousands movwf FSR call adjBCD ; goto loop16 ; adjBCD movlw 3 addwf INDF,W movwf temp btfsc temp,3 ; test if result > 7 movwf INDF movlw 0x30 addwf INDF,W movwf temp btfsc temp,7 ; test if result > 7 movwf INDF ; save as MSD RETLW 0
The easiest (and slowest) method is to implement a binary down counter and a BCD up counter. Load the down counter with the binary data. Clear the BCD up counter. Decrement the down counter to zero. For each decrement, increment the BCD counter by one. ~ For a more elegant solution, see this article: BIDEC - A Binary-to-Decimal or Decimal-to-Binary Converter, J. F. Couleur, IRE Transactions on Electronic Computers, Vol. EC-7, pp313-316, IRE, 1958. Regards, Jon
--
The brute force way to do it is to increment a 4 digit BCD counter
then to decrement the 10 bit binary value, sequentially and
repeatedly until the binary value gets to zero, at which time the
BCD counter will have the data encoded properly.
Divide your number by 10. The remainder is the ones value in BCD.
Divide the quotient by 10. The remainder is the tens value in BCD.
Divide the new quotient by 10. The remainder is the hundreds value in BCD.
The final quotient is either 1 or 0 if you really started from 10 bits. It is the thousands value.
You can carry this procedure on indefinitely, and it is a general method for converting from one base to another (so should you want to display things in base 5, now you know how).
--
Tim Wescott
Wescott Design Services
http://www.wescottdesign.com
Posting from Google? See http://cfaj.freeshell.org/google/
Here's a nice page on how to do it with combinational logic...
formatting link
...Jim Thompson
--
| James E.Thompson, P.E. | mens |
| Analog Innovations, Inc. | et |
| Analog/Mixed-Signal ASIC\'s and Discrete Systems | manus |
| Phoenix, Arizona Voice:(480)460-2350 | |
| E-mail Address at Website Fax:(480)460-2142 | Brass Rat |
| http://www.analog-innovations.com | 1962 |
Old Latin teachers never die...they just decline
In article , Tim Wescott wrote: [.. binary to BCD ..]
If you don't have a divide but do know how to add BCD values:
Consider your binary number to be all to the right of the binary point.
X = your number Y = zero Loop 10 times: Y = Y + Y decimal adjust Y ; ie make it a BCD add X = X + X ; Shift the MSB above the "binary point" if Y>=1024 then ; thats 2^10 Y = Y + 1 ; Put the bit in the bottom of Y end if end loop
2X 1024 x 8 PROMs with a look-up table. :-) (can an Atmel do a LUT? I'm pretty sure that doing an LUT with a PIC is a real PITA, if it can be done at all.)
Or, since you have BASIC, you could do the repeated mod 10/divide by 10 loop, as Tim Wescott suggested. It'd be nice if high-level languages had a facility to do an integer divide and get both the quotent and remainder back in one instruction.
An improvement to this method would be to start with the most significant decimal digit, ie while (number is > 1000) sub 1000 from number and inc 4th digit while (number is > 100) sub 100 from number and inc 3rd digit etc...
then you only have to count up to 36
if you have a lot of digits you could use a digit index and a variabvle to hold the 1000/100/10 value etc.
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.