-
        

Seite 1 von 2 12 LetzteLetzte
Ergebnis 1 bis 10 von 19

Thema: Timer (mit externem Quarz)

  1. #1
    Neuer Benutzer Öfters hier
    Registriert seit
    17.06.2007
    Beiträge
    20

    Timer (mit externem Quarz)

    Anzeige

    Hallo zusammen, ich habe folgendes Problem:

    Ich möchte mit dem Timer0 eine Sieben-Segment-Anzeige zum blinken bringen. Das Problem: Es funktioniert nicht .
    Hier erstmal mein Code:

    Code:
    #include <avr/io.h>
    #include <inttypes.h>
    #include <avr/interrupt.h>
    #include <../../avr/include/util/delay.h>
    
    // gobale Variablen
    uint8_t summerOn = 0;
    uint8_t timeRunning = 0;
    
    uint8_t counter = 0;
    uint8_t _NUM_ARRAY[10] = {(1<<PD1) | (1<<PD1) | (1<<PD2) | (1<<PD3) | (1<<PD4) | (1<<PD5) | (1<<PD7), 
    						   (1<<PD2) | (1<<PD5),
    						   (1<<PD0) | (1<<PD2) | (1<<PD3) | (1<<PD4) | (1<<PD7),
    						   (1<<PD0) | (1<<PD2) | (1<<PD3) | (1<<PD5) | (1<<PD7),
    						   (1<<PD0) | (1<<PD1) | (1<<PD2) | (1<<PD5),
    						   (1<<PD0) | (1<<PD1) | (1<<PD3) | (1<<PD5) | (1<<PD7),
    						   (1<<PD0) | (1<<PD1) | (1<<PD3) | (1<<PD4) | (1<<PD5) | (1<<PD7),
    						   (1<<PD2) | (1<<PD5) | (1<<PD7),
    						   (1<<PD0) | (1<<PD1) | (1<<PD2) | (1<<PD3) | (1<<PD4) | (1<<PD5) | (1<<PD7),
    						   (1<<PD0) | (1<<PD1) | (1<<PD2) | (1<<PD3) | (1<<PD5) | (1<<PD7)};
    
    uint8_t _NUM_A_ALL_ON = (1<<PD0) | (1<<PD1) | (1<<PD2) | (1<<PD3) | (1<<PD4) | (1<<PD5) | (1<<PD6) | (1<<PD7);
    uint8_t _NUM_A_ALL_OFF = ~((1<<PD0) | (1<<PD1) | (1<<PD2) | (1<<PD3) | (1<<PD4) | (1<<PD5) | (1<<PD6) | (1<<PD7));
    	
    
    void checkSummer();
    void drawDisplay();
    
    
    inline uint8_t debounce(volatile uint8_t *port, uint8_t pin)
    {
        if ( ! (*port & (1 << pin)) )
        {
            // Pin wurde auf Masse gezogen, 100ms warten   
            _delay_ms(50);  // max. 262.1 ms / F_CPU in MHz
            //_delay_ms(50); 
            if ( *port & (1 << pin) )
            {
                // Anwender Zeit zum Loslassen des Tasters geben 
                //_delay_ms(50);
                //_delay_ms(50); 
                return 1;
            }
        }
        return 0;
    }
    
    
    
    void checkSummer()
    {
    	/*if (summerOn == 1)
    	{
    		PORTB |= (1<<PB1);
    		PORTB ^= (1<<PB1);
    		_delay_ms(500);
    	}*/
    }
    
    void drawDisplay()
    {
    		//if (timeRunning == 0)
    		//{
    //			PORTD = _NUM_A_ALL_OFF;
    			//_delay_ms(500);
    			//PORTD = _NUM_ARRAY[counter];
    		//}
    }
    
    //SIGNAL(SIG_OVERFLOW1)
    ISR(TIMER0_OVF_vect)
    {
    	//PORTD = _NUM_A_ALL_OFF;
    	//_delay_ms(500);
    	PORTD = _NUM_ARRAY[counter];
        PORTB |= (1<<PB1);
    }
    
    int main(void)
    {
    	// Ausgänge definieren
    	DDRD = 0xff; 		//Ziffern-Anzeige
    	DDRB |= (1<<PB1); 	// Summer
    	
    	// Eingänge definieren
    	DDRB |= (1<<PB0);
    
    	
    	// Display überprüfen
    	PORTD = _NUM_A_ALL_ON; 
    //	_delay_ms(1000);
    //	PORTD = _NUM_A_ALL_OFF; 
    	
    	//Timer aktivieren
    	TCCR0 = (1<<CS01)|(1<<CS00);
    	TCNT0 = 0; 
    	TIMSK | (1<<TOIE0);
    	sei();
    	counter = 6;
    	
    	while(1)
    	{
    		
    		if (debounce(&PINB, PB0))
    		{
    			counter += 1;
    			if (counter > 9)
    				counter = 0;
    				
    			if (counter == 9)
    				summerOn = 1;
    		}
    		
    		checkSummer();
    		drawDisplay();
    	}
    	
    	return 0;
    }
    Sorry für die vielen auskommentierten Textzeilen aber ich habe halt etwas rumprobiert um das Ding zum laufen zu bringen. Ich möchte es nun einfach erstmal schaffen, dass das Programm in die ISR-Routine springt und dort den Summer zum ertönen bringt. Sieht jemand hier irgendeinen Fehler?

    Ich verwende übrigens einen externen 4 Mhz Quarz.

    Mfg,
    Rahvin

  2. #2
    Benutzer Stammmitglied
    Registriert seit
    03.11.2004
    Ort
    Süderlügum
    Alter
    36
    Beiträge
    86

    Re: Timer (mit externem Quarz)

    Zitat Zitat von Rahvin
    TIMSK | (1<<TOIE0);
    Fehlt da nicht ein = ?

    Bin mir auch nicht ganz sicher ob

    Zitat Zitat von Rahvin
    PORTB |= (1<<PB1);
    PORTB ^= (1<<PB1);
    so direkt eine gute Idee ist, denn da wird ja angeschaltet und praktisch verzögerungsfrei wieder aus. Ich denke es wird wohl eher ein Geräusch geben wenn Du zwischen den beiden Befehlen zeitmässig etwas "Luft" (für die Lautsprechermembran zum Schwingen) lässt.

  3. #3
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    29.05.2005
    Ort
    Rott am Inn
    Alter
    29
    Beiträge
    373
    Hi,
    also einen Eingang definiert man wenn dann so:
    // Eingänge definieren
    DDRB &=~ (1<<PB0); und nicht so DDRB |= (1<<PB0);
    dann noch die zwei Fehler die der Vorgänger schon erwähnt hat.
    Dann noch mal probieren und wenns nicht klappt noch mal fragen und wenn möglich ein bisschen die Anzahl der Leichtsinnsfehler reduzieren.
    mfg franz

  4. #4
    Neuer Benutzer Öfters hier
    Registriert seit
    17.06.2007
    Beiträge
    20

    Re: Timer (mit externem Quarz)

    Zitat Zitat von Steinigtmich
    Zitat Zitat von Rahvin
    TIMSK | (1<<TOIE0);
    Fehlt da nicht ein = ?
    Stimmt... aber auch mit = geht es nicht.

    Zitat Zitat von Steinigtmich
    Zitat Zitat von Rahvin
    PORTB |= (1<<PB1);
    PORTB ^= (1<<PB1);
    Auch da hast du Recht aber die Funktion ist ja auch auskommentiert .


    Zitat Zitat von franzl
    Hi,
    also einen Eingang definiert man wenn dann so:
    // Eingänge definieren
    DDRB &=~ (1<<PB0); und nicht so DDRB |= (1<<PB0);
    Du hast Recht, das ist mir auch schon aufgefallen, das Problem ist, wenn ich den Eingang so definiere: DDRB &=~ (1<<PB0) dann gehts nicht
    So allerdings funktionierts: DDRB |= (1<<PB0).

    Der Taster an PB0 funktioniert (auch wenn der Eingang scheinbar 'falsch' definiert ist). Wenn er gedrückt wird, dann wird ein counter hochgezählt und die Zahl auf der 7-Segment-Anzeige angezeigt. Diese soll dabei jetzt noch blinken und das funktioniert leider nicht .

    Hier jetzt nochmal der ursprüngliche Code:
    Code:
    #include <avr/io.h>
    #include <inttypes.h>
    #include <avr/interrupt.h>
    #include <../../avr/include/util/delay.h>
    
    // gobale Variablen
    uint8_t summerOn = 0;
    uint8_t timeRunning = 0;
    
    uint8_t counter = 0;
    uint8_t _NUM_ARRAY[10] = {(1<<PD1) | (1<<PD1) | (1<<PD2) | (1<<PD3) | (1<<PD4) | (1<<PD5) | (1<<PD7), 
    						   (1<<PD2) | (1<<PD5),
    						   (1<<PD0) | (1<<PD2) | (1<<PD3) | (1<<PD4) | (1<<PD7),
    						   (1<<PD0) | (1<<PD2) | (1<<PD3) | (1<<PD5) | (1<<PD7),
    						   (1<<PD0) | (1<<PD1) | (1<<PD2) | (1<<PD5),
    						   (1<<PD0) | (1<<PD1) | (1<<PD3) | (1<<PD5) | (1<<PD7),
    						   (1<<PD0) | (1<<PD1) | (1<<PD3) | (1<<PD4) | (1<<PD5) | (1<<PD7),
    						   (1<<PD2) | (1<<PD5) | (1<<PD7),
    						   (1<<PD0) | (1<<PD1) | (1<<PD2) | (1<<PD3) | (1<<PD4) | (1<<PD5) | (1<<PD7),
    						   (1<<PD0) | (1<<PD1) | (1<<PD2) | (1<<PD3) | (1<<PD5) | (1<<PD7)};
    
    uint8_t _NUM_A_ALL_ON = (1<<PD0) | (1<<PD1) | (1<<PD2) | (1<<PD3) | (1<<PD4) | (1<<PD5) | (1<<PD6) | (1<<PD7);
    uint8_t _NUM_A_ALL_OFF = ~((1<<PD0) | (1<<PD1) | (1<<PD2) | (1<<PD3) | (1<<PD4) | (1<<PD5) | (1<<PD6) | (1<<PD7));
    	
    
    void checkSummer();
    void drawDisplay();
    
    inline uint8_t debounce(volatile uint8_t *port, uint8_t pin)
    {
        if ( ! (*port & (1 << pin)) )
        {
            // Pin wurde auf Masse gezogen, 100ms warten   
            _delay_ms(50);  // max. 262.1 ms / F_CPU in MHz
            //_delay_ms(50); 
            if ( *port & (1 << pin) )
            {
                // Anwender Zeit zum Loslassen des Tasters geben 
                //_delay_ms(50);
                //_delay_ms(50); 
                return 1;
            }
        }
        return 0;
    }
    
    
    void checkSummer()
    {
    	if (summerOn == 1)
    	{
    		PORTB ^= (1<<PB1);
    		_delay_ms(500);
    	}
    }
    
    void drawDisplay()
    {
    	PORTD = _NUM_ARRAY[counter];
    }
    
    //SIGNAL(SIG_OVERFLOW1)
    ISR(TIMER0_OVF_vect)
    {
    	//PORTD = _NUM_A_ALL_OFF;
    	//_delay_ms(500);
    	//PORTD = _NUM_ARRAY[counter];
        PORTB |= (1<<PB1);
    }
    
    int main(void)
    {
    	// Ausgänge definieren
    	DDRD = 0xff; 		//Ziffern-Anzeige
    	DDRB |= (1<<PB1); 	// Summer
    	
    	// Eingänge definieren
    	DDRB |= (1<<PB0);
    	//DDRB &= ~(1<<DDB0);
    	
    	// Display überprüfen
    	PORTD = _NUM_A_ALL_ON; 
    	_delay_ms(1000);
    	PORTD = _NUM_A_ALL_OFF; 
    	
    	//Timer aktivieren
    	TCCR0 = (1<<CS01)|(1<<CS00);
    	TCNT0 = 0; 
    	TIMSK |= (1<<TOIE0);
    	sei();
    	counter = 0;
    	
    	while(1)
    	{
    		
    		if (debounce(&PINB, PB0))
    		{
    			counter += 1;
    			if (counter > 9)
    				counter = 0;
    				
    			if (counter == 9)
    				summerOn = 1;
    		}
    		
    		checkSummer();
    		drawDisplay();
    	}
    	
    	return 0;
    }
    Dieser Code funktioniert, solange ich das sei(); auskommentiert habe. Also der Taster funktioniert, der Counter wird erhöht und das Display zeigt die entsprechende Zahl an. Ist der Counter == 9, so fängt der Summer an zu piepen.

    Ist das sei(); einkommentiert, so sind alle LEDs im Display an, der Schalter reagiert nicht und die ISR-Routine wird nicht ausgeführt, denn sonst würde es ja piepen.

    Ich habs mittlerweile auch mit Timer1 ausprobiert aber das klappt auch nicht . Hat irgendjemand noch ne Idee?... oder vielleicht eine Erklärung dafür, dass der Taster nur dann funktioniert, wenn ich den Port als Ausgang anstatt Eingang definiere ?

  5. #5
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    08.05.2005
    Ort
    Issum
    Alter
    45
    Beiträge
    2.236
    Hat irgendjemand noch ne Idee?... oder vielleicht eine Erklärung dafür, dass der Taster nur dann funktioniert, wenn ich den Port als Ausgang anstatt Eingang definiere ?
    Ja, ich hab eine Idee, wie ist denn Dein Taster beschaltet ?
    Schaltest Du gegen VCC oder GND, hast Du einen externen Pullup oder Pulldown dran?

    Und vor allem, Du räumst Dein Programm was auf, das ist eine Zumutung sowas zu posten, wo hast Du Dir das alles zusammenkopiert?

    Wenn das jemand sieht, hat er wieder einen Grund sich über C lustig zu machen...

    Fang mal klein an, lass mal eine LED in einem Timerinterrupt toggeln, sonst nichts.

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

  6. #6
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    29.05.2005
    Ort
    Rott am Inn
    Alter
    29
    Beiträge
    373
    Hi,
    Ja das mit dem Taster könnt daran liegen dass du den internen Pull-up aktivieren musst. Und beim Programm muss ich Sebastian recht geben du kannst nicht gleich mit einem riesen Programm beginnen, wenn du die Grundlagen nicht beherscht. Und wer sich über C lustig macht hat meiner Meinung nach noch nie damit Programmiert sonst wüsst er das C wunderbar ist.
    mfg franz

  7. #7
    Neuer Benutzer Öfters hier
    Registriert seit
    17.06.2007
    Beiträge
    20
    Also erstmal sorry für den Quellcode, ich werde später nochmal eine aufgeräumte Version posten .
    Zusammenkopiert ist da allerdings nur die Funktion für die Entprellung des Tasters, der Rest stammt von mir. Ich hab zudem ja klein angefangen und es hat alles funktioniert bis auf die ISR und die initialisierung des Timers. Ich werde wohl aber den Taster erstmal rausschmeissen und wirklich nur versuchen die LED per Timer zum blinken zu bringen .

    Der Taster ist übrigens gegen VCC geschaltet und es ist kein externer Pullup oder Pulldown-Widerstand dran. Muss ich den Taster gegen GND schalten? Den interner Pull-up hatte ich bei den ersten Versuchen aktiviert (ist nicht mehr im Quellcode), hat aber auch nicht funktioniert.

  8. #8
    Neuer Benutzer Öfters hier
    Registriert seit
    17.06.2007
    Beiträge
    20
    Ups, eine Frage hab ich mir wohl gerade selbst beantwortet, ich muss den Taster gegen GND schalten .
    Ich werde das heute Abend sofort mal ändern .

  9. #9
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    29.05.2005
    Ort
    Rott am Inn
    Alter
    29
    Beiträge
    373
    Hallo,
    ja wie du schon selber gemerkt hast musst du den Taster gegen GND schalten und dann eben den internen Pull-up aktivieren.
    mfg franz

  10. #10
    Neuer Benutzer Öfters hier
    Registriert seit
    17.06.2007
    Beiträge
    20
    So, ich hab den Taster jetzt mal gegen Ground geschaltet und das funktioniert einwandfrei. Was allerdings immer noch nicht funktioniert, dass ist der Timer . Ich hab den Code mal auf ein minimum reduziert:

    Code:
    #include <avr/io.h>
    #include <avr/interrupt.h>
    
    
    ISR(TIMER1_OVF_vect)
    {
        PORTB |= (1<<PB1);
    }
    
    int main(void)
    {
    	// Ausgänge definieren
    	DDRB |= (1<<PB1); 	// Summer
    	
    	//Timer aktivieren
    	TCCR1A = 0;
    	TCCR1B |= (1<<CS10);
    	TIMSK = (1<<TOIE1);
    	sei();
    	
    	while(1)
    	{
    		
    	}
    	
    	return 0;
    }
    Es soll einfach der Summer an Port PB1 aktiviert werden, wenn die ISR-Routine aufgerufen wird aber das scheint nicht zu passieren . Wenn ich den Summer im Hauptprogramm 'manuell' aufrufe, dann summt er...

    Weiß jemand, was ich falsch mache...

Seite 1 von 2 12 LetzteLetzte

Berechtigungen

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