
Introduction
This discussion deals with the conversion of natural binary quantities to BCD, suitable for display on a serial LCD or monitor. Routines are presented which accept either one or two natural binary bytes and display them on the serial LCD in decimal.
Program LCD_CTRL.ASM
Another discussion presents some simple routines which may be included in your application to control a serial LCD. These routines include;
LCD_CLR ; clears serial LCD LCD_LINE1 ; locates cursor at beginning of line 1 LCD_LINE2 ; same except line 2 LCD_CHAR ; displays the character in W on LCD LCD_VAL ; converts quantity in W and displays the two ; characters
For example, assume you are making measurements using a DS1621 Digital Thermometer and after each reading you have the 8-bit representation in variable T_C. Assume the measured temperature is 104 degrees C.
One might be tempted to;
MOVF T_C, W CALL LCD_VAL
The result which appears on the LCD panel will be 68. Note that the value in T_C is stored in natural binary and thus the result is displayed in hexadecimal. This is perfectly adequate for debugging, but Americans rejected the metric system. Even if they accept degrees C, they sure are not going to go for degrees C displayed in hexadecimal; "The temperature today is 1EH degrees C".
Program BCD_1.ASM
Thus, program BCD_1.ASM presents a program which allows you to do this;
MOVF T_C, W MOVWF LO_BYTE CALL BCD_1
This will cause the temperature to appear in decimal as 104, not as 68.
The technique used is to successively subtract 100 from LO_BYTE while incrementing DEC_COUNT in a BCD fashion and then outputting DEC_COUNT on the serial LCD. If the hundreds digit is zero, it is replaced with a space.
The remainder of LO_BYTE is then decremented, while incrementing DEC_COUNT in a BCD fashion. DEC_COUNT is then displayed on the serial LCD.
Program BCD_2.ASM
Program BCD_2.ASM extends this to a two byte natural binary quantity, but is limited to values in the range 0000H - 270FH or 0 - 9999 decimal. The natural binary quantity to be displayed in decimal is transferred to subroutine BCD_2 using variables H_BYTE and LO_BYTE. The technique is similar to that used in BCD_1.ASM, except the successive subtraction of 100s involves borrowing from the HI_BYTE. Note that leading zero suppression is not implelented in BCD_2.ASM. Note that both of these rouyines require use of program LCD_CTRL.ASM.

; BCD_1.ASM ; ; Illustrates how to convert a one byte natural binary quantity to BCD. ; This is limited to FF H or 255 decimal. ; ; The result is output to a serial LCD. If the hundreds character is 0 ; it is suppressed. ; ; The natural binary quantity is passed to subroutine BCD_1 in variable ; LO_BYTE. ; ; The algorithm is one of successively subtracting 100 from the one byte ; natural binary while incrementing a variable DEC_COUNT in a BCD ; fashion. This is then output to serial LCD. If it is zero, a space is ; ouput in place of the leading. ; ; The remainder is then decremented in a natural binary fashion while ; incrementing DEC_COUNT in BCD. DEC_COUNT is then output to the serial ; LCD. ; ; Note that LCD_CTRL.ASM is included at the end of the program. ; ; Copyright, Peter H. Anderson, Morgan State University, July 3, '97 LIST p=16c84 ; these lines not required when included in ; another file #include <c:\mplab\p16c84.inc> __CONFIG 11h CONSTANT VARS=0CH LO_BYTE EQU VARS+0 DEC_COUNT EQU VARS+1 ; used by BCD_1_BYTE routine T_C EQU VARS+2 ; used for illustration ORG 000H MAIN: ; as an example, perform a temperature measurement ; assume result is in T_C MOVLW 78H ; but i will dummy it to 120 degrees MOVWF T_C CALL LCD_CLR CALL LCD_LINE1 MOVF T_C, W ; get the temperature MOVWF LO_BYTE ; place it in LO_BYTE CALL BCD_1_BYTE ; convert to BCD and display on serial LCD DONE: ; endless loop GOTO DONE BCD_1_BYTE: BCD_1_HUNDS: CLRF DEC_COUNT BCD_1_HUNDS1: MOVLW .100 SUBWF LO_BYTE, F ; LO_BYTE=LO_BYTE-100 BTFSS STATUS, C ; no borrow GOTO BCD_1_HUNDS2 CALL INC_DEC_COUNT ; if no borrow GOTO BCD_1_HUNDS1 ; keep going BCD_1_HUNDS2: MOVF DEC_COUNT, W ; get the count BTFSC STATUS, Z ; if not zero MOVLW " " ; otherwise put in a space CALL LCD_VAL ; and display it MOVLW .100 ADDWF LO_BYTE, F ; add back any falsely subtracted 100 BCD_1_UNITS: CLRF DEC_COUNT ; now for the units BCD_1_UNITS1: MOVLW .1 SUBWF LO_BYTE, F BTFSS STATUS, C ; did not go from 00 to FF GOTO BCD_1_UNITS2 ; done with units CALL INC_DEC_COUNT ; else increment and keep going GOTO BCD_1_UNITS1 BCD_1_UNITS2: MOVF DEC_COUNT, W ; get the number of units CALL LCD_VAL ; and display RETURN INC_DEC_COUNT: ; increments counter in BCD fashion INCF DEC_COUNT, F MOVF DEC_COUNT, W ANDLW 0FH SUBLW .9 ; W = low nibble - 9 BTFSC STATUS, C ; low nibble is in range of A - F GOTO INC_DEC_COUNT_DONE MOVF DEC_COUNT, W ADDLW .6 MOVWF DEC_COUNT INC_DEC_COUNT_DONE: RETURN #include <a:\lcd\lcd_ctrl.asm> END

; BCD_2.ASM
;
; Illustrates how to convert a two byte natural binary quantity to BCD.
; This is limited to XXXX H or 9999 decimal.
;
; The result is output to a serial LCD. There is no leading zero
; suppression.
;
; The natural binary quantity is passed to subroutine BCD_2 in variables
; HI_BYTE and LO_BYTE.
;
; The algorithm is one of successively subtracting 100 from the two byte
; natural binary while incrementing a variable DEC_COUNT in a BCD fashion.
; This is then output to serial LCD.
;
; The remainder is then decremented in a natural binary fashion while
; incrementing DEC_COUNT in BCD. DEC_COUNT is then output to the serial
LCD.
;
; Note that LCD_CTRL.ASM is included at the end of the program.
;
; Copyright, Peter H. Anderson, Morgan State University, July 3, '97
LIST p=16c84 ; these lines not required when included in
; another file
#include <c:\mplab\p16c84.inc>
__CONFIG 11h
CONSTANT VARS=0CH
HI_BYTE EQU VARS+0
LO_BYTE EQU VARS+1
DEC_COUNT EQU VARS+2 ; used by BCD_2_BYTE routine
ORG 000H
MAIN:
CALL LCD_CLR
CALL LCD_LINE1
MOVLW 3H ; dummy up 03CA H
MOVWF HI_BYTE
MOVLW 0CAH
MOVWF LO_BYTE
CALL BCD_2_BYTE ; display BCD value on serial LCD
DONE:
GOTO DONE
BCD_2_BYTE:
BCD_2_HUNDS:
CLRF DEC_COUNT
BCD_2_HUNDS1:
MOVLW .100
SUBWF LO_BYTE, F ; LO_BYTE=LO_BYTE-100
BTFSS STATUS, C ; no borrow
GOTO HUNDS_BORROW
CALL INC_DEC_COUNT ; if no borrow
GOTO BCD_2_HUNDS1 ; keep going
HUNDS_BORROW:
MOVLW .1
SUBWF HI_BYTE, F
BTFSS STATUS, C ; did not go from 00 to FF
GOTO BCD_2_HUNDS2 ; done with subtracting 100s
CALL INC_DEC_COUNT ; if not done
GOTO BCD_2_HUNDS1 ; keep going
BCD_2_HUNDS2:
MOVF DEC_COUNT, W ; get the count
CALL LCD_VAL ; and display it
MOVLW .100
ADDWF LO_BYTE, F ; add back any falsely subtracted 100
BCD_2_UNITS:
CLRF DEC_COUNT ; now for the units
BCD_2_UNITS1:
MOVLW .1
SUBWF LO_BYTE, F
BTFSS STATUS, C ; did not go from 00 to FF
GOTO BCD_2_UNITS2 ; done with units
CALL INC_DEC_COUNT ; else increment and keep going
GOTO BCD_2_UNITS1
BCD_2_UNITS2:
MOVF DEC_COUNT, W ; get the number of units
CALL LCD_VAL ; and display
RETURN
INC_DEC_COUNT: ; increments counter in BCD fashion
INCF DEC_COUNT, F
MOVF DEC_COUNT, W
ANDLW 0FH
SUBLW .9 ; W = low nibble - 9
BTFSC STATUS, C ; low nibble is in range of A - F
GOTO INC_DEC_COUNT_DONE
MOVF DEC_COUNT, W
ADDLW .6
MOVWF DEC_COUNT
INC_DEC_COUNT_DONE:
RETURN
#include <a:\lcd\lcd_ctrl.asm>
END
