68HCS12 Microcontroller Programming Question

Thread Starter

stupidlogic

Joined Aug 10, 2010
39
I need to write a program for my microcontrollers class that takes a user inputted value, unit, and desired unit. And then converts the inputted value and unit to the proper value in the desired unit.

The problem I'm up against right now is that the conversion factor for say, inches to cm is 2.54. You can't just input a non-integer number and tell the processor to multiply it together. So I'm wondering what sort of solutions there are for representing a decimal in binary/hex, doing the required operation, and output a final number.

I'm very new to programming in assembly language and using microcontrollers altogether so any help would be awesome. Thanks for the help!
 

Markd77

Joined Sep 7, 2009
2,806
<ed>Have a search for BCD (binary coded decimal) to binary algorithms. That should help with the first part.</ED>

Multiplying by a constant is not too bad.
There is a code generator here, not for your processor but it will give you the general idea. It generated the below for multiply by 2.54 (and some code).
If you need to use fractional numbers you can multiply by a constant (10, 100, etc) to make it all integers then move the decimal place when you display.
Or you can get into the whole floating point numbers thing.

http://www.golovchenko.org/cgi-bin/constdivmul

Rich (BB code):
; ACC = ACC * 2.54
; Temp = TEMP
; ACC size = 8 bits
; Error = 0.5 %
; Bytes order = little endian
; Round = no

; ALGORITHM:
; Clear accumulator
; Add input * 2 to accumulator
; Add input / 2 to accumulator
; Add input / 32 to accumulator
; Move accumulator to result
;
; Approximated constant: 2.53125, Error: 0.344488 %

;     Input: ACC0, 8 bits
;    Output: ACC0 .. ACC1, 10 bits
; Code size: 19 instructions
 

Thread Starter

stupidlogic

Joined Aug 10, 2010
39
Thanks for the help. I am going to try to implement that later on; it would be a lot nicer of an output. I had already used the technique of multiplying the conversions by a constant to keep working on my program and test it in the simulator.

I'm probably going to post my code this afternoon with a few questions on where I'm getting stuck. Any help then would be appreciated, but until then... thanks!
 

Thread Starter

stupidlogic

Joined Aug 10, 2010
39
Below I have posted my code thus far...

The immediate problem I am having is that when it tries to multiply the inputted number by the conversion number, I get zero no matter what. Right now it's loading the wrong numbers into the accumulators I'm using and one of them always ends up zero. I can't figure out why. Any suggestions would be appreciated.

The next problems I'm running into/going to run into is expanding the program for all the units that I need to accommodate for. I also need to have to be able to differentiate between length units and volume units. My idea for that was to maybe create a string with all the length units called length and all the volume units called volume. And then somehow compare the inputted units and desired units with those strings to see if they are contained inside. The it could go to the next sub-routine or throw an error saying that the conversion's not possible. Any ideas of how to implement this or even another more efficient idea?

I'm very new at this so any tutorial websites or whatnot on assembly language would also be helpful. Thank you for your help!


Here is the code:
Rich (BB code):
;********************************************
; Program Description
; A user inputs a value and two unit types into
; the program and does a simple unit conversion.
; Acceptable unit abbreviations and types are:
;   Lengths: in (inches)
;            ft (feet)
;            cm (centimeters)
;            m (meters) 
;   Volumes: L (liters)
;            floz (fluid ounces)
;            qrts (quarts)
;            cups (cups)
; The program also detects whether or not the
; conversion is possible (i.e., must be length
; to length) and whether or not the conversion is
; necessary (i.e., inches to inches).
;*********************************************



; Set the beginning address for DATA
 org $1000

; Define all possible types of units
Foot fcc 'ft'	
 db 0			; null character to terminate string
Inch fcc 'in'	
 db 0			; null character to terminate string
Meter fcc 'm'
 db 0			; null character to terminate string
Centimeter fcc 'cm'
 db 0			; null character to terminate string
Liter fcc 'L'
 db 0			; null character to terminate string
Fluid_Ounce fcc 'floz'
 db 0			; null character to terminate string
Quarts fcc 'qrts'
 db 0			; null character to terminate string
Cups fcc 'cups'
 db 0			; null character to terminate string
Length fcc 'length'
 db 0			; null character to terminate string
Volume fcc 'vol'
 db 0			; null character to terminate string

; Conversion constants
; Since a you can't have non-integer values,
; all conversion factors are multiplied by 1000
; .: all ouputs are in the (N x 10^-3) format

; Length conversions
ftIn equ #12
ftM equ #305
ftCm equ #30480
inM equ #25
inCm equ #2540
mCm equ #100
inFt equ #83
mFt equ #3281
cmFt equ #33
mIn equ #39370
cmIn equ #394
cmM equ #10

; Volume conversions
lFloz equ #33810
lQrts equ #1057
lCups equ #4227
flozQrts equ #31
flozCups equ #125
qrtsCups equ #4
flozL equ #30
qrtsL equ #946
cupsL equ #237
qrtsFloz equ #32
cupsFloz equ #8
cupsQrts equ #250


 
; User designated values
inputUnit fcc 'in'	; string to identify the current unit type
 db 0			; null character to terminate string
desiredUnit fcc 'ft'	; string to identify desired unit type
 db 0			; null character to terminate string
unitValue equ #1

; Set aside space for output
output ds 1


; Beginning address for CODE
 org $2000
main:
; lds #$2000		; initializes the SP
 ldx #inputUnit		; get address of first character
 ldy #desiredUnit	; get address of first character

checkSameUnit:
 ldaa 0,X	; now A has a character in it
 ldab 0,Y	; now B has a character in it

; compare them
 cba
 bne differentUnits
 
; if they are the same, move to next character
 inx
 iny
 
; If at the end of the string(s), stop.
; Look at the next char in string 1.
; If it's the NULL char, check to see 
; if string 2 is NULL too.  If not,
; different strings.

 tst 0,X
 beq foundNullInput		; branch if equal
 
 tst 0,Y
 beq foundNullDesired		; branch if equal
 
 bra checkSameUnit

; if we're here, then found a NULL in inputUnit
foundNullInput:
 tst 0,Y
 beq sameUnits		; if Z set, both strings have NULL
 bne differentUnits

foundNullDesired:
 bra differentUnits
 
; if same unit, set output to 0 and stop
sameUnits:
 clra
 ldaa #0		; stores zero as error code
 staa output
 bgnd			; bgnd halts simulator
 
differentUnits:
 bra FttoIn		; branch to IntoFt subroutine

 ; idea: use test function to find out which subroutine to use

FttoIn:
 clra
 clrb
 
 ldaa unitValue
 ldab inFt		;loads as zero right now
 mul
 std output
 
 
; End the program
 org $FFFE
 dw main
 

Thread Starter

stupidlogic

Joined Aug 10, 2010
39
Well hey, I was able to get everything working properly. If anyone is interested in how I did it take a look below. Code is posted. Thanks for the help.

Rich (BB code):
; Set the beginning address for DATA
 org $1000
 
; Set aside space for output large enough for 16x16 bit operation
outputWord1 dw 0
outputWord2 dw 0
 
; User designated values
inputUnit fcc 'L'	; string to identify the current unit type
 db 0			
desiredUnit fcc 'cm'	; string to identify desired unit type
 db 0		
unitValue dw 10		; numerical value of the current unit

; Define all possible types of units
foot fcc 'ft'	
 db 0		
inch fcc 'in'	
 db 0		
meter fcc 'm'
 db 0			
centimeter fcc 'cm'
 db 0		
liter fcc 'L'
 db 0		
fluidOunce fcc 'floz'
 db 0		
quarts fcc 'qrts'
 db 0		
cups fcc 'cups'
 db 0	
 
; error code
error fcc 'ER'
 db 0		
 
 
; Conversion constants
; Since a you can't have non-integer values,
; all conversion factors are multiplied by 1000
; .: all ouputs are in the (N x 10^-3) format

; Length conversions
ftIn dw 1200
ftM dw 31
ftCm dw 3048
inM dw 3
inCm dw 254
mCm dw 10000
inFt dw 8
mFt dw 328
cmFt dw 3
mIn dw 3937
cmIn dw 39
cmM dw 1

; Volume conversions
lFloz dw 3381
lQrts dw 106
lCups dw 423
flozQrts dw 3
flozCups dw 13
qrtsCups dw 400
flozL dw 3
qrtsL dw 95
cupsL dw 24
qrtsFloz dw 3200
cupsFloz dw 800
cupsQrts dw 25



 org $2000

; figure out what the input unit is
; load input unit and compare to each other unit
; type.  branches when it finds which one it is
findInputUnit:
 ldx #inputUnit
 clra
 ldaa 0,X

 ldy #foot
 clrb
 ldab 0,Y
 cba
 lbeq inputIsFoot

 ldy #inch
 clrb
 ldab 0,Y
 cba
 lbeq inputIsInch
 
 ldy #meter
 clrb
 ldab 0,Y
 cba
 lbeq inputIsMeter
 
 ldy #centimeter
 clrb
 ldab 0,Y
 cba
 lbeq inputIsCentimeter
 
 ldy #liter
 clrb
 ldab 0,Y
 cba
 lbeq inputIsLiter
 
 ldy #fluidOunce
 clrb
 ldab 0,Y
 cba
 lbeq inputIsFluidOunce
 
 ldy #quarts
 clrb
 ldab 0,Y
 cba
 lbeq inputIsQuarts
 
 ldy #cups
 clrb
 ldab 0,Y
 cba
 lbeq inputIsCups
 
 
; use the following set of routines to find desired input
; load desired unit and compare to each other unit
; type.  branches when it finds which one it is, whether or
; not the conervsion is possible and if it's the SAME unit
inputIsFoot:
 ldx #desiredUnit
 clra
 ldaa 0,X
 
 ldy #foot
 clrb
 ldab 0,Y
 cba
 lbeq sameExactUnit
 
 ldy #inch
 clrb
 ldab 0,Y
 cba
 lbeq FttoIn
 
 ldy #meter
 clrb
 ldab 0,Y
 cba
 lbeq FttoM
 
 ldy #centimeter
 clrb
 ldab 0,Y
 cba
 lbeq FttoCm
 
 ldy #liter
 clrb
 ldab 0,Y
 cba
 lbeq impossibleConversion
 
 ldy #fluidOunce
 clrb
 ldab 0,Y
 cba
 lbeq impossibleConversion
 
 ldy #quarts
 clrb
 ldab 0,Y
 cba
 lbeq impossibleConversion
 
 ldy #cups
 clrb
 ldab 0,Y
 cba
 lbeq impossibleConversion
 
inputIsInch:
 ldx #desiredUnit
 clra
 ldaa 0,X
 
 ldy #foot
 clrb
 ldab 0,Y
 cba
 lbeq IntoFt
 
 ldy #inch
 clrb
 ldab 0,Y
 cba
 lbeq sameExactUnit
 
 ldy #meter
 clrb
 ldab 0,Y
 cba
 lbeq IntoM
 
 ldy #centimeter
 clrb
 ldab 0,Y
 cba
 lbeq IntoCm
 
 ldy #liter
 clrb
 ldab 0,Y
 cba
 lbeq impossibleConversion
 
 ldy #fluidOunce
 clrb
 ldab 0,Y
 cba
 lbeq impossibleConversion
 
 ldy #quarts
 clrb
 ldab 0,Y
 cba
 lbeq impossibleConversion
 
 ldy #cups
 clrb
 ldab 0,Y
 cba
 lbeq impossibleConversion
 
inputIsMeter:
 ldx #desiredUnit
 clra
 ldaa 0,X
 
 ldy #foot
 clrb
 ldab 0,Y
 cba
 lbeq MtoFt
 
 ldy #inch
 clrb
 ldab 0,Y
 cba
 lbeq MtoIn
 
 ldy #meter
 clrb
 ldab 0,Y
 cba
 lbeq sameExactUnit
 
 ldy #centimeter
 clrb
 ldab 0,Y
 cba
 lbeq MtoCm
 
 ldy #liter
 clrb
 ldab 0,Y
 cba
 lbeq impossibleConversion
 
 ldy #fluidOunce
 clrb
 ldab 0,Y
 cba
 lbeq impossibleConversion
 
 ldy #quarts
 clrb
 ldab 0,Y
 cba
 lbeq impossibleConversion
 
 ldy #cups
 clrb
 ldab 0,Y
 cba
 lbeq impossibleConversion
 
inputIsCentimeter:
 ldx #desiredUnit
 clra
 ldaa 0,X
 
 ldy #foot
 clrb
 ldab 0,Y
 cba
 lbeq CmtoFt
 
 ldy #inch
 clrb
 ldab 0,Y
 cba
 lbeq CmtoIn
 
 ldy #meter
 clrb
 ldab 0,Y
 cba
 lbeq CmtoM
 
 ldy #centimeter
 clrb
 ldab 0,Y
 cba
 lbeq sameExactUnit
 
 ldy #liter
 clrb
 ldab 0,Y
 cba
 lbeq impossibleConversion
 
 ldy #fluidOunce
 clrb
 ldab 0,Y
 cba
 lbeq impossibleConversion
 
 ldy #quarts
 clrb
 ldab 0,Y
 cba
 lbeq impossibleConversion
 
 ldy #cups
 clrb
 ldab 0,Y
 cba
 lbeq impossibleConversion
 
inputIsLiter:
 ldx #desiredUnit
 clra
 ldaa 0,X
 
 ldy #foot
 clrb
 ldab 0,Y
 cba
 lbeq impossibleConversion
 
 ldy #inch
 clrb
 ldab 0,Y
 cba
 lbeq impossibleConversion
 
 ldy #meter
 clrb
 ldab 0,Y
 cba
 lbeq impossibleConversion
 
 ldy #centimeter
 clrb
 ldab 0,Y
 cba
 lbeq impossibleConversion
 
 ldy #liter
 clrb
 ldab 0,Y
 cba
 lbeq sameExactUnit
 
 ldy #fluidOunce
 clrb
 ldab 0,Y
 cba
 lbeq LtoFloz
 
 ldy #quarts
 clrb
 ldab 0,Y
 cba
 lbeq LtoQrts
 
 ldy #cups
 clrb
 ldab 0,Y
 cba
 lbeq LtoCups
 
inputIsFluidOunce:
 ldx #desiredUnit
 clra
 ldaa 0,X
 
 ldy #foot
 clrb
 ldab 0,Y
 cba
 lbeq impossibleConversion
 
 ldy #inch
 clrb
 ldab 0,Y
 cba
 lbeq impossibleConversion
 
 ldy #meter
 clrb
 ldab 0,Y
 cba
 lbeq impossibleConversion
 
 ldy #centimeter
 clrb
 ldab 0,Y
 cba
 lbeq impossibleConversion
 
 ldy #liter
 clrb
 ldab 0,Y
 cba
 lbeq FloztoL
 
 ldy #fluidOunce
 clrb
 ldab 0,Y
 cba
 lbeq sameExactUnit
 
 ldy #quarts
 clrb
 ldab 0,Y
 cba
 lbeq FloztoQrts
 
 ldy #cups
 clrb
 ldab 0,Y
 cba
 lbeq FloztoCups
 
inputIsQuarts:
 ldx #desiredUnit
 clra
 ldaa 0,X
 
 ldy #foot
 clrb
 ldab 0,Y
 cba
 lbeq impossibleConversion
 
 ldy #inch
 clrb
 ldab 0,Y
 cba
 lbeq impossibleConversion
 
 ldy #meter
 clrb
 ldab 0,Y
 cba
 lbeq impossibleConversion
 
 ldy #centimeter
 clrb
 ldab 0,Y
 cba
 lbeq impossibleConversion
 
 ldy #liter
 clrb
 ldab 0,Y
 cba
 lbeq QrtstoL
 
 ldy #fluidOunce
 clrb
 ldab 0,Y
 cba
 lbeq QrtstoFloz
 
 ldy #quarts
 clrb
 ldab 0,Y
 cba
 lbeq sameExactUnit
 
 ldy #cups
 clrb
 ldab 0,Y
 cba
 lbeq QrtstoCups
 
inputIsCups:
 ldx #desiredUnit
 clra
 ldaa 0,X
 
 ldy #foot
 clrb
 ldab 0,Y
 cba
 lbeq impossibleConversion
 
 ldy #inch
 clrb
 ldab 0,Y
 cba
 lbeq impossibleConversion
 
 ldy #meter
 clrb
 ldab 0,Y
 cba
 lbeq impossibleConversion
 
 ldy #centimeter
 clrb
 ldab 0,Y
 cba
 lbeq impossibleConversion
 
 ldy #liter
 clrb
 ldab 0,Y
 cba
 lbeq CupstoL
 
 ldy #fluidOunce
 clrb
 ldab 0,Y
 cba
 lbeq CupstoFloz
 
 ldy #quarts
 clrb
 ldab 0,Y
 cba
 lbeq CupstoQrts
 
 ldy #cups
 clrb
 ldab 0,Y
 cba
 lbeq sameExactUnit
 
 
; Length conversions
FttoIn:
 ldy unitValue
 ldd ftIn
 emul
 sty outputWord1
 std outputWord2
 bgnd			; bgnd halts simulator
FttoM:
 ldy unitValue
 ldd ftM
 emul
 sty outputWord1
 std outputWord2
 bgnd			; bgnd halts simulator
FttoCm:
 ldy unitValue
 ldd ftCm
 emul
 sty outputWord1
 std outputWord2
 bgnd			; bgnd halts simulator
IntoM:
 ldy unitValue
 ldd inM
 emul
 sty outputWord1
 std outputWord2
 bgnd			; bgnd halts simulator
IntoCm:	
 ldy unitValue
 ldd inCm
 emul
 sty outputWord1
 std outputWord2
 bgnd			; bgnd halts simulator
MtoCm:
 ldy unitValue
 ldd mCm
 emul
 sty outputWord1
 std outputWord2
 bgnd			; bgnd halts simulator
IntoFt:	
 ldy unitValue
 ldd inFt
 emul
 sty outputWord1
 std outputWord2
 bgnd			; bgnd halts simulator
MtoFt:	
 ldy unitValue
 ldd mFt
 emul
 sty outputWord1
 std outputWord2
 bgnd			; bgnd halts simulator
CmtoFt:	
 ldy unitValue
 ldd cmFt
 emul
 sty outputWord1
 std outputWord2
 bgnd			; bgnd halts simulator
MtoIn:	
 ldy unitValue
 ldd mIn
 emul
 sty outputWord1
 std outputWord2
 bgnd			; bgnd halts simulator
CmtoIn:	 
 ldy unitValue
 ldd cmIn
 emul
 sty outputWord1
 std outputWord2
 bgnd			; bgnd halts simulator
CmtoM:	
 ldy unitValue
 ldd cmM
 emul
 sty outputWord1
 std outputWord2
 bgnd			; bgnd halts simulator
	
; Volume conversions
LtoFloz:
 ldy unitValue
 ldd lFloz
 emul
 sty outputWord1
 std outputWord2
 bgnd			; bgnd halts simulator
LtoQrts:
 ldy unitValue
 ldd lQrts
 emul
 sty outputWord1
 std outputWord2
 bgnd			; bgnd halts simulator
LtoCups:
 ldy unitValue
 ldd lCups
 emul
 sty outputWord1
 std outputWord2
 bgnd			; bgnd halts simulator
FloztoQrts:
 ldy unitValue
 ldd flozQrts
 emul
 sty outputWord1
 std outputWord2
 bgnd			; bgnd halts simulator
FloztoCups:
 ldy unitValue
 ldd flozCups
 emul
 sty outputWord1
 std outputWord2
 bgnd			; bgnd halts simulator
QrtstoCups:	
 ldy unitValue
 ldd qrtsCups
 emul
 sty outputWord1
 std outputWord2
 bgnd			; bgnd halts simulator
FloztoL:
 ldy unitValue
 ldd flozL
 emul
 sty outputWord1
 std outputWord2
 bgnd			; bgnd halts simulator
QrtstoL:
 ldy unitValue
 ldd qrtsL
 emul
 sty outputWord1
 std outputWord2
 bgnd			; bgnd halts simulator
CupstoL:
 ldy unitValue
 ldd cupsL
 emul
 sty outputWord1
 std outputWord2
 bgnd			; bgnd halts simulator
QrtstoFloz:
 ldy unitValue
 ldd qrtsFloz
 emul
 sty outputWord1
 std outputWord2
 bgnd			; bgnd halts simulator
CupstoFloz:
 ldy unitValue
 ldd cupsFloz
 emul
 sty outputWord1
 std outputWord2
 bgnd			; bgnd halts simulator
CupstoQrts:
 ldy unitValue
 ldd cupsQrts
 emul
 sty outputWord1
 std outputWord2
 bgnd			; bgnd halts simulator

; goes here if the input unit is the same as the
; desired unit
sameExactUnit:
 clra
 clrb
 ldd #unitValue
 std outputWord2
 bgnd			; bgnd halts simulator
 
; goes here if the conversion trying to be made
; is impossible
impossibleConversion:
 clra
 clrb
 ldd error
 std outputWord1
 std outputWord2

 bgnd			; bgnd halts simulator
 
Top