[ Pobierz całość w formacie PDF ]
; You need to convert this into a floating point number in the range from 0.00 to 5.00 Volt
; The program scheme:
; 1. Multiplication by 502 (hex 01F6).That step multiplies by 500, 256 and divides by 255 in one step!
; 2. Round the result and cut the last byte of the result. This step divides by 256 by ignoring the last byte of the result.
; Before doing that, bit 7 is used to round the result.
; 3. Convert the resulting word to ASCII and set the correct decimal sign. The resulting word in the range from 0 to 500
; is displayed in ASCII-characters as 0.00 to 5.00.
; The registers used:
; The routines use the registers R8..R1 without saving these before. Also required is a multipurpose register called rmp,
; located in the upper half of the registers. Please take care that these registers don't conflict with the register use in the
; rest of your program.
; When entering the routine the 8-bit number is expected in the register R1. The multiplication uses R4:R3:R2 to hold
; the multiplicator 502 (is shifted left max. eight times during multiplication). The result of the multiplication is calculated
; in the registers R7:R6:R5. The result of the so called division by 256 by just ignoring R5 in the result, is in R7:R6. R7:R6
; is rounded, depending on the highest bit of R5, and the result is copied to R2:R1.
; Conversion to an ASCII-string uses the input in R2:R1, the register pair R4:R3 as a divisor for conversion, and places the
; ASCII result string to R5:R6:R7:R8 (R6 is the decimal char).
; Other conventions:
; The conversion uses subroutines and the stack.The stack must work fine for the use of three levels (six bytes SRAM).
Avr-Asm-Tutorial 39 http://www.avr-asm-tutorial.net
; Conversion times:
; The whole routine requires 228 clock cycles maximum (converting $FF), and 79 clock cycles minimum (converting $00).
; At 4 MHz the times are 56.75 microseconds resp. 17.75 microseconds.
; Definitions:
; Registers
.DEF rmp = R16 ; used as multi-purpose register
; AVR type: Tested for type AT90S8515, only required for stack setting, routines work fine with other AT90S-types also
.NOLIST
.INCLUDE "8515def.inc"
.LIST
; Start of test program
; Just writes a number to R1 and starts the conversion routine, for test purposes only
.CSEG
.ORG $0000
rjmp main
main:
ldi rmp,HIGH(RAMEND) ; Set the stack
out SPH,rmp
ldi rmp,LOW(RAMEND)
out SPL,rmp
ldi rmp,$FF ; Convert $FF
mov R1,rmp
rcall fpconv8 ; call the conversion routine
no_end: ; unlimited loop, when done
rjmp no_end
; Conversion routine wrapper, calls the different conversion steps
fpconv8:
rcall fpconv8m ; multiplicate by 502
rcall fpconv8r ; round and divide by 256
rcall fpconv8a ; convert to ASCII string
ldi rmp,'.' ; set decimal char
mov R6,rmp
ret ; all done
; Subroutine multiplication by 502
fpconv8m:
clr R4 ; set the multiplicant to 502
ldi rmp,$01
mov R3,rmp
ldi rmp,$F6
mov R2,rmp
clr R7 ; clear the result
clr R6
clr R5
fpconv8m1:
or R1,R1 ; check if the number is all zeros
brne fpconv8m2 ; still one's, go on convert
ret ; ready, return back
fpconv8m2:
lsr R1 ; shift number to the right (div by 2)
brcc fpconv8m3 ; if the lowest bit was 0, then skip adding
add R5,R2 ; add the number in R6:R5:R4:R3 to the result
adc R6,R3
adc R7,R4
fpconv8m3:
lsl R2 ; multiply R4:R3:R2 by 2
rol R3
rol R4
rjmp fpconv8m1 ; repeat for next bit
; Round the value in R7:R6 with the value in bit 7 of R5
fpconv8r:
clr rmp ; put zero to rmp
lsl R5 ; rotate bit 7 to carry
adc R6,rmp ; add LSB with carry
adc R7,rmp ; add MSB with carry
mov R2,R7 ; copy the value to R2:R1 (divide by 256)
mov R1,R6
ret
; Convert the word in R2:R1 to an ASCII string in R5:R6:R7:R8
fpconv8a:
clr R4 ; Set the decimal divider value to 100
ldi rmp,100
mov R3,rmp
rcall fpconv8d ; get ASCII digit by repeated subtraction
mov R5,rmp ; set hundreds string char
ldi rmp,10 ; Set the decimal divider value to 10
mov R3,rmp
rcall fpconv8d ; get the next ASCII digit
mov R7,rmp ; set tens string char
ldi rmp,'0' ; convert the rest to an ASCII char
add rmp,R1
mov R8,rmp ; set ones string char
ret
Avr-Asm-Tutorial 40 http://www.avr-asm-tutorial.net
; Convert binary word in R2:R1 to a decimal digit by substracting the decimal divider value in R4:R3 (100, 10)
fpconv8d:
ldi rmp,'0' ; start with decimal value 0
fpconv8d1:
cp R1,R3 ; Compare word with decimal divider value
cpc R2,R4
brcc fpconv8d2 ; Carry clear, subtract divider value
ret ; done subtraction
fpconv8d2:
sub R1,R3 ; subtract divider value
sbc R2,R4
inc rmp ; up one digit
rjmp fpconv8d1 ; once again
; End of conversion test routine
Example 2: 10-bit-AD-converter with fixed decimal output
This example is a bit more complicated. Refer to the website if you need it.
Avr-Asm-Tutorial 41 http://www.avr-asm-tutorial.net
Annex
Commands sorted by function
For the abbreviations used see the list of abbreviations.
Function Subfunction Command Flags Clk
0 CLR r1 Z N V 1
Register
255 SER rh 1
set
Constant LDI rh,c255 1
Register => Register MOV r1,r2 1
SRAM => Register, direct LDS r1,c65535 2
SRAM => Register LD r1,rp 2
SRAM => Register and INC LD r1,rp+ 2
DEC, SRAM => Register LD r1,-rp 2
SRAM, displaced => Register LDD r1,ry+k63 2
Port => Register IN r1,p1 1
Stack => Register POP r1 2
Copy
Program storage Z => R0 LPM 3
Register => SRAM, direct STS c65535,r1 2
Register => SRAM ST rp,r1 2
Register => SRAM and INC ST rp+,r1 2
DEC, Register => SRAM ST -rp,r1 2
Register => SRAM, displaced STD ry+k63,r1 2
Register => Port OUT p1,r1 1
Register => Stack PUSH r1 2
8 Bit, +1 INC r1 Z N V 1
8 Bit ADD r1,r2 Z C N V H 1
Add
8 Bit + Carry ADC r1,r2 Z C N V H 1
16 Bit, constant ADIW rd,k63 Z C N V S 2
8 Bit, -1 DEC r1 Z N V 1
8 Bit SUB r1,r2 Z C N V H 1
8 Bit, constant SUBI rh,c255 Z C N V H 1
Subtract
8 Bit - Carry SBC r1,r2 Z C N V H 1
8 Bit - Carry, constant SBCI rh,c255 Z C N V H 1
16 Bit SBIW rd,k63 Z C N V S 2
logic, left LSL r1 Z C N V 1
logic, right LSR r1 Z C N V 1
Rotate, left over Carry ROL r1 Z C N V 1
Shift
Rotate, right over Carry ROR r1 Z C N V 1
Arithmetic, right ASR r1 Z C N V 1
Nibble exchange SWAP r1 1
And AND r1,r2 Z N V 1
And, constant ANDI rh,c255 Z N V 1
Or OR r1,r2 Z N V 1
Binary Or, constant ORI rh,c255 Z N V 1
Exclusive-Or EOR r1,r2 Z N V 1
Ones-complement COM r1 Z C N V 1
Twos-complement NEG r1 Z C N V H 1
Avr-Asm-Tutorial 42 http://www.avr-asm-tutorial.net
Function Subfunction Command Flags Clk
Register, set SBR rh,c255 Z N V 1
Register, clear CBR rh,255 Z N V 1
Register, copy to T-Flag BST r1,b7 T 1
Bits
change
Register, copy from T-Flag BLD r1,b7 1
Port, set SBI pl,b7 2
Port, clear CBI pl,b7 2
Zero-Flag SEZ Z 1
Carry Flag SEC C 1
Negative Flag SEN N 1
Twos complement carry Flag SEV V 1
Statusbit
set
Half carry Flag SEH H 1
Signed Flag SES S 1
Transfer Flag SET T 1
Interrupt Enable Flag SEI I 1
Zero-Flag CLZ Z 1
Carry Flag CLC C 1
Negative Flag CLN N 1
Twos complement carry Flag CLV V 1
Statusbit
clear
Half carry Flag CLH H 1
Signed Flag CLS S 1
Transfer Flag CLT T 1
Interrupt Enable Flag CLI I 1
Register, Register CP r1,r2 Z C N V H 1
Register, Register + Carry CPC r1,r2 Z C N V H 1
Compare
Register, constant CPI rh,c255 Z C N V H 1
[ Pobierz całość w formacie PDF ]