-         

Seite 1 von 3 123 LetzteLetzte
Ergebnis 1 bis 10 von 24

Thema: TWI stört meinen Interrupt zur Frequenzmessung

  1. #1
    Neuer Benutzer Öfters hier
    Registriert seit
    21.10.2006
    Beiträge
    22

    TWI stört meinen Interrupt zur Frequenzmessung

    Anzeige

    Ich messe eine Frequenz, indem ich die Flanke vom INT0 auswerte. Bei der ersten Flanke wird TCNT1 in Start gespeichert und bei der zweiten Flanke wird TCNT1 in Stop gespeichert. In der main-Schleife wird dann über eine Freischaltbedingung die Frequenz in Hz berechnet. Das funktioniert einwandfrei.

    Jetzt wird in der main-Schleife das Ergebnis nach der Berechnung per I2C an das Display geschickt. Währenddessen können ja ruhig weitere Flanken gemessen werden, da der Interrupt0 ja Vorrang hat. Leider stimmt das Ergebnis nicht mehr, sobald die I2C Befehle im Programm sind.

    Wie kann das sein, dass die Zeit falsch gemessen wird, obwohl der Interrupt doch Vorrang hat und ja auch garantiert einmal ohne Unterbrechung abgearbeitet wird?

    Die I2C Bibliotheken basieren auf denen von P.Fleury. Also es wird der Hardware-TWI benutzt. Ich konnte im Code auch nirgendwo einen anderen Interrupt finden. Aber die INT0-Routine sperrt ja sowieso andere Interrupt, während sie aktiv ist?

    Code:
    // Interrupt INT0
    ISR(INT0_vect)
    {
     static unsigned char ErsteFlanke = TRUE;
    
     if( Update )       //Erst erneut Messen, wenn vorher ausgewertet wurde.
      return;
    
     if( ErsteFlanke )
     {
      StartTime0 = TCNT1;    //Zeit der ersten Flanke speichern
      NumberOverflow = 0;
      ErsteFlanke = FALSE;       
      }
      else
      {
       EndTime = TCNT1;    //Zeit der zweiten Flanke speichern
       Update = TRUE;        //Berechnung freigeben
       ErsteFlanke = TRUE;    
      }
    }
    
    int main()
    {
           while (1)
           {
    
    	   if(Update) // Berechnung der Frequenz
      	    {
    	      Drehzahl = (NumberOverflow * 65536) + EndTime - StartTime;
    	      Drehzahl = F_CPU / Drehzahl;
    	      Update0 = FALSE;	
                }
    	
    	     
            // I2C 
        	if (!TWIM_Start (SlaveAddress, TWIM_WRITE))
    	 {
    	   TWIM_Stop ();
    	 }
    	else
    	{
    	   TWIM_Write (display_value);
               TWIM_Stop ();
    	   Delay_ms (1);
    	 }
     
        	if (!TWIM_Start (SlaveAddress, TWIM_READ))
    	 {
    	   TWIM_Stop ();
    	 }
    	else
    	{
    	   Data[0] = TWIM_ReadNack ();
    	   TWIM_Stop ();
    	   Delay_ms (1);
    	}
         }
    }

  2. #2
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    08.05.2005
    Ort
    Issum
    Alter
    45
    Beiträge
    2.236
    Hallo,
    Code:
    Drehzahl = (NumberOverflow * 65536) + EndTime - StartTime;
    Das kann zu Problemen führen, Grund:
    NumberOverflow,Endtime und StartTime können sich während der Berechnung ändern.
    Leg Dir mal 3 lokale Variablen an , schalte kurz mit cli() die Interrupts ab, kopiere NumberOverflow,Endtime und StartTime in die lokale Variablen, gib die Interrupts wieder frei und rechne in Ruhe mit den Kopien weiter.

    Vielleicht hilft das.

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

  3. #3
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    20.05.2006
    Ort
    Lippe
    Alter
    48
    Beiträge
    524
    Hallo,

    wenn du bei 0 U/min Daten über das TWI schickst, wird dann die Drehzahl richtig mit 0 erkannt oder gibt es trotzdem Interrupts? Falls ja, wie sieht die Beschaltung aus, woher kommt das Signal? Wo ich drauf hinaus will ist, dass es sich auch um ein Hardwareproblem handeln kann.
    Der Tipp von Sebastian ist aber in jedem Fall richtig und wichtig.

    Gruß

    Jens

  4. #4
    Neuer Benutzer Öfters hier
    Registriert seit
    21.10.2006
    Beiträge
    22
    Die Berechnung der Frequenz wird ja mit dem Update-Flag freigeschaltet. Es wird also erst wieder ein neuer Wert eingelesen, sobald die vollständige Berechnung bestätigt ist. Tritt ein Interrupt auf, während Update = FALSE ist, wird die Interrupt-Routine nicht ausgeführt, sondern direkt wieder verlassen. Also die Frequenzmessung funktioniert für meine Zwecke zu 100%.

    Sobald ich den TWI-Client abziehe, wird die Frequenz wieder richtig angezeigt. Ich verstehe nicht, wie ein paar Funktionen im pollenden Betrieb meine Interrupt-Routine beeinflussen können. Mit cli() habe ich auch schon versucht das zu verriegeln, aber das hatte keine Wirkung, da die Interrupt-Routine cli() zu Beginn ja selbst auch ausführen.

    Es geht also darum:
    Code:
    while(1)
    {
       if (Update) //Update => Freischaltbedingung für vollständige Messung
        {
          Frequenzberechnung...
          Update = FALSE;  //Neue Messung erlauben
        }
    
       I2C_Sende();
       I2C_Stop();
       I2C_Empfange();
       I2C_Stop();
    }
    Bei jedem Schleifendurchlauf wird also einmal per I2C gesendet. Wenn ich die I2C-Befehle auskommentiere, stimmt die Berechnung natürlich wieder. Ich kann mir überhaupt nicht erklären, warum die Interrupt-Routine vom pollenden I2C gestört werden könnte.

    Die gemessene Frequenz wird von einem Atmega8 generiert.

  5. #5
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    08.05.2005
    Ort
    Issum
    Alter
    45
    Beiträge
    2.236
    Hallo,
    kannst Du mal das ganze Programm posten ?

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

  6. #6
    Neuer Benutzer Öfters hier
    Registriert seit
    21.10.2006
    Beiträge
    22

    Code

    Hier mal als Anhang der Code. Danke schonmal für die Mühe!
    Angehängte Dateien Angehängte Dateien

  7. #7
    Erfahrener Benutzer Robotik Visionär Avatar von Hubert.G
    Registriert seit
    14.10.2006
    Ort
    Pasching OÖ
    Beiträge
    6.186
    Du bist sicher das in deiner TWI_Master.c kein Interrupt verwendet wird.
    Grüsse Hubert
    ____________

    Meine Projekte findet ihr auf schorsch.at

  8. #8
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    08.05.2005
    Ort
    Issum
    Alter
    45
    Beiträge
    2.236
    Nur mal so eine Frage am Rande,
    was ergibt
    Code:
    (NumberOverflow0 * 65536)
    wenn
    Code:
    unsigned int NumberOverflow0 = 0;
    Gibt es hier keinen Überlauf ?
    Software is like s e x: its better when its free.
    Linus Torvald

  9. #9
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    20.05.2006
    Ort
    Lippe
    Alter
    48
    Beiträge
    524
    Hallo,

    das dachte ich auch erst und wollte schon ein Typecasting vorschlagen. Aber da 65536 nicht mehr in 2Byte geht (max. 65535) sollte er schon richtig rechnen.

    Gruß

    Jens

  10. #10
    Neuer Benutzer Öfters hier
    Registriert seit
    21.10.2006
    Beiträge
    22
    Wie gesagt funktioniert die Frequenzmessung einzeln korrekt. Die Overflow-Variable wird gelegentlich auf 1 gesetzt, wenn zwischen der ersten Messung und der zweiten Messung die 65535 des Timers auf 0 springen.

    Ich hatte auch schon vermutet, dass die I2C-Routine irgendwelche Interrupts nutzt, die meine Frequenz verfälschen. Aber im Quellcode sind nur Registerabfragen und wait-Befehle. Mal abgesehen davon, wäre Interrupts auch garnicht schlimm, da eine Interrupt-Routine nie mittendrin verlassen werden kann, sondern immer erst am Ende.

    Wenn ich vor den I2C-Befehlen ein cli() schreibe, dürften ja keine Interrupts ausgeführt werden? Da I2C dann noch funktioniert, gehe ich davon aus, dass die Bibliotheken keine Interrupts enthalten.

    Edit:
    Könnte folgender Code aus meiner TWI-Bibliothek meinen INT0 beeinflussen?

    /*
    ** Wait until transmission completed
    */
    while (!(TWCR & (1<<TWINT)));

Seite 1 von 3 123 LetzteLetzte

Berechtigungen

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