www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Analog Komparator Input Capture + Timer


Autor: Sven (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

leider muss ich auch nochmal mit dem Thema Analog Komparator anfangen...

Ich versuche ganz einfach die Zeit zwischen 2 Flanken zu messen, und 
verwende dazu Testweise den Timer 1, der alle 1 Sekunde einen überläuft. 
Da die Signalfrequenz aber über 1Hz ist passiert das aber nie, ist also 
nur zu Testzwecken so gewählt.
Erkennt der Komparator eine steigende Flanke sollte ja der Zählerstand 
in das ICR1x Register kopiert werden, welches ich dann gleich über den 
UART verschicke. Danach stelle ich den Timer wieder auf die 1 Sekunde 
ein, so dass die nächste Messung beginnen kann.

Den Timer Initialisiere ich so:
void timer_init(void)
{

  TCCR1A = 0;
  TCCR1B |= (1<<ICNC1) | (1<<ICES1) | (1<<CS12)| (1<<CS10);  // prescaler 1024

  ACSR = (1<<ACIC) | (1<<ACIS1) | (1<<ACIS0);// rising edge, timer 1

  TIMSK |= (1<<TICIE1) | (1<<TOIE1);  // input compare + overflow

  TCNT1H = 0xC2;  // preset for 1sec interrupts
  TCNT1L = 0xF7;

  TIFR &= ~(1<<ICF1);

}

Dazu habe ich folgende ISRs:
ISR(SIG_COMPARATOR)
{
    while( (UCSRA & 1<<UDRE) == 0 );
      UDR = 10;


}


ISR(TIMER1_CAPT_vect)
{
    
    cli();
    c_time = ICR1L;
    c_time += (ICR1H<<8);
    
    c_time -= 49911;  // offset durch preset value  
    c_time /= 61;  // scale to 8 bits


    TCNT1H = 0xC2;
    TCNT1L = 0xF7;
  
    TIFR &= ~(1<<ICF1);

    while( (UCSRA & 1<<UDRE) == 0 );
      UDR = c_time;

    sei();
}


ISR(TIMER1_OVF_vect)
{

    while( (UCSRA & 1<<UDRE) == 0 );
      UDR = 11;

    TCNT1H = 0xC2;
    TCNT1L = 0xF7;

}

In der main mache ich nur:
int main( void )
{

  timer_init();
  uart_init();
  sei();

  while(1){

  }
}
Jetzt habe ich leider noch das Problem, dass ich fast immer 2 mal den 
"Messwert" am PC empfange, und dazwischen sehr viele (~20) 0en gesendet 
werden. Die Signalquelle ist ein Frequenzgenerator der einen 0-5V Sinus 
erzeugt, und hängt an AIN1. AIN0 habe ich über einen Spannungsteiler auf 
2,5V gelegt.

Kann mir irgendjemand sagen was das Problem an meinem Code ist?

Autor: Johnny (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Damit Dir geholfen werden kann, würde ich noch den verwendeten uC 
angeben.

Autor: Sven (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich verwende einen Mega8 der mit 16Mhz Quarz läuft.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wie schnell wird dein µC getaktet?
Welche Frequenz legst du an den Komperator an?


Lass in einer ISR das Interrupt Flag in Ruhe! sei() und cli() haben in 
einer ISR normalerweise nichts verloren.
Ein Flag Bit in den Interrupt Registern kann man nicht mit
    TIFR &= ~(1<<ICF1);
löschen. Damit löscht du alle anderen Flag-Bits, nur das ICF1 Flag nicht 
:-)

Dein Compiler unterstützt dich beim Auslesen von 16-Bit Pseudoregistern. 
Nutze das!

Entscheide dich für Hex oder Dezimal, je nachdem was in deiner Situation 
am sinnvollsten ist. Aber mische nicht die Zahlensysteme, wenn es nicht 
notwendig ist.

Achte auf deine Einrückungen. Die Ausgabe auf die UART suggeriert durch 
die äussere Form an dieser Stelle, dass sie von der while-Schleife 
wiederholend kontrolliert wird. Dem ist nicht so!
ISR(TIMER1_CAPT_vect)
{
    c_time = ICR1;

    c_time -= 49911;  // offset durch preset value  
    c_time /= 61;  // scale to 8 bits

    TCNT1 = 49911;
  
    while( (UCSRA & 1<<UDRE) == 0 )
      ;
    UDR = c_time;

    TIFR |= (1<<ICF1);
}

Autor: Sven (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vielen Dank Dir schon mal! Das mit den 16 bit Registern habe ich noch 
nie gesehen und ist wirklich sehr praktisch.

Leider habe ich noch nicht wirklich rausgefunden wo die 0en herkommen, 
aber ansonsten funktioniert es soweit ganz gut.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.