- 3D-Druck Einstieg und Tipps         
Seite 2 von 3 ErsteErste 123 LetzteLetzte
Ergebnis 11 bis 20 von 22

Thema: Testroutine für Zählerüberlauf

  1. #11
    Benutzer Stammmitglied
    Registriert seit
    31.12.2006
    Beiträge
    61
    Anzeige

    LiFePo4 Akku selber bauen - Video
    Irgendwie finde ich im Datenblatt vom ATMega8 kein Interrupr füt Match on Compare vom Timer0. Sagt jetzt bloß nicht, das Timer0 das nicht unterstützt.

  2. #12
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    08.05.2005
    Ort
    Issum
    Alter
    52
    Beiträge
    2.236
    Sagt jetzt bloß nicht, das Timer0 das nicht unterstützt.
    Tja was soll ich sagen...
    Nimm den Timer 2....

    Gruß Sebastian
    Software is like s e x: its better when its free.
    Linus Torvald

  3. #13
    Benutzer Stammmitglied
    Registriert seit
    31.12.2006
    Beiträge
    61
    Also das mit dem Match on Compare lasse ich erstmal sein. Ich komme nämlich bei einem kleine Programm nicht weiter. Die LED leuchtet nicht.

    Wo ist da der Fehler?
    Code:
    .include "m8def.inc"
     
    .def temp = r16
     
    .org 0x000
    	rjmp main				
    .org 0x009
    	rjmp timer			       
     
    main:                        
     
             ldi temp, LOW(RAMEND)
             out SPL, temp
             ldi temp, HIGH(RAMEND)
             out SPH, temp
    
             sbi DDRD, PD5
     
             sei                   
    
    loop:   
             rjmp loop            
     
    timer:
             sbi PORTD, PD5
             reti
    Ich wette, dass da irgend ein Flag nicht gesetzt wurde.

  4. #14
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    08.05.2005
    Ort
    Issum
    Alter
    52
    Beiträge
    2.236
    .org 0x009
    Schreib besser
    Code:
    .org OVF0addr
    Ist doch besser zu lesen, oder ?
    Ich wette, dass da irgend ein Flag nicht gesetzt wurde.
    Damit hättest Du die Wette gewonnen, schau mal im Dattenblatt nach :
    TCCR0 ->Prescaller
    TIMSK -> Interrupt beim Überlauf freischalten
    eventuell
    TCNT ->um den Timerwert vorzugeben...

    ldi temp, LOW(RAMEND)
    out SPL, temp
    ldi temp, HIGH(RAMEND)
    out SPH, temp
    Mach es andersrum, zuerst High und dann LOW schreiben, es gibt da Registerpaare, wo das nicht egal ist!!


    Gruß Sebastian
    Software is like s e x: its better when its free.
    Linus Torvald

  5. #15
    Benutzer Stammmitglied
    Registriert seit
    31.12.2006
    Beiträge
    61
    Ich wollte mit SBI TCCR0, CS02 ein Bit in den Register setzen, aber der Compiler meldet: "Out of range".
    Mit LDI temp, 0b00000100 und dann OUT TCCR0, temp hat es dann geklappt. Aber jetzt frage ich mich, wie ich einzelne Bits in dem Register manipulieren kann, ohne andere zu beeinflussen?

    Noch was:
    Ne ganz komische Sache. Beim ersten Überlauf wird der Interrupt aktiviert, alles ok. Der TOV0 Flag wird auch (automatisch) zurückgesetzt und die LED geht an. Beim zweiten Überlauf kommt das Programm aber nicht mehr aus der loop-Schleife und der TOV1 Flag wird zwar gesetzt, aber nicht mehr gelöscht. Auch die Befehle ldi temp, (1<<TOV0) und out TIFR, temp haben da nicht gebracht. Woran liegt das?

    Hier der Quellcode:
    Code:
    .include "m8def.inc"
     
    .def temp = r16
     
    .org 0x000
    	rjmp main				; Reset Handler
    
    .org OVF0addr 
    	rjmp timer				; Timer0 Handler			
     
     
    main:                        
     
    	ldi temp, HIGH(RAMEND)
    	out SPH, temp
    	ldi temp, LOW(RAMEND)
    	out SPL, temp
    
    	sbi DDRD, PD5
    	cbi DDRD, PD2
    	
    	ldi temp, 0b00000001
    	out TCCR0, temp	
    
    	ldi temp, 0b00000001
    	out TIMSK, temp
    
    	sei                  
     
    loop:
    	rjmp loop             
     
    timer:
    	sbis PORTD, PD5
    	rjmp setLED
    
    	sbic PORTD, PD5
    	rjmp clrLED
    
    setLED:
    	sbi PORTD, PD5
    
    	ldi temp, (1<<TOV0)
    	out TIFR, temp
    
    	rjmp loop
    
    clrLED:
    	cbi PORTD, PD5
    
    	ldi temp, (1<<TOV0)
    	out TIFR, temp
    
    	rjmp loop

  6. #16
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    30.07.2005
    Beiträge
    569
    Zitat Zitat von cipoint
    Ich wollte mit SBI TCCR0, CS02 ein Bit in den Register setzen, aber der Compiler meldet: "Out of range".
    Wenn du nur das eine Bit ändern möchtest kannst du es auch so versuchen:
    Code:
    in r16, TCCR0
    ori r16, (1<<CS02)
    out TCCR0, r16
    Zitat Zitat von cipoint
    Noch was:
    Ne ganz komische Sache. Beim ersten Überlauf wird der Interrupt aktiviert, alles ok. Der TOV0 Flag wird auch (automatisch) zurückgesetzt und die LED geht an. Beim zweiten Überlauf kommt das Programm aber nicht mehr aus der loop-Schleife und der TOV1 Flag wird zwar gesetzt, aber nicht mehr gelöscht. Auch die Befehle ldi temp, (1<<TOV0) und out TIFR, temp haben da nicht gebracht. Woran liegt das?
    Das liegt dadran, das mein eine ISR (und timer ist eine) nicht mit rjmp #label sondern mit reti verlassen wird.

    Grüße,
    Hanni.
    Grundregeln des Forenpostings:
    1. Nutze niemals die Suchfunktion!
    2. Überprüfe niemals die Topics nach Ähnlichkeiten!
    3. Schreibe alles in hellgelb!

  7. #17
    Benutzer Stammmitglied
    Registriert seit
    31.12.2006
    Beiträge
    61
    Danke, dann schreib' ich das Programm um.

    edit: Habe Schwierigkeiten, das zu realisieren. Bin eben noch sehr unerfahren, was den Stack angeht.
    Also ein Flowchart habe ich schonmal angefertigt. Mit dem Quellcode klappt das alleridngs noch nicht.

    Bild hier  

    Der uC befindet sich zunächst in einer Endlosschleife. Im Interrupthandler vom Timer0 (Label timer) wird dann mit sbic abgefragt, ob die LED an ist. Wenn nicht, springt der uC zum Label LEDon. Dort wird die LED angemacht. Danach kehrt der uC ja aber wieder zurück zum Label timer. Dort steht leider der Befehl sbis, nach welchem der Sprung zu LEDoff steht.

    Wie verhindere ich also, dass der uC nicht nach LEDoff springt, wenn er im selben Durchlauf schon in LEDon war?

    edit²: Habe das jetzt so gelöst.
    Code:
    include "m8def.inc"
     
    .def temp = r16
    .def oldStatus = r17
     
    .org 0x000
    	rjmp main				; Reset Handler
    
    .org OVF0addr 
    	rjmp timer				; Timer0 Handler			
     
     
    main:                        
     
    	ldi temp, HIGH(RAMEND)
    	out SPH, temp
    	ldi temp, LOW(RAMEND)
    	out SPL, temp
    
    	sbi DDRD, PD5
    	cbi DDRD, PD2
    	
    	ldi temp, 0b00000001
    	out TCCR0, temp	
    
    	ldi temp, 0b00000001
    	out TIMSK, temp
    
    	sei          
    	
    	cbi PORTD, PD5
     
    loop:
    	rjmp loop             
     
    timer:
    	sbic PORTD, PD5
    	rjmp LEDoff
    	sbi PORTD, PD5
    	reti
    	
    LEDoff:
    	cbi PORTD, PD5
    	reti
    Ist das programmiertechnisch und stilistisch richtig?

  8. #18
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    30.07.2005
    Beiträge
    569
    Zitat Zitat von cipoint
    Ist das programmiertechnisch und stilistisch richtig?
    Programmiertechnisch schon, über den Stil und die Lesbarkeit kann man sicher streiten.

    Anstatt:
    Code:
       ldi temp, 0b00000001
       out TCCR0, temp   
    
       ldi temp, 0b00000001
       out TIMSK, temp
    würde ich in dem Teil das folgende schreiben:
    Code:
       ldi temp, (1<<CS00)
       out TCCR0, temp   
    
       ldi temp, (1<<TOIE0)
       out TIMSK, temp
    Das ganze ist meiner Ansicht nach vor allem besser lesbar.

    Im übrigen sollte man in Interupt Routinen prinzipiell das Status Register SREG sichern. dieses kann z.B. wie folgt erfolgen:
    Code:
    timer:
       push temp
       in temp, SREG
       push temp
       sbic PORTD, PD5
       rjmp LEDoff
       sbi PORTD, PD5
       rjmp timer_exit
       
    LEDoff:
       cbi PORTD, PD5
    
    timer_exit:
       pop temp
       out SREG, temp
       pop temp
       reti
    Dieses ist insbesondere dann wichtig, wenn in deinem Loop und in der ISR Operationen durchgeführt werden, bei denen Flags im SREG verändert werden können.

    In deinem Programmablaufplan würde ich die Timer Interupt Routine komplett entkoppelt zeichnen. Zum einen, weil der µC nach dem Interupt exakt dort weitermacht, wo er aufgehört hat und zum anderen, weil es später weniger verwirrend wirkt.

    Grüße,
    Hanni
    Grundregeln des Forenpostings:
    1. Nutze niemals die Suchfunktion!
    2. Überprüfe niemals die Topics nach Ähnlichkeiten!
    3. Schreibe alles in hellgelb!

  9. #19
    Benutzer Stammmitglied
    Registriert seit
    31.12.2006
    Beiträge
    61
    Zitat Zitat von Hanni
    Zitat Zitat von cipoint
    Ist das programmiertechnisch und stilistisch richtig?
    Anstatt:
    Code:
       ldi temp, 0b00000001
       out TCCR0, temp   
    
       ldi temp, 0b00000001
       out TIMSK, temp
    würde ich in dem Teil das folgende schreiben:
    Code:
       ldi temp, (1<<CS00)
       out TCCR0, temp   
    
       ldi temp, (1<<TOIE0)
       out TIMSK, temp
    Das ganze ist meiner Ansicht nach vor allem besser lesbar.
    Aber wenn ich CS00, CS01 und CS02 manipulieren will, und zwar getrennt voneinander? Bleibt mir da nur die Möglichkeit, den kompletten Register auszulesen, mit OR oder AND zu bearbeiten und zurückzuschreiben?
    Für I/O Register gibt es ja sbi und sbi. Und für "normale" Register?

  10. #20
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    30.07.2005
    Beiträge
    569
    Zitat Zitat von cipoint
    Aber wenn ich CS00, CS01 und CS02 manipulieren will
    z.B.: ldi temp, (1<<CS00) | (1<<CS01)

    zum setzen von 2 Bits.
    Grundregeln des Forenpostings:
    1. Nutze niemals die Suchfunktion!
    2. Überprüfe niemals die Topics nach Ähnlichkeiten!
    3. Schreibe alles in hellgelb!

Seite 2 von 3 ErsteErste 123 LetzteLetzte

Berechtigungen

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

LiFePO4 Speicher Test