-         
+ Antworten
Ergebnis 1 bis 6 von 6

Thema: Wieder ein LED-Blinker

  1. #1
    Neuer Benutzer
    Registriert seit
    09.12.2004
    Ort
    Bochum
    Alter
    35
    Beiträge
    3

    Wieder ein LED-Blinker

    Hallo !

    Habe mich durch zig andere Varianten von "LED-Blinker-mit-Timer-Interrupts" gelesen und kann den Fehler in meiner nicht entdecken... hat jemand ein Stichwort für mich ?

    Das Problem: Statt dem erwarteten Verhalten (LED für ca. 1 Sek. ein, dann für ca. 1 Sek. aus), blitzt die LED in Abständen von ca. 1 Sek kurz auf. Warum ??

    Code:
    .include "m8def.inc"
    
    .org	0x000	
    	rjmp main
    .org	0x008	
    	rjmp TimerHandler
    
    main:	ldi r16,0xFF ; PortB ist Output
    	out DDRB, r16
    	
    	ldi r16,0b00000100 ; Overflow Interrupt Enable
    	out TIMSK, r16
    	
    	ldi r16,0b00000011 ; Timer div. 1/64
    	out TCCR1B, r16
    	
    	ldi r16,0b00000000
    	out PORTB, r16
    	
    	sei
    	
    loop:	rjmp loop
    
    TimerHandler:	in r16,PORTB;	Aktuellen Zustand von PORTB einlesen
    		sbrc r16,0;                sind die LEDs gerade aus ?Dann Einschalten, sonst...
    		rjmp Ausschalten;	       ausschalten...
    
    		ldi r16,0b00000111
    		out PORTB,r16
    		rjmp Ende
    
    Ausschalten:	ldi r16,0b00000000
    		out PORTB,r16
    
    Ende:		reti


    [/code]

  2. #2
    Gast
    Hallo,
    ich schätze das Problem liegt in der Anweisung
    "in r16, PORTB"
    hier liest du nicht den Ausgangs-Portzustand,
    sondern den Pegel der Pins am Chip.
    Je nachdem, wie die externe Beschaltung mit der LED ist,
    kann der Pegel dort nicht mehr eindeutig 1 oder 0 sein,
    so wie du es ausgegeben hast.
    Wenn z.B eine LED direkt am Port-Pin nach GND angeschlossen ist.
    So leuchtet diese bei PORT=1,
    aber die Spannnung am PIN bricht zusammen,
    und der Pegel ist nur ca. 1-2 je nach LED.
    Wenn man das per IN-Anweisung liest, ist das 0 und nicht 1.
    Versuche mal, den Zustand in einem Register festzuhalten.

    Gruß Jan

  3. #3
    Neuer Benutzer
    Registriert seit
    09.12.2004
    Ort
    Bochum
    Alter
    35
    Beiträge
    3
    Hallo !

    Danke erstmal für die Antwort!

    Hab' deinen Vorschlag entsprechend umgesetzt und das Programm dabei etwas vereinfacht, sieht jetzt so aus:

    Code:
    .include "m8def.inc"
    
    .org	0x000	
    	rjmp main
    .org	0x008
    	rjmp TimerHandler
    
    main:	ldi r16,0xFF ; PortB ist Output
    	out DDRB, r16
    	
    	ldi r16,0b00000011 ; Timer div. 1/64
    	out TCCR1B, r16
    	
    	
    	ldi r16,0b00000100 ; Overflow Interrupt Enable
    	out TIMSK, r16
    	
    	
    	ldi r16,0b00000000	; Alle LEDs aus.
    	out PORTB, r16
    	
    	sei
    	
    loop:	rjmp loop
    
    TimerHandler:	com r16
    		out PORTB,r16
    Ende:		reti
    Interessanterweise zeigt die Schaltung exakt dasselbe Verhalten wie vorher.

    (Habe auch Varianten ausprobiert, bei denen der Zustand in einem anderen Register verwaltet wird, ebenfalls das gleiche Verhalten.)

    An Pin 14 hängt ein 100 Ohm - Widerstand, daran die LED an Masse. Den Pin einfach nur eingeschaltet lassen funktioniert.

    Ich vermute fast, daß schlicht *zwei* Interrupts kurz hintereinander generiert werden, könnte das sein ?

    Grüße!
    Alex

  4. #4
    Neuer Benutzer
    Registriert seit
    09.12.2004
    Ort
    Bochum
    Alter
    35
    Beiträge
    3
    Lösung gefunden !

    Das Problem war schlicht, daß kein Stack initialisiert, jedoch (bei den Interrupts) benutzt wurde.

    Fertiges Programm läuft und sieht so aus:

    Code:
    .include "m8def.inc"
    
    .org	0x000	
    	rjmp main
    	reti
    	reti
    	reti
    	reti
    	reti
    	reti
    	reti
    .org	0x008
    	rjmp TimerHandler
    
    main:	ldi r16, LOW(RAMEND)
    	out SPL, r16
    	ldi r16, HIGH(RAMEND)
    	out SPH, r16
    	
    	ldi r16,0xFF ; PortB ist Output
    	out DDRC, r16
    	
    	ldi r16,0b00000011 ; Timer div. 1/64
    	out TCCR1B, r16
    	
    	
    	ldi r16,0b00000100 ; Overflow Interrupt Enable
    	out TIMSK, r16
    	
    	
    	ldi r16,0b00000000	; Alle LEDs aus.
    	out PORTC, r16
    	
    	sei
    	
    loop:	rjmp loop
    
    TimerHandler:	com r16
    		out PORTC,r16
    Ende:		reti

  5. #5
    JanB
    Gast
    Hi Alex,
    Ich vermute fast, daß schlicht *zwei* Interrupts kurz hintereinander generiert werden, könnte das sein ?
    Ja, könnte sein, zumal ich in deinem Code
    das Setzen des eigentlichen Timerregisters vermisse.

    bei mir sieht das so aus:

    Code:
     Ausschnitt aus einem Programm für ATTiny15L
    
    .DEF mp = R16          
    .DEF timeval = R12
    
    init:    ...
             ldi mp,0-30         ;0- weil der timer vorwärts zählt
             mov timeval,mp      ;timerwert (ca. 25 us)
             ldi mp,1            ;timer0 Vorteiler auf 1
             out tccr0,mp        ;timer0 control
             ldi mp,2            ;timer0 int enable
             out timsk,mp        ;timer int mask   
             out tcnt0,timeval   ;timer setzen
             ...
    
    ;Timer0 interrupthandler
    Timer0Int: 
            out tcnt0,timeval    ;timer wieder setzen
            ...
            reti


    Das timerregister tcnt0 zählt vorwärts (!) bis zum Überlauf,
    der dann den Interrupt auslöst.
    In der Interruptroutine muss dann sofort das Timerregister
    wieder besetzt werden, damit das Timing stimmt.
    Aber eigentlich müsste es bei dir auch funktionieren,
    da müsste das Timeregister eben einmal "ganz rum" zählen.
    Deshalb hab ich das bisher nicht erwähnt.

    Aber probier halt mal...

    Gruß Jan

  6. #6
    JanB
    Gast
    Ahh. ich sehe gerade, du hast es schon gelöst.
    Da haben wir uns "überschnitten"

    Also dann Viel Spaß noch....

    Jan

+ Antworten

Berechtigungen

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