## A routine to convert 16bits(hex) to decimal number

7 posts / 0 new
Author
Message

I am doing a small project to control a Photographic camera to do panoramic pictures (360º), to offer to my son, that is a photography lover.

For that project I need to convert a word (16 bit counter) to a decimal number for later convert it ti ASCII. I only work in assembler (I do not know C, I plan to learn), I know a way how to do it, but I do not know if it is the better way. The way I am thinking is decrement the word and increment a nibble and test for hex A if A clear the nibble and add one to next nibble and so forth till the end. Is there a better and faster way to do it?

Thanks for help.

Manuel

Total votes: 0

I used to use repeated subtraction with a 6502. You have indexed addressing with the AVR, so you can do the same thing.

0. Table of decades: 10000, 1000, 100, 10, 1, 0
1. Start with decade = 10000, digit_position = 0.
2. digit = '0'
3. while (number >= decade) increment digit, subtract decade
4. increment position, use next decade from table
5. if decade is not 0 then go to stage 2.
6. all 5 digits are done.

You will find this method is quite fast enough. The alternative is to use division. The advantage of which is that you will probably want a division subroutine anyway.

You should find Atmel application notes that will give you addition, subtraction, comparison, multiplication, division subroutines. Just put all these in a file, and call them as required.

David.

Total votes: 0

I'll bet the GCC source of itoa() is written in assembler - seek that out and you probably have a ready made solution (that can do any radix)

Total votes: 0
```.def    a0              = r16
.def    a1              = r17
.def    a2              = r18
.def    a3              = r19
.def    a4              = r20
;************************************************************************
;*                                                                      *
;*                      binary to ASCII decimal conversion              *
;*                                                                      *
;************************************************************************
;input: a1, a0 = 16 bit value 0 ... 65535
;output: a4, a3, a2, a1, a0 = digits
;cycle: 27 .. 183
;bytes: 42
;
binbcd:
ldi     a4, -1 + '0'
_bib1:  inc     a4
subi    a0, low(10000)
sbci    a1, high(10000)
brcc    _bib1

ldi     a3, 10 + '0'
_bib2:  dec     a3
subi    a0, low(-1000)
sbci    a1, high(-1000)
brcs    _bib2

ldi     a2, -1 + '0'
_bib3:  inc     a2
subi    a0, low(100)
sbci    a1, high(100)
brcc    _bib3

ldi     a1, 10 + '0'
_bib4:  dec     a1
subi    a0, -10
brcs    _bib4

subi    a0, -'0'
ret
;------------------------------------------------------------------------```

Peter

Total votes: 0

danni,
I like your routine. Far better than using index registers and tables.

David.

Total votes: 0

Hello all!

Thanks for the information/help. Your suggestion are very good and saves a lot of code.

Regards,
Manuel

Total votes: 0

Interesting project! I did something that sounds much like what you are describing using a stepper motor and a high resolution CCD camera.

The AVR would move the stepper one degree (or less) at a time and then allow the computer program to capture a single vertical line from the camera. After a full stepper rotation, a 360 degree seamless photo was aquired. It took almost a minute to get the full image.

The photo had a final resolution of about 3500x1000, and was cool to look at as it seemed to never end.

If you want a really high res. image, a scanner CCD can be hacked fairly easy as it is nothing more than a triple shift register.

When you get your project done, I would like to see your results.

Brad

I Like to Build Stuff : http://www.AtomicZombie.com