-         

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

Thema: Interruptbehandlung bei ATMega8

  1. #1
    Erfahrener Benutzer Begeisterter Techniker
    Registriert seit
    06.05.2005
    Ort
    Berlin
    Beiträge
    212

    Interruptbehandlung bei ATMega8

    Anzeige

    Hi,
    ich bau mir gerade einen "Rhythmusrobotter"
    aus dem Rhythmusteil einer alten Elektroorgel
    und 'nem ATMega8 mit 16MHz.
    Dazu brauche ich an den Pins PC0 -PC3 je einen Impuls
    von ca 10- 40mSek. Mit aktivem Warten hab ich's nun schon
    hingekriegt, wuerd's aber lieber mit 'nem Timer Overflow Interrupt
    machen.
    Ich habe nun den Prescaler von Timer 0 auf 1/1024
    bei einer Quarzfrequenz von 16MHz gestellt:

    Code:
    int Timer_Inits(void)
    {
    	//Timer Interrupt=(Quarzfreq 16000000/8Bit-Ueberlauf 256)/ Prescaler 1024= 16mS
    	//letzte 3 Bit von Timer Clock Control: Prescaler = Quarz/1024:
    	TCCR0 = (TCCR0 | (1 << CS00) | (1 << CS02)) & (~(1 << CS01));
    	//Timer Interrupt Mask Register Bit 1 setzen fuer Timer Overflow Interrupt enable:
    	TIMSK |=(1<<TOIE0);
    	return 0;
    }
    Das sollten dann ca. 16mSek für einen Überlauf sein.
    (16M / 256) / 1024.
    Meine Frage ist nun, kommt das hin mit der Initialisierungsroutine?
    Mit der Interruptbehandlung komme ich noch nicht so klar,
    welcher Vektor ist das nun: SIGNAL (SIG_OVERFLOW0) ?
    und wie bekomme ich das in meinen Code rein?
    Wann muß ich die Interrupts global enabeln?
    Code:
    int Bass_Drum(void)
    {
    	PORTC |= (1<<PC1); //PC1=Port fuer Bass Drum
    	//hier muesste dann nach einem Timer 0 Overflow
    	//der Pin PC1 wieder ausgeschaltet werden.
    	return 0;
    }
    Danke schonmal,
    tholan

  2. #2
    Super-Moderator Robotik Visionär Avatar von PicNick
    Registriert seit
    23.11.2004
    Ort
    Wien
    Beiträge
    6.836
    Das schaut recht vernünftig aus.
    Enablen sei() an besten bevor du in die Hauptschleife kommst
    while (ewig)
    {
    }

    SIGNAL (SIG_OVERFLOW0) wird vom Timer angesprungen, die kannst du wie jede andere Funktion hinschreiben, wo du willst.


    EDIT: keep rockin' !
    mfg robert
    Wer glaubt zu wissen, muß wissen, er glaubt.

  3. #3
    Erfahrener Benutzer Robotik Einstein Avatar von SprinterSB
    Registriert seit
    09.06.2005
    Ort
    An der Saar
    Beiträge
    2.801

    Re: Interruptbehandlung bei ATMega8

    Die Initialisierung ist soweit ok. Es ist allerdings u.U. besser, TCCR0 wirklich zu setzen, damit alle Bits den gewünschten Wert haben. Sollte bei dir aber egal sein.
    Code:
    void Timer_Inits(void)
    {
    	//Timer Interrupt=(Quarzfreq 16000000/8Bit-Ueberlauf 256)/ Prescaler 1024= 16mS
    	//letzte 3 Bit von Timer Clock Control: Prescaler = Quarz/1024:
    	TCCR0 = (1 << CS00) | (1 << CS02);
    	//Timer Interrupt Mask Register Bit 1 setzen fuer Timer Overflow Interrupt enable:
    	TIMSK |=(1<<TOIE0);
    }
    Wenn ich's recht sehe, willst du so was wie Timeouts machen: Nen Port an und nach ner bestimmten Zeit wieder aus, wahrscheinlich unterschiedliche Zeiten für die verschiedenen Ports...

    Du könntest dir eine Struktur machen mit Countdown-Werten, die du setzt und die in der ISR bis aus 0 zurückgezählt werden, eine Einheit pro Tick (16ms):

    Code:
    typedef struct
    {
       uint8_t takt;
       uint8_t bass;
       ...
    } countdown_t;
    
    volatile countdown_t countdown;
    
    SIGNAL (SIG_OVERFLOW0)
    {
    	uint8_t i = sizeof (countdown_t);
    	uint8_t * cd = (uint8_t *) &countdown;
    
    	cd += i;
    	
    	do
    	{
    		uint8_t wert = *(--cd);
    		
    		if (wert)
    			*cd = wert-1;
    	} while (--i);
    }
    Dadurch werden in jedem Tick die Elemente von countdown, die nicht 0 sind, um 1 erniedrigt.

    Code:
    int main()
    {
       ioinit();
       Timer_Inits();
       sei();
    
       // Hauptschleife
       while (1)
       {
          if (countdown.takt == 0)
          {
             countdown.takt = 200;
             countdown.bass = 20;
             PORTC |= (1 << 1);
          }      
    
          if (countdown.bass == 0)
          {
             PORTC &= ~(1 << 1);
          }      
       }
    Disclaimer: none. Sue me.

  4. #4
    Erfahrener Benutzer Begeisterter Techniker
    Registriert seit
    06.05.2005
    Ort
    Berlin
    Beiträge
    212
    Hi und danke,
    habe zur Veranschaulichung noch 'ne LED an PD5
    gehängt und folgenden Testcode eingegeben:
    Code:
    #include<avr/io.h>
    #include<avr/signal.h>
    #define LED	PD5 //Port fuer gruene LED
    
    int Timer_Inits(void)
    {
    	//Timer Interrupt=(Quarzfreq 16000000/8Bit Ueberlauf 256)/ Prescaler 1024= 16mS
    	//letzte 3 Bit von Timer Clock Control: Prescaler = Quarz/1024:
    	TCCR0 = (1 << CS00) | (1 << CS02);
    	//Timer Interrupt Mask Register Bit 1 setzen fuer Timer Overflow Interrupt enable:
    	TIMSK |=(1<<TOIE0);
    	return 0;
    }
    
    int Port_Inits(void)
    {
    	DDRD	|=(1<<LED); //Datenrichtungsregister fuer Pin5, PortD auf Ausgang
    	return 0;
    }
    SIGNAL (SIGOVERFLOW0)
    {
    	PORTD |=(1<<LED);
    }
    
    int main(void)
    {
    	Timer_Inits();
    	Port_Inits();
    	sei();
    	for(;;)			//Warten auf Godot...
    	;
    	return 0;
    }
    Da sollte die LED doch angehen?
    Der Compiler gibt keine Warnung,
    aber bei der LED tut sich nix..
    Hab ich noch irgendwas vergessen?

  5. #5
    Erfahrener Benutzer Robotik Einstein Avatar von SprinterSB
    Registriert seit
    09.06.2005
    Ort
    An der Saar
    Beiträge
    2.801
    Der ISR-Name muss genau stimmen, also SIG_OVERFLOW0.
    Disclaimer: none. Sue me.

  6. #6
    Erfahrener Benutzer Begeisterter Techniker
    Registriert seit
    06.05.2005
    Ort
    Berlin
    Beiträge
    212
    Uups...
    irgendwie hatte auf einmal nix mehr geklappt.
    #include<avr/interrupt.h> hatte ich auch vergessen.
    Weiß nur noch nicht, warum der Compiler nicht gemeckert hat,
    aber egal: jetzt pfundst es.
    Nu werd ich mich mal den Sternchen und Brezeln aus Deinem Beispiel
    widmen, da ich noch längere Pausen für die Noten brauche.
    Vielen Dank für den Code.

  7. #7
    Super-Moderator Robotik Visionär Avatar von PicNick
    Registriert seit
    23.11.2004
    Ort
    Wien
    Beiträge
    6.836
    @tholan: sag' nicht "sternchen und Brezeln" wenn der SprinterSb in der Nähe ist.
    Das ist, als wenn du einem Tischtennis Champion sagst, er spiele Ping-Pong.
    mfg robert
    Wer glaubt zu wissen, muß wissen, er glaubt.

  8. #8
    Erfahrener Benutzer Robotik Einstein Avatar von SprinterSB
    Registriert seit
    09.06.2005
    Ort
    An der Saar
    Beiträge
    2.801
    *lach* Jepp, es gibt nix schlimmeres als in Gegenwart eines Badminton-Spielers das Wort "Fedderball" zu sagen.

    Ich sach aber auch immer "Brezel" und "Teppich" und "Schniedel" oder "Schlangilon".
    Disclaimer: none. Sue me.

  9. #9
    Super-Moderator Robotik Visionär Avatar von PicNick
    Registriert seit
    23.11.2004
    Ort
    Wien
    Beiträge
    6.836
    "Schneckennudel" SprinterSB:
    Na, wenn du es so siehst, is ja nix passiert. Ich wollt halt nicht, daß er in Ungnade fällt.
    mfg robert
    Wer glaubt zu wissen, muß wissen, er glaubt.

  10. #10
    Erfahrener Benutzer Robotik Einstein Avatar von SprinterSB
    Registriert seit
    09.06.2005
    Ort
    An der Saar
    Beiträge
    2.801
    Nö, da braucht's schon viel schlimmeres wie Rosinen in den Apfelkuchen oder Sahne auf nen "Cappucino" oder Speck im Salat *ÖRGX*
    Disclaimer: none. Sue me.

Seite 1 von 2 12 LetzteLetzte

Berechtigungen

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