ASCII is a mapping between integers and characters.

For example,

'0' has the ASCII value 0x30.

'1' has ASCII value 0x31.

'9' has ASCII value 0x39.

'A' has ASCII value 0x41.

'B' has ASCII value 0x42.

The LCD panel accepts ASCII values for input.

Binary to ASCII Conversions

Suppose we want to convert a one-byte hexadecimal value into a two-byte ASCII sequence.

For example, 0xA5 = 0b10100101. Converted to ASCII would be 'A' = 0x41 and '5' = 0x35.

In order to convert this to ASCII, we'll need to deal with the lower four bits (lower nibble) and upper four bits (upper nibble) independently.

We can get the lower nibble by masking the upper four bits to zero.

If 0xA5 is in R20,

andi r20, 0x0f
masks the upper nibble to produce 0x05 = 0b00000101.
* Next we need to add 0x30 (since '0' = 0x30):
subi r20, -'0'

We use SUBI because the ATmega32 does not have an ADDI instruction.

Adding 0x30 to 0x05 gets us: 0x35 which is '5'.

This works as long as the result is between '0' and '9', but if the result is greater than '9', then we need a letter.

We can get this by adding 7... 'A' = 0x41 = 0x40 + 7.

cpi r20, '9' + 1
brlo done
subi r20, -7
done:
ret

Example Program

The following instructions may be useful:

SWAPRd swaps the upper and lower nibbles — this can be used to isolate the upper nibble.

SUBIRd, value — subtracts value from Rd (there is no add immediate instruction.

CPIRd, value — compares value and the value stored in Rd.

BRSHaddress — (BRanch if Same or Higher) branch to address if value in Rd is greater than or equal (unsigned arithmetic) to value in the preceeding CPI instruction.

Don't use BRGE (BRanch if Greater than or Equal) which uses signed arithmetic.

Flowchart for Conversion Function

The following generates a two byte ASCII sequence that represents the value stored in r17 and stores the ASCII values in r16 (most significant) and r17 (least significant).

It makes use of a convert_lower_nibble function shown below.

Flowchart for Function that Converts a Nibble to an ASCII value

; Converts lower nibble of r20 into its ASCII equivalent
; The result is stored in r20
convert_lower_nibble:
andi r20, 0x0f ; masking: clear upper nibble
; Convert to ASCII
subi r20, -'0' ; add '0' to r20
; Correct conversion if digit is greater than '9'
cpi r20, '9' + 1
brlo done
subi r20, -7
done:
ret