ATMega8 + asembler

May 06, 2004 11 Replies

Witam Mam takie pytanko: w jaki sposob najprosciej i najszybciej w asemblerze zamienic liczbe 16bitowa na liczbe dziesietna? Mam wynik z przetwornika (2*8bitow) i chcialbym wyrzucic na wyswietlacz liczbe odpowiadajaca tej wartosci binarnej. Dzieki za pomoc Krzysiek


Tutaj masz algorytm konwersji bin->spakowane bcd.

formatting link
wypakowaæ ka¿d± cyfrê, dodac kod ascii zera i wyrzuciæ na wy¶wietlacz.

oczywi¶cie je¶li mówimy o wy¶wietlaczu lcd.

Tak chodzi mi o wyswietlacz LCD

zaczalem robic wedlug tego pdfa :

.def tmp=r19 .def L1=r13 .def L2=r14 .def L3=r15 .def DanaLSB=r16 ;mlodszy bajt liczby ktora chce zamienic .def DanaMSB=r17 ;starszy bajt tej liczby .def count=r18

ldi count,0x10 clr r13 clr r14 clr r15

lop: LsL DanaLSB RoL DanaMSB RoL L1 RoL L2 RoL L3 dec count breq end

ale doszedlem dotad i nie za bardzo wiem co dalej.. gdybys mogl podpowiedziec bylbym wdzieczny

DZieki za pomoc Krzysiek

Nie wiem skad to mam ale moze pomoze ;-) Nie sprawdzalem czy dziala ale pewnie tak.

;-----------------------------------------------------------------------------; ; Universal decimal string conversion (8/16 bit unsigned) ; ; Register Variables: ; Call: var1:0 = 16 bit value to be converted ; len = String length ; tmp1:0 = <Don't care> (high register must be assigned) ; tmp2 = <Don't care>

; ; Result: var1:0 = <Unknown>

; len = <Not changed>

; tmp1:0 = <Unknown>

; tmp2 = 0 ; ; Size: 30 words ; Clock: depends on output routine ; Stack: 10 bytes max (+output routine) ; ; Examples: var1 len output ; 100 0 "100" ; 1234 0 "1234" ; 0 7 " 0" ; 100 5 " 100" ; 100 2 "100"

mk_decu8: clr var1 ;8 bit entry mk_decu16: ;16 bit entry clr tmp2 ;digit counter inc tmp2 ;---- decimal string generating loop clr tmp0 ;var1 /= 10; ldi tmp1,16 ; lsl var0 ; rol var1 ; rol tmp0 ; cpi tmp0,10 ; brcs PC+3 ; subi tmp0,10 ; inc var0 ; dec tmp1 ; brne PC-8 ;/ subi tmp0,-'0' ;Push the remander (a decimal digit) push tmp0 ;/ cp var0,tmp1 ;if(var =! 0) cpc var1,tmp1 ; continue digit loop; brne PC-16 ;/ cp tmp2,len ;Adjust string length (this can be removed for auto-length) brcc PC+5 ; inc tmp2 ; ldi var0,' ' ; push var0 ; rjmp PC-5 ;/ pop var0 ;Put decimal string rcall xmit ;<-- Put a char (var0) to memory, console or any display device dec tmp2 ; brne PC-3 ;/ ret

Pewnego dnia Krzy$ przemówił ludzkim głosem:

No to może zacznę od początku. W nocie masz opisany algorytm konwersji, ale nie musisz go sam implementować. Możesz ściągnąć gotową funkcję ze strony atmela, albo jeśli masz zainstalowane avrstudio to znajdziesz ją w pliku avr204.asm.

Konwersję wywołujesz tak:

ldi fbinL,low(12345) ; 12345 to przykładowa liczba ldi fbinH,high(12345) rcall Bin2BCD16 ; tu wywołujesz konwersję

teraz trzeba rozpakować liczby po konwersji, dodać do każdej kod ascii 0

Najpierw wysyłasz najstarszą cyfrę:

ldi temp,'0' ; add temp,tBCD2 rcall WyslijNaLCD ;

Potem 2 i 3 w kolejności:

mov temp,tBCD1 swap temp ; zamien polowy bajtow andi temp,$0f ; zostaw tylko połówkę subi temp,(-'0') ; dodaj kod ascii 0 rcall WyslijNaLCD mov temp,tBCD1 ; to samo dla młodszej tetrady andi temp,$0f subi temp,(-'0') rcall WyslijNaLCD

Dla cyfry 4 i 5 blok jest identyczny jak dla 2 i 3, musisz tylko zmienić tBCD1 na tBCD0.

Ale jezeli ja mam taka sytuacje ze odbieram z przetwornika wartosc 16bitowa jest ona zapisana jako dodeb1 - (MSB) i dodeb2 - (LSB) to jak mam uzyc tej funkcji?? wpisalem tak:

.include"avr204.asm" ; zalaczylem mu ten plik z tym ze zmienilem w nim .include "8515def.inc" na .include "m8def.inc" .... ldi fbinL,low(dodeb2) ; przy kompilacji wywala mi tu blad: "undefined variable referenced" ldi fbinH,high(dodeb1) ;przy kompilacji wywala mi tu blad: "undefined variable referenced" rcall Bin2BCD16 ;

ldi dana,'0' ; add dana,tBCD2 rcall dana_lcd

mov dana,tBCD1 swap dana ; zamien polowy bajtow andi dana,$0f ; zostaw tylko po³ówkê subi dana,(-'0') ; dodaj kod ascii 0 rcall dana_lcd mov dana,tBCD1 ; to samo dla m³odszej tetrady andi dana,$0f subi dana,(-'0') rcall dana_lcd ;wyslij na lcd

mov dana,tBCD0 swap dana ; zamien polowy bajtow andi dana,$0f ; zostaw tylko po³ówkê subi dana,(-'0') ; dodaj kod ascii 0 rcall dana_lcd mov dana,tBCD0 ; to samo dla m³odszej tetrady andi dana,$0f subi dana,(-'0') rcall dana_lcd ;wyslij na lcd

Co tu jest jeszcze zle?? Dzieki za pomoc Krzysiek

Pewnego dnia Krzy$ przemówił ludzkim głosem:

Ja bym wywalił low i high (bo to jest makro które dzieli liczbę ma młodszy i starszy bajt). A jak masz zadeklarowane dodeb1 i 2 ?

uruchom to w debugerze, wpisz jakieś wartości do dedeb i sprawdź czy działa.

Pewnego dnia Zbych przemówił ludzkim głosem:

i jeszcze jedno, jeśli dodeb to komórki pamięci, to użyj mov zamiast ldi.

Dodeb1 i dodeb2 sa to rejestry zdefiniowane: .def dodeb1=r21 .def dodeb2=r22

Hmm czyli jak to powinno wygladac, bo juz nie mam pomyslow??

Pewnego dnia Krzy$ przemówił ludzkim głosem:

mov fbinL,dodeb2 mov fbinH,dodeb1 rcall Bin2BCD16

Join the Discussion

Have something to add? Share your thoughts — no account required.

Didn't find your answer?

Ask the community — no account required