Timer0 Problem atmega8

Gast #973545
Hi,

Ich versuche softwaremäßig eine Frequenz an einem Port pin zu erzeugen.

Das prog:
1
ISR(TIMER0_OVF_vect)
2

3
{
4
  cli();
5

6

7
      time1++;
8
      TCNT0 = 240;
9
  sei();
10

11
}
12

13

14
void init(void)
15

16
{
17

18
  
19

20
  //Konfiguration der Outputs
21

22
  output_IO_Direction_REG |= (1<<out1);
23

24
  output_IO_Direction_REG |= (1<<out2);
25

26

27
  //Konfiguration Timer 0
28
  TCNT0 = 240
29
     TCCR0 = (1<<CS00);      //kein vorteiler
30

31

32
      TIMSK = (1<<TOIE0);  //aktiviere Timer0  overflow
33

34

35

36
  sei();
37

38
}
39

40
int main(void)
41

42
{
43
   while(1){
44

45

46
  if(time1 < gl_impulsdauer){
47

48
        output_IO_Port |= (1<<out1);
49

50
        }
51

52
  else{
53

54
        output_IO_Port &=~ (1<<out1);
55

56
        }
57

58
  if(time1 >= gl_pausendauer){
59

60
        time1 = 0;
61

62
        }
63
        }
64
}

Soweit funktioniert es auch. Setze ich aber TCNT0 = 255 scheint es als 
hätte sich der kontroller aufgehangen.

Das Selbe wenn ich den Vorteiler auf 8 stelle. sobald ich  TCNT0 auf 255 
setzte funktioniert nichts mehr.

Hat jemand eine idee?


Gruß Jörn
#973557
Ein Interrupt-Aufruf dauert normalerweise mehr als 20 CPU-Takte. Wenn Du 
aber alle 8 oder sogar in jedem CPU-Takt einen Interrupt auslösen 
willst, ist es kein Wunder, dass nichts mehr läuft. Mich wundert, dass 
es bei 240 (also 16 Takte bis zum Überlauf) noch funktioniert (wobei ich 
vermute, dass da auch schon Interrupts verloren gehen und dadurch ein 
Jitter entsteht).

cli() und sei() haben im Interrupt Handler nichts verloren. Während der 
Abarbeitung eines Interrupts ist die Verarbeitung anderer Interrupts 
sowieso durch die Hardware gesperrt. Schau mal ins AVR-GCC-Tutorial.

Und wenn Du glaubst, dass die ganzen Leerzeilen in Deinem Code die 
Lesbarkeit erhöhen: Das Gegenteil ist der Fall. Abgesehen davon ist das 
Programm unvollständig. Es fehlt z.B. die Deklaration von time.

Wenn Du einigermaßen präzise Takte erzeugen willst, dann benutze einen 
Timer, der die CTC-Betriebsart hat (beim ATMega8 Timer 1 und 2) oder 
einen neueren AVR, bei dem auch Timer 0 das kann (z.B. ATMega88, 
pinkompatibel zum ATMega8). Timer-Preload ist v.a. bei höheren 
Frequenzen Murks, eben weil das nur mit Interrupt sinnvoll geht. CTC 
hingegen braucht keinen Interrupt und kann das Signal auch direkt 
hardwaremäßig an einem Pin ausgeben.
Gast #973604
dann willst du ja eine PWM machen, dafür ist OC ja genau richtig.
nimm einfach den 8 Bit Timer 2, das müsste reichen, außer du willst es 
genauer einstellen können.
Gast #973619
Achso die Frequenz soll auch variabel sein von ca. 50 Hz bis 300 Hz
Das ganze benötige ich 2 x und muss unabhängig voneinander sein...

Deshalb dachte ich es wäre in Software am einfachsten zu lösen.

Ich werde mich mal am OC versuchen

Danke schonmal für die Hilfe

Gruß Jörn
Gast #973691
ok dann musst du halt Timer 1 und Timer 2 verwendet, gibt dann halt 2 
Unterschiedliche Routinen ab, da der eine 8 und der andere 16 Bit.
Mit dem OCR Register änderst du die Pulsdauer und mit 2^8-TCNT bzw. 
2^16-TCNT die Frequenz.
Gast #973702
Ok, das hört sich gut an
mir ist nur noch nicht ganz klar wie der timer eingestellt werden muss.
1
  TCCR1B = (1<<CS11);     //Vorteiler 8
2
  TCCR1A = (1<<COM1A1)|(1<<COM1A0)|(1<<WGM12)|(1<<WGM10);  
3
  TCNT1 = 10000;
4
  OCR1A = 1000;    //Output Compare vergleichsregister

Das sind meine einstellungen... also eine PWM
doch wie muss ich das ganze einstellen um auch die frequenz verändern zu 
können
Gast #973705
>Wie bitte? Das TCNT hat man bei PWM in Ruhe zu lassen! Bitte lies Dir
>mal im Datenblatt und/oder im Tutorial durch, wie es geht.

Du kannst die gewünschte Frequenz ja nicht mit dem Vorteiler einstellen 
bzw. nicht genau genug, also musst du den Timer vorladen um dann die 
jeweilige Frequenz zu bekommen ...
#973710
Es gibt im Datenblatt eine Tabelle, in der alle Betriebsarten des Timers 
dargestellt sind. In der Tabelle steht auch, welcher Wert die 
Periodendauer des Signals (und damit die PWM-Frequenz) definiert. Im 
Datenblatt ist das der TOP-Wert (TOP Value). Damit kannst Du die 
PWM-Frequenz (in Zusammenarbeit mit dem Prescaler) praktisch beliebig 
einstellen.
#973713
Mätte wrote:
>>Wie bitte? Das TCNT hat man bei PWM in Ruhe zu lassen! Bitte lies Dir
>>mal im Datenblatt und/oder im Tutorial durch, wie es geht.
>
> Du kannst die gewünschte Frequenz ja nicht mit dem Vorteiler einstellen
> bzw. nicht genau genug, also musst du den Timer vorladen um dann die
> jeweilige Frequenz zu bekommen ...
Nö, das ist absoluter Quatsch! Gerade den Vorlade-Mist kann man sich mit 
der Hardware-PWM nämlich sparen. Noch mal: Lies es Dir im Datenblatt und 
im AVR-GCC-Tutorial durch und erzähl hier keinen Unsinn!
#973729
Mätte wrote:
>> erzähl hier keinen Unsinn!
> hab ja nicht behauptet, dass es die beste Variante ist, (mit Top macht
> halt alles die HW) aber funktionieren tuts.
Warum erzählst Du es überhaupt? Oben wurde schon mal auf die Probleme, 
die das Nachladen (per Interrupt) mit sich bringt, hingewiesen, und es 
ist nicht nur "nicht die beste" Variante, sondern die unsinnigste!
#973746
Mätte wrote:
> macht dem uC bei 300Hz ja nichts ...
Je nachdem, was das Programm sonst noch machen soll, schon. 300 unnötige 
Interrupts pro Sekunde sind u.U. zu viel. Also lass es einfach. Der µC 
hat das alles eingebaut, also sollte man das auch nutzen.
#973775
Jörn wrote:
> Mit welchem register lege ich denn nun die Top Value fest?
>
> Laut datenblatt ICP1  doch damit funktinoniert es nicht
Wenn überhaupt, dann ICR1.

Du solltest Dir auch beim Posten vielleicht ein wenig mehr Mühe geben. 
Dein Geschreibsel ist echt anstrengend zu lesen! Auch Groß- und 
Kleinschreibung sollten etwas weniger willkürlich eingesetzt werden. Und 
die Sache mit "ICP1" anstatt "ICR1" hätte sich durch etwas 
sorgfältigeres Arbeiten auch vermeiden lassen.
Gast #973793
Tja so ist das wenn man von so einem Timer in den Wahnsinn getrieben 
wird.
ICR1 hatte ich auch verwendet war nur ein Tippfehler hier im forum.

Hier nochmal meine neuen Einstellungen:
1
  TCCR1B = (1<<CS11)|(1<<CS10);
2
  TCCR1A = (1<<COM1A1)|(1<<WGM11)|(1<<WGM13);M
3

4
  OCR1A = 50;
5
  ICR1 = 500;

Laut Datenblatt:

PWM, Phase and Frequency Correct

TOP  =  ICR1
Update of OCR1X TOP

Mit OCR1A kann ich nun die Impulsdauer verändern.
Nur mit ICR1 kann ich immer noch nicht die Frequenz verändern.

Danke für eure mühe ;-)
#973803
Jörn wrote:
>
1
>   TCCR1A = (1<<COM1A1)|(1<<WGM11)|(1<<WGM13);M
2
>
Schau bitte nochmal genau ins Datenblatt und überprüfe, in welchem 
Register WGM13 steht! ((Kleiner Tipp: Es ist nicht im TCCR1A!)) Und 
das "M" hinter dem Semikolon steht da im Original hoffentlich auch 
nicht...
Gast #973809
;-) Nein das M ist im Orginal nicht vorhanden.

Meine güte was ein blöder Fehler, aber nach 4 Stunden sieht man auch den 
Wald vor lauter Bäumen nicht mehr.

Bin davon ausgegangen das die Bits in der Tabelle alle zu dem einen 
Register gehören.

Jetzt funktioniert es.

Vielen Dank

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 18 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.