- LiFePO4 Speicher Test         
Ergebnis 1 bis 10 von 19

Thema: Assembler Mega16 Timer Probleme

Hybrid-Darstellung

Vorheriger Beitrag Vorheriger Beitrag   Nächster Beitrag Nächster Beitrag
  1. #1
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    20.09.2008
    Ort
    Linz A
    Beiträge
    126

    Assembler Mega16 Timer Probleme

    Hi,
    ich bin dabei meine defekte Heizungselektronik durch einen Mega16 zu ersetzen.
    Das soll natürlich relativ rasch geschehen, denn die Heizperiode steht vor der Tür bzw. hat schon begonnen ...!

    Beim Tiny13 und Mega8 hatte ich bislang keine Probleme mit den Timern bzw. den Vektor-Sprüngen bei Overflow.
    Den Mega16 verwende ich das erste Mal.
    Ich benötige alle 3 Timer.
    Beim debuggen mit dem AVR Studio staunte ich nicht schlecht, als kein einziger TmrOvf auf die richtige Vektoradresse gesprungen ist.
    Nun habe ich ein Testprogramm zusammen gestellt.
    Bei diesem ist es genauso der Fall!

    Beim Testen dieses Testprogrammes (und in meinem eigentlichen ebenso) mit AVR Studio 4.12 und 4.19 springen die Timer Interrupts auf eine komplett andere Vectoradresse als es sein soll!!!

    Der Tmr0-Ovf-Int springt auf INT2 External Interrupt Request 2,
    der Tmr1-Ovf-Int auf ANA_COMP Analog Comparator und
    der Tmr2-Ovf-Int auf TIMER1 OVF Timer/Counter1 Overflow!

    Wo hab ich bloß meinen Gedanken- und Programmfehler!??
    Kann mir bitte jemand helfen?

    Gruß Heinz

    Code:
    #include "m16def.inc"
    ; Interrupt Vektoren lt. Datenblatt und m16def.inc
    .cseg
    .org    0x000        
        rjmp    INIT    ; POR oder Reset
        reti         ;INT0 External Interrupt Request 0
        reti         ;INT1 External Interrupt Request 1
        reti         ;TIMER2 COMP Timer/Counter2 Compare Match
        rjmp    TMR2OVF    ;TIMER2 OVF Timer/Counter2 Overflow
        reti         ;TIMER1 CAPT Timer/Counter1 Capture Event
        reti         ;TIMER1 COMPA Timer/Counter1 Compare Match A
        reti         ;TIMER1 COMPB Timer/Counter1 Compare Match B
        rjmp    TMR1OVF    ;TIMER1 OVF Timer/Counter1 Overflow
        rjmp    TMR0OVF    ;TIMER0 OVF Timer/Counter0 Overflow
        reti         ;SPI, STC Serial Transfer Complete
        reti         ;USART, RXC USART, Rx Complete
        reti         ;USART, UDRE USART Data Register Empty
        reti         ;USART, TXC USART, Tx Complete
        reti         ;ADC ADC Conversion Complete
        reti         ;EE_RDY EEPROM Ready
        reti         ;ANA_COMP Analog Comparator
        reti         ;TWI Two-wire Serial Interface
        reti         ;INT2 External Interrupt Request 2
        reti         ;TIMER0 COMP Timer/Counter0 Compare Match
        reti         ;SPM_RDY Store Program Memory Ready
    
    INIT:
        cli        ;disable Interrupts 
    
    ; Stack anlegen
        ldi    R16,LOW(RAMEND)
        out    SPL,R16
        ldi    R16,HIGH(RAMEND)
        out    SPH,R16
    
    ; Interrupt enabling
        ldi    R16,69        ;Tmr0+1+2 IntEn
        out    TIMSK,R16
        sei            ;Interrupts freigeben
    
    ;*****************************************************************
    ; Start Timer0
        ldi    R16,250
        out    TCNT0,R16    ;TimerCounter auf 250
        ldi    R16,1        ;no Prescaler
        out    TCCR0,R16    ;StartTimer0
    ; Start Timer1
        ser    R17
        ldi    R16,245
        out    TCNT1H,R17    ;TimerCounter auf 255
        out    TCNT1L,R16    ;TimerCounter auf 245
        ldi    R16,1        ;no Prescaler
        out    TCCR1B,R16    ;StartTimer1
    ; Start Timer2
        ldi    R16,240
        out    TCNT2,R16    ;TimerCounter auf 240
        ldi    R16,1        ;no Prescaler
        out    TCCR2,R16    ;StartTimer2
    
    ; Loop zum Testen der TmrOvf Interrupts
    LOOP:
        nop
        rjmp    loop
    
    ;******************** START INTERRUPTROUTINEN ********************
    TMR0OVF:
        in    R18,SREG
        cli
        out    SREG,R18
        reti
    
    TMR1OVF:
        in    R19,SREG
        cli
        out    SREG,R19
        reti
    
    TMR2OVF:
        in    R20,SREG
        cli
        out    SREG,R20
        reti
    
    ;******************** ENDE INTERRUPTROUTINEN *********************
    .EXIT

  2. #2
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    07.03.2011
    Beiträge
    1.899
    Hallo,

    ich hab zwar mit AVRs nichts zu tun, was mir aber auffällt ist die Verwendung von zwei verschiedenen Befehlen in der Interrupt Tabelle: reti und rjmp. Ich kenne das eigentlich so, daß überall jumps sind, die bei unbenutzten Interrupts auf einen Errorhandler zeigen.

    MfG Klebwax
    Strom fließt auch durch krumme Drähte !

  3. #3
    Erfahrener Benutzer Begeisterter Techniker
    Registriert seit
    21.06.2011
    Ort
    Dresden
    Beiträge
    219
    Hi,
    Solange diese jump-adressen nicht angesprungen werden sollte das "reti" nicht stören, ich kenns allerdings auch so,
    das dort ein jmp 0 oder so steht.
    Würde aber zunächst mal das "sei" nach timer-initialisierung stellen und vor allem im TIFR vorm "sei" alle betroffenen
    Interrupt-Flags löschen.
    mfg
    Achim

  4. #4
    Erfahrener Benutzer Robotik Einstein Avatar von wkrug
    Registriert seit
    17.08.2006
    Ort
    Dietfurt
    Beiträge
    2.214
    Guck noch mal genau ins Datenblatt, da steht nicht RJMP zum anspringen der Interrupts sondern JMP.
    Die Sprungweite vin RJMP reicht bei einem ATMEGA16 nicht mehr aus um den kompletten Adressraum bedienen zu können, deshalb müssen hier die JMP Befehle verwendet werden. - Der Fehler ist mir auch schon passiert.

    Denk auch dran die JTAGEN Fuse zu deaktivieren, sonst gehen ein paar Ports von PORT C nicht richtig.

    SEI löscht übrigens keinen Interrupt, sondern ermöglicht nur dessen Ausführung.
    Die entsprechenden Flags werden durch Aufruf der entsprechenden Interrupt Routine mit dem Befehl RETI, oder durch gezieltes Schreiben auf bestimmte Register Bits gelöscht.

    So etwas wie eine Heizungssteuerung in Assembler zu programmieren halt ich schon für etwas mutig.
    Ich würde da eher ne Hochsprache nehmen wie z.B. "C" oder BASCOM, aber das musst Du selber entscheiden.
    Geändert von wkrug (29.09.2013 um 10:12 Uhr)

  5. #5
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    26.11.2004
    Beiträge
    451
    Ein RJMP geht auch bei den Interrupts, es muss nur ein .org vor jeden Interrupt-Vektor und man muss sich im klaren sein, dass man nicht alles anspringen kann (sagt einem aber idr. der Compiler).
    Ein Vorteil für den RJMP kann aber sein, dass es schneller abgearbeitet werden kann (1 Takt weniger).

    Das .org hätte auch den Vorteil, dass man auch mal einen Vektor vergessen kann, ohne dass das Programm gleich durch dreht und die Vektoren sicher an ihrem Platz stehen.

  6. #6
    Erfahrener Benutzer Robotik Einstein Avatar von wkrug
    Registriert seit
    17.08.2006
    Ort
    Dietfurt
    Beiträge
    2.214
    Ein Vorteil für den RJMP kann aber sein, dass es schneller abgearbeitet werden kann (1 Takt weniger).
    Wie gesagt, ein RJMP reicht aber nicht bis zum Ende des Adressbereiches.
    Wenn man dort dann Interrupt routinen plaziert, können die nicht mehr angesprungen werden - "Out of Range" Fehler.

    Das Problem mit dem RETI in der Vektortabelle hat sich bei mir noch nicht ergeben, da ich immer alle Vektoren mit JMP Befehlen verwende und die nicht gebrauchten einfach mit RETI am angesprungenen Label abschließe.
    Das hat den Vorteil, das ich relativ problemlos diese Interrupt Vektoren aktivieren kann, wenn ich sie dann doch brauche.

  7. #7
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    20.09.2008
    Ort
    Linz A
    Beiträge
    126
    Danke für die vielen und raschen Antworten!
    RJMP und RETI funktionieren in der Vektortabelle bei Tiny13 und Mega8 einwandfrei.
    Arbeitet der Mega16 anders???
    Zudem sollte das Problem mit dem Adressbereich zumindest im obigen Testprogramm kein Problem sein.
    Weiters motzt der Compiler ja nicht, was er bei einem "BRANCH" sehr wohl tut/getan hat (in meinem Heizungsprogramm).


    SEI setze ich deshalb vor dem Starten der Timer, weil ich sie zu unterschiedlichen Zeiten bzw. Bedingungen starte und bei Overflow wieder stoppe.
    Also muss SEI generell vorher gesetzt sein. Macht bei T13 + M8 auch keine Probleme.


    Zitat Zitat von wkrug Beitrag anzeigen
    Denk auch dran die JTAGEN Fuse zu deaktivieren, sonst gehen ein paar Ports von PORT C nicht richtig.
    Was funktioniert da dann nicht richtig?
    Wie muss ich die setzen?
    Ich hab bislang geflissentlich die Finger von Fuses gelassen - außer Takt.


    Zitat Zitat von wkrug Beitrag anzeigen
    So etwas wie eine Heizungssteuerung in Assembler zu programmieren halt ich schon für etwas mutig.
    Ich würde da eher ne Hochsprache nehmen wie z.B. "C" oder BASCOM, aber das musst Du selber entscheiden.
    Ich hab vor ein paar Jahren mit Assembler begonnen und mich damit bisher gut zurecht gefunden. Wenn man vorher einen guten Programmablauf (programflow) ausarbeitet und skizziert, dann geht das Programmieren auch ganz flott von der Hand.


    Zitat Zitat von wkrug Beitrag anzeigen
    Guck noch mal genau ins Datenblatt, da steht nicht RJMP zum anspringen der Interrupts sondern JMP.
    Sollte im Prinzip egal sein welcher Befehl in der Vektortabelle an der Ansprungadresse steht.
    Denn bei einem Interrupt (TOVF) springt AVR gar nicht dort hin!!!!!!!!
    DAS IST MEIN PROBLEM!!

  8. #8
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    08.08.2008
    Ort
    DE
    Beiträge
    523
    Schonmal so versucht?

    Code:
    .org PORTB_INT0_vect        ; Vector adress
        rjmp SW1_ISR
    mfg

  9. #9
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    26.11.2004
    Beiträge
    451
    Zitat Zitat von HeSt Beitrag anzeigen
    Denn bei einem Interrupt (TOVF) springt AVR gar nicht dort hin!!!!!!!!
    DAS IST MEIN PROBLEM!!
    Im unterschied von jmp und Rjmp liegt dein Problem, klar kannst du mit beidem springen, aber ein jmp ist größer (32 Bit befehl) als ein rjmp (16 Bit Befehl). Wenn du jetzt ohne .org rjmps hinter einander hängst, dann verschiebt sich dein ganzer code um zwei byte.

    sprich durch dein rjmp init ist dein darauf folgendes reti an Adresse 0x02h und nicht and 0x04h wo es sein sollte. deswegen .org vorne dran dann passieren solche fehler nicht, oder eben jmp verwenden wenn du mehr als 8k flash hast.

  10. #10
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    07.03.2011
    Beiträge
    1.899
    Zitat Zitat von seite5 Beitrag anzeigen
    Solange diese jump-adressen nicht angesprungen werden sollte das "reti" nicht stören, ich kenns allerdings auch so,
    das dort ein jmp 0 oder so steht.
    Sie wären dann ein Problem, wenn ein jmp mehr Bytes braucht als ein reti. Die Tabelle würde dann nicht mehr passen.

    MfG Klebwax
    Strom fließt auch durch krumme Drähte !

Ähnliche Themen

  1. Verwirrung.....Timer von Mega16 mit Bascom
    Von JensB im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 8
    Letzter Beitrag: 05.06.2008, 11:10
  2. Timer-Programmierung an Mega16
    Von ThomasF im Forum AVR Hardwarethemen
    Antworten: 5
    Letzter Beitrag: 06.10.2005, 17:48
  3. Timer beim Mega16
    Von maw_hn im Forum C - Programmierung (GCC u.a.)
    Antworten: 3
    Letzter Beitrag: 22.08.2005, 10:03
  4. Probleme Mega16 Timer1 Interrupt
    Von skyrider im Forum AVR Hardwarethemen
    Antworten: 0
    Letzter Beitrag: 16.04.2005, 15:49
  5. AT MEGA16 Timer Problem
    Von Markus Krepper im Forum AVR Hardwarethemen
    Antworten: 0
    Letzter Beitrag: 24.10.2004, 22:51

Stichworte

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

fchao-Sinus-Wechselrichter AliExpress