mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Timer zählt nur bis zu Hälfte


Autor: Doubleyou W. (doubleyou)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich habe mich heute ein bisschen in die Timer in Verbindung mit 
Interruptfunktionen beschäftigt. Ich würde gerne eine Softwarelösung zum 
generieren von zwei PWM Signale realisieren. Ich habe dazu die CTC 
Methode verwändet. Der Code hänge ich unten an.

Im Einsatz ist ein ATMEGA8 an einem 16MHz Quarz.
Zum Berechnen des OCR Wertes habe ich folgende Formel benutzt:

OCRnx = e ^ (0,00330082*iBit+5,86166)

Wobei iBit für einen Wert vom AD Wandler steht und somit zwischen 
0-1024bit liegt. Die Formel habe ich über Gnumeric ermittelt um den 
Bereich von 1,5kHz bis 4,5kHz abzudecken. Über die Formel zum Berechnen 
der Freqenzen mit Hilfe folgender Formel hat auch in Exel exakt 
gestimmt. Jedoch bekomme ich bei dem unten angehängten Programm exakt 
die hälfte der Frequenz. Obwohl der Prescaler auf 1 eingestellt ist.

Freq = (F_CPU/(Prescaler*(OCRnx+1)))

Wie man sie auch hier findet: 
http://www.mikrocontroller.net/articles/AVR-GCC-Tu...

Mir ist kein offensichtlicher Fehler aufgefallen vielleicht habt ihr ja 
noch einen Tipp für mich.
volatile uint8_t flag;

int OCR(int iBit)
{
  float f_e, f_func_var1, f_func_var2, f_OCR_res, f_OCR_zres;
  int i_OCR_res;
  f_e = 2.718282;
  f_func_var1 = 0.00330082;
  f_func_var2 = 5.86166;
  f_OCR_zres  = ((f_func_var1 * iBit) + f_func_var2);
  f_OCR_res   = (float) pow(f_e, f_OCR_zres);
  f_OCR_res  += 0.5;
  i_OCR_res   = (int) f_OCR_res;
  return i_OCR_res;
}

float frequenz(int i_OCR)        
{
  float f_freq_res;  
  f_freq_res = (CPU_T/(PRESCALE*(i_OCR+1)));
  f_freq_res = (f_freq_res / 1000);
  return f_freq_res;
}


ISR (TIMER1_COMPB_vect)//(SIG_OUTPUT_COMPARE1B)
{
  if (flag == 1) {
    flag = 0;
    PORTB |= (1<<PB1);
    PORTB &= ~(1<<PB2);
  }
  else {
    flag = 1;
    PORTB &= ~(1<<PB1);
    PORTB |= (1<<PB2);
  }
}
int main(void)

{
        ...
        //PortB Einstellen
  DDRB |= (1 << DDB1) | (1 << DDB2); //PIN PB1 und PB2 als Ausgang
  //Timer Einstellen
  TCCR1B = 0x00;
  TCCR1B |= (1<<WGM12); //Timer1 mit Auflösung 2¹⁶ in CTC Modus
  TCCR1B |= (1<<CS10);  //Prescaler auf 1
  TIMSK  |= (1<<OCIE1B);// Output Compare Match Interrupt Enable
  sei();
        ...
        //Hauptprogramm starten

  while(1){
        ...
        cli();
        OCR1A = (uint16_t) iOCR;
        sei();
        ...
}

Autor: Stefan B. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vermutung: Pro ISR erzeugst du nur eine Halbperiode deines Signals. Die 
ISR müsste also doppelt so oft aufgerufen werden, um eine ganze Periode 
zu erzeugen.

Tipp: Bei Fragen den Quellcode und erwartete/gemessene Werte für ein 
komplettes Beispiel angeben. Dann kann man das im Simulator nachstellen 
und braucht nicht zu vermuten.

Autor: Knut (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Moin,

im Datenblatt des ATmega8 steht auf Seite 91/307 die Formel zu 
Berechnung der Ausgangsfrequenz. Da der Ausgang bei jedem Compare Match 
toggelt, hast du immer einen Faktor von 1/2 drinn!

Autor: Doubleyou W. (doubleyou)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Na dann hab ich da wohl was überlesen. Danke für die Information dann 
werde ich das ganze nochmal überarbeiten.

Mit freundlichen Grüßen

DoubleU

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.