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 ASSEMBLER: dziwne działanie - bardzo proszę o pomoc

kris_jr 26 Sty 2011 12:57 1944 4
REKLAMA
  • #1 9059039
    kris_jr
    Poziom 10  
    Witam,
    bardzo Was proszę drodzy koledzy o pomoc w ustaleniu przyczyny dziwnego działania programu na procesorze ATmega, bo już zaczynam dostawać białej gorączki od tego. Bardzo mi zależy na szybkim ukończeniu projektu, a tu co chwilę jakieś problemy i zmarnowane dni na szukanie przyczyn niepowodzeń.

    Problem polega na tym iż procesor co jakiś czas wykonuje instrukcje w sposób w jaki teoretycznie nie powinien. Nie mogąc zlokalizować wyraźnego błędu w programie zacząłem go stopniowo upraszczać, aż w końcu tak mocno go okroiłem, że już wszystko wydaje się jasne i oczywiste, a teoretycznie procesor nie powinien zrobić nic nieprzewidzianego, ale to nie rozwiązało problemu.
    W załączniku w formie obrazka (żeby było łatwiej się rozeznać- kolorki) przedstawiam już tą najprostszą formę programu, który w tej wersji ma w zasadzie przetestować przerwania od trzech przycisków. Przerwanie od nich jest na INT2 (zboczem opadającym) a rozróżnienie na porcie C (PC4=0 i PC5=1 => przycisk 1, PC4=1 i PC5=0 => przycisk2, PC4=1 i PC5=1 => przycisk3). W zależności od tego który został wciśnięty to na wyświetlaczu wyświetla odpowiedni symbol.
    Działa to nie najgorzej, czasem zdarza się że błędnie rozpozna przycisk (być może nie udało mi się całkowicie wyeliminować drgań styków), ale nie to jest problemem tylko to, że co jakiś czas (co kilkanaście naciśnięć- liczba nie jest stała) udaje się programowi wejść do trybu SPECIAL. Jest to dla mnie bardzo dziwne bo w tak napisanym programie wydaje się, że nie ma w ogóle takiej możliwości.

    Tu wielka prośba do Was. Może ktoś wie o jakiejś właściwości tych procesorów o której nie wiem i na którą to nie zabezpieczyłem się w kodzie, a może coś przeoczyłem. Bo już zaczynam podejrzewać uszkodzenie procesora. Procesor programuje się prawidłowo (nie wyrzuca błędów i program odczytany jest zgodny z tym co było do zaprogramowania). Dodam, że jest to procesor ATmega32 jest on taktowany kwarcem 16MHz, porty są ustawione prawidłowo (choć to nie powinno mieć na to zachowanie wpływu- bardziej na prawidłowe działanie przerwania) w AVR studio jest dobrze zadeklarowany typ procesora. W obrazkach kodu nie pokazałem ustawień portów i trybu SPECIAL, ale to nie ma wpływu na pierwszą część programu.

    Bardzo proszę Was o szybką pomoc w ustaleniu przyczyny bo już zaczynam się załamywać.
    Dziękuję za zainteresowanie i pozdrawiam
    ATmega32 ASSEMBLER: dziwne działanie - bardzo proszę o pomoc
    ATmega32 ASSEMBLER: dziwne działanie - bardzo proszę o pomoc
    ATmega32 ASSEMBLER: dziwne działanie - bardzo proszę o pomoc ATmega32 ASSEMBLER: dziwne działanie - bardzo proszę o pomoc
  • REKLAMA
  • #2 9059078
    LordBlick
    VIP Zasłużony dla elektroda
    A ustawienie stosu to gdzie ? Kodu w obrazkach się nie wstawia, tylko w tagach [code][/code]
    Kod w ogóle to masakra, użyj preprocesora...
    Co to za "delaje" w przerwaniu ?
    Obsługa przycisków przez przerwanie to mi bascomem zalatuje...
  • REKLAMA
  • #3 9059163
    kris_jr
    Poziom 10  
    delayX to procedury opóźniające w przerwaniu akurat ma służyć odczekaniu do wygaśnięcia drgań styków przycisku.

    Według sugestii zamieszczam program bez definicji rejestrów i trybu SPECIAL, żeby nie zaciemniać, a to akurat nie ma wpływu na działanie.

    .CSEG 				; początek segmentu programu
    
    .ORG 0x00 			; wektor przerwania od resetu
    rjmp Reset
    
    .ORG 0x04 			; wektor przerwania INT1 (powiązany z enkoderami)
    jmp ServiceINT1
    
    .ORG 0x06 			; wektor przerwania INT2 (powiązany zarówno ze sterowaniem kablowym jak i radiowym)
    jmp ServiceINT2
    
    .ORG 0x1A
    jmp ServiceUSART_RxComplete	; wektor przerwania wywołany zakończeniem odbierania danych z USART
    
    Reset:
    
    ldi temp1, high(RAMEND)
    out SPH, temp1
    ldi temp1, low(RAMEND)
    out SPL, temp1
    
    ;jtag: wyłączenie JTAG'a aby uzyskać pełny dostęp do lini portu normalnie zajmowanego przes JTAG
    
    ldi temp1, (1<<JTD)
    out MCUCSR, temp1
    
    ldi temp1, (1<<JTD)
    out MCUCSR, temp1
    
    ldi temp1, (1<<PUD)
    out SFIOR, temp1
    
    ; Ustawienie portów: kierunek - 1 wyjście, 0 wejście, rezystory pull-up - 1 włączony, 0 wyłączony 
    
    ; Port A: AD i LCD
    
    ldi temp1,0b11111100 	; kierunek:   
    out DDRA,temp1 			; AD (PA0, PA1) wejście ; LCD (PA2-PA7) wyjście
    ldi temp1,0b00000000	; stan/pull-up:
    out PORTA,temp1			; wyłączone, stan niski
    						
    ; Port B: SPI/sterowanie silnikami i przekaźnikami, zegar PS2, przerwanie 2
    
    ldi temp1,0b11111010	; kierunek:
    out DDRB,temp1 			; wejście KBD_C (PB0), INT2 (PB2) ; wyjście REL2, REL1, S2/1_P/L (PB1,PB3 i PB4-7)
    ldi temp1,0b00000101	; stan/pull-up:
    out PORTB,temp1 		; pull-up na KBD_C i na INT2, stan niski na REL2/1 oraz na S2/1_P/L
    
    ; Port C: JTAG/ wejścia przycisków itp.
    
    ldi temp1,0b00000000	; kierunek:
    out DDRC,temp1 			; wejście ON-R, P1/2-R, VT*, P1/2, KTN1/2 (PC0-7)
    ldi temp1,0b00001000	; stan/pull-up:
    out PORTC,temp1 		; pull-up na VT* (reszta może być ale nie musi)
    
    ; Port D: przerwania 0/1, czujniki, PWM, we/wy danych PS2/buzer
    
    ldi temp1,0b10110010	; kierunek:	
    out DDRD,temp1 			; wejście KBD_D (PD0), INT0/1 (PD2/3), USRC (PD6); wyjście TXD (PD1), USTR2/1 (PD4/5), PWM (PD7)
    ldi temp1,0b00001101	; stan/pull-up:
    out PORTD,temp1 		; pull-up na KBD_D i INT1/2, bez podciągania USRC ; stani niski na pozostałych
    
    ; USTAWIENIE PRZERWAŃ 
    
    ldi temp1, 0x0E	; INT1 wyzwalane zboczem wznoszącym (enkoder), INT0 wyzwalane zboczem opadającym (kontaktron), bez sleep
    out MCUCR, temp1	; [SE SM2 SM1 SM0 ISC11 ISC10 ISC01 ISC00]
    ; w MCUCSR na razie nic bo ISC2 jest wyzerowane = wyzwalanie zboczem opadającym
    ; MCUCSR	; [JTD ISC2 – JTRF WDRF BORF EXTRF PORF]
    ldi temp1, (1<<INT1)|(1<<INT2)	; aktywne przerwanie od enk i przycisków, wektory przerwań od adresu 0x00
    out GICR, temp1	; [INT1 INT0 INT2 – – – IVSEL IVCE]
    ; kasujemy też wszystkie flagi
    out GIFR, temp1	; [INTF1 INTF0 INTF2 – – – – –]
    sei		; aktywowanie przerwań globalnie
    ;==========================================================================================================================
    
    START:
    nop
    mov state_1, state
    nop
    cpi state_1, 0x13
    brne nttp
    call LCDprawo
    nop
    nttp:
    cpi state_1, 0x16
    brne nttl 
    call LCDlewo
    nop
    nttl:
    cpi state_1, 0x17
    brne ntto 
    call LCDonoff
    nop
    ntto:
    cpi state_1, 0x80
    brlo ntts 
    nop
    call SPECIAL
    nop
    ntts:
    nop
    rjmp START
    nop
    ;---------------------------------------------------------------------------
    Clear_LCD:
    ; Display clear: (0x01- wpisanie spacji, powrót kursora do początku)
    ldi lcdout, 0x01
    call comandout
    call delay2
    call delay1
    ret
    ;---------------------------------------------------------------------------
    LCDprawo:
    ; wpisanie
    	ldi lcdout, 0x7E ; ->
    	call dataout
    	clr state
    	clr state_1
    	ret
    LCDlewo:
    ; wpisanie
    	ldi lcdout, 0x7F ; <-
    	call dataout
    	clr state
    	clr state_1
    	ret
    LCDonoff:
    ; wpisanie
    	ldi lcdout, 0x23 ; #
    	call dataout
    	clr state
    	clr state_1
    	ret
    ;---------------------------------------------------------------------------
    ; PODPROCEDURA OBSŁUGI LCD - odpowiada za wysyłanie komend do wyświetlacza
    comandout:
    push temp1
    push temp2
    
    cbi PORTA, 2			; stan niski na RS - wysyłanie komend
     ldi temp1, 0x10
     A1:					;
      dec temp1				; opóźnienie
      cpi temp1, 0x00		;
      brne A1				;
     nop		
    sbi PORTA, 3			; ustawienie E - high
     ldi temp1, 0x10
     A2:
      dec temp1
      cpi temp1, 0x00
      brne A2
     nop
    ldi temp2, 0xF0			;
    and temp2, lcdout		; wpisanie ważniejszego nibla
    sbr temp2, 0x08			; (przy zachowaniu stanów E i RS na porcie)
    out PORTA, temp2		;
     ldi temp1, 0x10
     A3:
      dec temp1
      cpi temp1, 0x00
      brne A3
     nop
    cbi PORTA, 3			; E -low
     ldi temp1, 0x10
     A4:
      dec temp1
      cpi temp1, 0x00
      brne A4
     nop
    sbi PORTA, 3			; E - high
     ldi temp1, 0x10
     A5:
      dec temp1
      cpi temp1, 0x00
      brne A5
     nop
    ldi temp2, 0xF0			;
    swap lcdout				; wpisanie drugiego nibla
    and temp2, lcdout		; 
    sbr temp2, 0x08			; (przy zachowaniu stanów E i RS na porcie)
    out PORTA, temp2		;
     ldi temp1, 0x10
     A6:
      dec temp1				
      cpi temp1, 0x00		
      brne A6				
     nop
    cbi PORTA, 3			; E - low
     ldi temp2, 0x10
     AA1:
      dec temp2
      ldi temp1, 0xFF
      AA2:
       dec temp1
       cpi temp1, 0x00
       brne AA2
      cpi temp2, 0x00
      brne AA1
      nop
    pop temp2
    pop temp1
    ret
    
    ; PODPROCEDURA OBSŁUGI LCD - odpowiada za wysyłanie danych do wyświetlacza
    dataout:
    push temp1
    push temp2
    
    sbi PORTA, 2			; stan wysoki na RS - wysyłanie danych, niski - instrukcje
     ldi temp1, 0x05
     B1:
      dec temp1
      cpi temp1, 0x00
      brne B1
     nop		
    sbi PORTA, 3			; ustawienie E - high
     ldi temp1, 0x05
     B2:
      dec temp1
      cpi temp1, 0x00
      brne B2
     nop
    ldi temp2, 0xF0			; 4 ważniejsze bity z literki A
    and temp2, lcdout
    sbr temp2, 0x0C
    out PORTA, temp2
     ldi temp1, 0x05
     B3:
      dec temp1
      cpi temp1, 0x00
      brne B3
     nop
    cbi PORTA, 3			; E -low
     ldi temp1, 0x05
     B4:
      dec temp1
      cpi temp1, 0x00
      brne B4
     nop
    sbi PORTA, 3			; E - high
     ldi temp1, 0x05
     B5:
      dec temp1
      cpi temp1, 0x00
      brne B5
     nop
    ldi temp2, 0xF0
    swap lcdout
    and temp2, lcdout
    sbr temp2, 0x0C			; 4 pozostałe bity z literki A
    out PORTA, temp2
     ldi temp1, 0x05
     B6:
      dec temp1
      cpi temp1, 0x00
      brne B6
     nop
    cbi PORTA, 3			; E - low
     ldi temp2, 0x10
     BB1:
      dec temp2
      ldi temp1, 0xFF
      BB2:
       dec temp1
       cpi temp1, 0x00
       brne BB2
      cpi temp2, 0x00
      brne BB1
      nop
    pop temp2
    pop temp1
    ret
    
    ; PODPROCEDURY OPÓŹNIAJĄCE:
    delay1:
    push temp1
    nop
    ldi temp1, 0x05
    more:
    dec temp1
    cpi temp1, 0x00
    brne more
    nop
    pop temp1
    ret
    
    delay2:
    push temp1
    push temp2
    nop
    ldi temp2, 0x10
    more1:
    dec temp2
    ldi temp1, 0xFF
    more2:
    dec temp1
    cpi temp1, 0x00
    brne more2
    cpi temp2, 0x00
    brne more1
    nop
    pop temp2
    pop temp1
    ret
    
    delay3:
    push temp1
    push temp2
    nop
    ldi temp2, 0xFF
    more3:
    dec temp2
    ldi temp1, 0xFF
    more4:
    dec temp1
    cpi temp1, 0x00
    brne more4
    cpi temp2, 0x00
    brne more3
    nop
    pop temp2
    pop temp1
    ret
    ;---------------------------------------------------------------------------------------------
    //	PRZERWANIE OD PRZYCISKÓW I RADIA	//
    ServiceINT2:
    
    call delay3
    call delay3
    call delay3
    
    sbic PINB,2			; sprawdzenie czy INT2=0
    reti
    
    in przyciski , PINC
    andi przyciski, 0b00111111		; dwa najwyższe bity są do czego innego więc je kasuje
    //////////////////////////
    //  spr czy -> radio	//
    //////////////////////////
    cpi przyciski, 0x35 			; sprawdzam czy nie strzałka w prawo radiowo
    brne button2_R
    jmp PRAWO
    //////////////////////////
    //  spr czy <- radio	//
    //////////////////////////
    button2_R:
    cpi przyciski, 0x33
    brne button3_R
    jmp LEWO
    //////////////////////////
    //  spr czy ON radio	//
    //////////////////////////
    button3_R:
    cpi przyciski, 0x36
    brne bezradia
    bezradia:
    ori przyciski, 0b00001111	; zamaskowanie jedynkami bitów od radia bo są zmienne!
    	//////////////////////////
    	//  spr czy -> kabel	//
    	//////////////////////////
    	cpi przyciski, 0x2F 			; sprawdzam czy nie strzałka w prawo kablowo
    	brne button2_K
    	jmp PRAWO
    	//////////////////////////
    	//  spr czy <- kabel	//
    	//////////////////////////
    	button2_K:
    	cpi przyciski, 0x1F
    	brne button3_K
    	jmp LEWO
    	//////////////////////////
    	//  spr czy ON kabel	//
    	//////////////////////////
    	button3_K:
    	cpi przyciski, 0x3F
    	brne WRONG
    	jmp ON_OFF_button
    
    ///////////////////////////
    WRONG:
    ldi tempix1, 0b00100000		; czyszczenie flagi przerwania int2
    out GIFR, tempix1			; - to w ramach eliminacji drgań stykow
    clr tempix1					; wyczyszczenie rejestru pomocniczego
    reti
    
    ////////////////////////////////
    //  obsługa strzałki w prawo  //
    ////////////////////////////////
    PRAWO:
     ldi state, 0x13
    ldi tempix1, 0b00100000		; czyszczenie flagi przerwania int2
    out GIFR, tempix1			; - to w ramach eliminacji drgań stykow
    clr tempix1
    reti
    /////////////////////////////////
    //   obsługa strzałki w lewo   //
    /////////////////////////////////
    LEWO:
    ldi state, 0x16		
    ldi tempix1, 0b00100000		; czyszczenie flagi przerwania int2
    out GIFR, tempix1			; - to w ramach eliminacji drgań stykow
    clr tempix1
    reti
    //////////////////////////////
    //   obsługa on/off			//	
    //////////////////////////////	
    ON_OFF_button:
    ldi state, 0x17		
    ldi tempix1, 0b00100000		; czyszczenie flagi przerwania int2
    out GIFR, tempix1			; - to w ramach eliminacji drgań stykow
    clr tempix1
    reti
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    
    SPECIAL:
    
    ;in temp1, GICR				;
    ;andi temp1, 0b11011111		; wyzerowanie/blokada przerwania INT2
    ;out GICR, temp1				;
    
    Password:
    ...
    
  • REKLAMA
  • Pomocny post
    #4 9059738
    JarekC
    Poziom 32  
    Witam,

    Pierwszy błąd, który wychwyciłem to brak zachowania i odtworzenia rejestru stanu procesora SREG we wszystkich obsługach przerwań. Należy również zadbać o zachowanie używanych rejestrów (R0-R31).

    Zobacz ci się stanie np. w takim przypadku:

    
     CPI  R16,10
        ; tutaj przychodi przerwanie które zmienia stan SREG (znaczniki Z,C ...)           
     BRNE xxx
     LDI  R16,10


    Będziesz miał przypadkowe skoki do xxx wcale nie związane z wykonanym porównaniem.

    Pozdrawiam
    JarekC
  • #5 9059994
    kris_jr
    Poziom 10  
    Dziękuję bardzo za pomoc faktycznie kłopot był z rejestrem statusowym. Jarku, jestem Ci bardzo wdzięczny.
    Mam też nauczkę, że trzeba bardzo uważać na takie szczegóły, bo jak się coś przeoczy na początku to potem można się nieźle zaplątać.

    Zamykam temat.
REKLAMA