logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

[ATmega32][ASM] 24bit div 24bit dzielenie 24 bit

Walentynka 03 Gru 2010 13:14 1452 4
REKLAMA
  • #1 8820190
    Walentynka
    Poziom 14  
    Korzystam z kodu zawartego na stronie:

    http://avr-asm.tripod.com/div2424.html

    Niestety nie działa on poprawnie i nie potrafię ustalić dlaczego:
    1.Dzielę liczbę 4999401(4C48E9 hex) przez 100(64 hex) powinienem otrzymać 49994(C34A)

    2.Testy na symulatorze AVRStudio potwierdzają poprawne działanie funkcji w odpowiednich rejestrach(R18,R19,R20) po wykonaniu funkcji znajdują się poprawne wyniki.

    3.Jednak po wgraniu na mikro-kontroler nie otrzymuje poprawnych wyników w celach testu podłączyłem pod mikro LCD żeby zobaczyć co fizycznie znajduje się w rejestrach po wykonaniu dzielenia powinno być C3 hex co odpowiada jakiemuś japońskiemu,chińskiemu bądź koreańskiemu znakowi oraz 4A hex odpowiadające literce "J" oraz 0x00 czyli nul. Na wyświetlaczu pojawiają mi się dwa chińskie znaki identyczne !! Sprawdziłem wszystko po kilka razy i nie znalazłem błędu.

    4.Korzystam z płytki uruchomieniowej EVB4.3V4 kod programu z dzieleniem 16 bit działa poprawnie wraz z wyświetlaniem wyniku na LCD także jestem przekonany ze to jest błąd w dzieleniu ale nie mogę ustalić gdzie bo na symulatorze wszystko dobrze działa.


    .INCLUDE "m32def.inc"
    .EQU LCD_RS=0
    .EQU LCD_E=1
    ;--------------------------------------------------------------------------
    .def rem24L =r24 
    .def rem24M =r25 
    .def rem24H =r26 
    .def result24L =r18 
    .def result24M =r19 
    .def result24H =r20 
    
    .def dvd24L =r18 
    .def dvd24M =r19 
    .def dvd24H =r20 
    
    .def dvr24L =r21 
    .def dvr24M =r22 
    .def dvr24H =r23 
    .def rLoopCnt1=r27
    ;-------------------------------------------------------------------------
    .macro mDelay 
    	ldi R22, 10*@0
    opz3:
    	ldi R21, 52
    opz2:
    	ldi R20, 255
    opz1:
    			dec R20		;1 cykl
    			brne opz1	;2 cykle (chyba, ze 'false', to 1 cykl)
    			;191us (764 cykle)
    		nop
    		dec R21			;1 cykl		
    	 	brne opz2		;2 cykle (chyba, ze [patrz wyzej])
    	nop
    	nop
    	nop
    	nop
    	nop
    	nop
    	nop
    	nop
    	nop
    	dec R22
    	brne opz3
    .endmacro
    
    
    .org 0				
    	jmp Reset
    
    
    Reset:
    	ldi R17,high(RAMEND) 				;inicjalizacja wskaznika stosu
    	out SPH,R17
    	ldi R17,low(RAMEND)
    	out SPL,R17
    Wyjscia:
    	ldi R16,0xFF
    	out DDRC, R16
    	out DDRB, R16
    ;-------------------------------------------------------------------------------		
    
    Inicjalizacja: ;/////////////inicjalizacja LCD	
    		mDelay 10			;0x38: 8 bit interface, 5 x 7 font, 2 lines
    	ldi R16,0b00111000
    	rcall LCD_Command
    		mDelay 10
    	ldi R16, 0b00001100		; display on, show cursor, don't blink
    	rcall LCD_Command
    		mDelay 10
    	ldi R16, 0x01			; clear display, cursor home
    	rcall LCD_Command
    		mDelay 10
    	ldi R16, 0b00000110		; auto-increment cursor
    	rcall LCD_Command
    				;////////////koniec inicjalizacji
    
    		rjmp Pentla
    ;-------------------------------------------------------------------------------
    LCD_Command:
    	cbi PortB, LCD_RS
    	out PortC, r16
    	sbi PortB, LCD_E
    	nop
    	nop
    	nop
    	nop
    	cbi PortB, LCD_E
    	ret
    ;---------------------------------------------------------------------------
    
    LCD_Data:
    	sbi PortB, LCD_RS
    	out PortC, r16
    	sbi PortB, LCD_E
    	nop
    	nop
    	nop
    	cbi PortB, LCD_E
    	cbi PortB, LCD_RS
    	ret
    ;----------------------------------------------------------------------------
    div24u: 
    	clr rem24L 							;clear remainder Low byte 
        clr rem24M 							;clear remainder mid byte 
        sub rem24H,rem24H 					;clear remainder High byte and carry 
        ldi rLoopCnt1,25 					;init loop counter 
                               
    d24u_1: 
    	rol dvd24L 							;shift left dividend 
        rol dvd24M 
        rol dvd24H 
        dec rLoopCnt1 						;decrement counter 
        brne d24u_2 						;if done 
        ret 								; return 
                                        
    d24u_2: 
    	rol rem24L 							;shift dividend into remainder 
        rol rem24M 
        rol rem24H 
        sub rem24L,dvr24L 					;remainder = remainder - divisor 
        sbc rem24M,dvr24M 
        sbc rem24H,dvr24H 
    	brcc d24u_3 						;if result negative 
        add rem24L,dvr24L 					; restore remainder 
        adc rem24M,dvr24M 
        adc rem24H,dvr24H 
        clc 								;clear carry to be shifted into result 
        rjmp d24u_1 						;else 
    d24u_3: 
    	sec 								;set carry to be shifted into result 
        rjmp d24u_1                                     
       
       		 ret
    ;------------------------------------------------------------------------------
    Pentla:
    	ldi dvr24l,0x64
    	ldi dvd24l,0xE9
    	ldi dvd24m,0x48
    	ldi dvd24h,0x4C
    
    		rcall div24u
    		mov R16,R18
    		rcall LCD_data
    		mDelay 0.1
    		mov R16,R19
    		rcall LCD_Data
    		mDelay 0.1
    		mov R16,R20
    		rcall LCD_Data
    		mDelay 0.1
    end:
    	nop 
    		rjmp end
    
    


    Zdjęcie tego co wyrzuca LCD

    [ATmega32][ASM] 24bit div 24bit dzielenie 24 bit

    Film z działania z dzieleniem 16bit niestety dokładność pomiaru jest nie wystarczająca i potrzebuje dzielić 24bit

    http://www.youtube.com/watch?v=Yx8RYYQpnK8[/img]
  • REKLAMA
  • Pomocny post
    #2 8821197
    Andrzej__S
    Poziom 28  
    Napisałeś, że jesteś pewien co do wyświetlania na LCD. Proponowałbym mimo wszystko spróbować zamiast mov r16, r18 i mov r16, r19 użyć ldi r16, 0x4A i ldi r16, 0xC3 i zobaczyć co zostanie wyświetlone. Wszystko wskazuje na to, że obliczenia powinny być wykonywane prawidłowo, więc mimo wszystko upewniłbym się co do wyświetlania.
  • REKLAMA
  • #3 8821505
    Walentynka
    Poziom 14  
    Zmodyfikowana część kodu

    	rcall div24u
    		ldi R16,0x4A
    		rcall LCD_data
    		mDelay 0.1
    		ldi R16,0xC3
    		rcall LCD_Data
    		mDelay 0.1
    		ldi R16,0x00
    		rcall LCD_Data
    		mDelay 0.1


    zgodnie z przewidywaniami na wyświetlaczu jest literka "J"(0x4A) oraz jakiś chiński znaczek (0xC3) oraz (0x00) kolejny znaczek.

    [ATmega32][ASM] 24bit div 24bit dzielenie 24 bit
  • REKLAMA
  • Pomocny post
    #4 8821570
    Andrzej__S
    Poziom 28  
    Spróbuj jeszcze przed dzieleniem wyzerować rejestry dvr24M (r22) i dvr24H (r23). O ile r22 jest wcześniej używany i powinien mieć wartość 0, o tyle r23 nigdzie nie inicjujesz, więc będzie mieć wartość przypadkową. W symulatorze będzie OK, bo tam rejestry przyjmują zawsze wartość początkową 0, ale w rzeczywistości w procesorze tak nie jest.
  • #5 8822097
    Walentynka
    Poziom 14  
    Dziękuje bardzo pomogło, wystarczyło wyzerować podane rejestry przed dzieleniem. Dwa dni nad tym siedziałem ;[
REKLAMA