Forum: Mikrocontroller und Digitale Elektronik Timer0 Problem atmega8


von Jörn (Gast)


Lesenswert?

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

von Jörn (Gast)


Lesenswert?

Achso ... init(); wird natürlich in main() als erstes aufgerufen

von Johannes M. (johnny-m)


Lesenswert?

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.

von Mätte (Gast)


Lesenswert?

Nimm "Output Compare" um dir deine Frequenz zu erzeugen, macht das 
Hardwaremäßig, ist genau und dein uC hat kein "Stress" ;)

von Johannes M. (johnny-m)


Lesenswert?

Mätte wrote:
> Nimm "Output Compare" um dir deine Frequenz zu erzeugen, macht das
> Hardwaremäßig, ist genau und dein uC hat kein "Stress" ;)
Timer 0 beim Mega8 hat keine Compare-Einheit.

von Mätte (Gast)


Lesenswert?

sorry, hab den ATM8 übersehen, dann ist klar ;)
dann nimm halt T/C 1 oder T/C 2
wie hoch soll die Frequenz denn sein ( laut Angaben ) ?

von Jörn (Gast)


Lesenswert?

ich möchte eine frequenz mit ca 300 hz erzeugen und dabei die 
impulsdauer zwischen 50uS und 200uS verstellen können

von Mätte (Gast)


Lesenswert?

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.

von Jörn (Gast)


Lesenswert?

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

von Mätte (Gast)


Lesenswert?

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.

von Johannes M. (johnny-m)


Lesenswert?

Mätte wrote:
> [...] und mit 2^8-TCNT bzw. 2^16-TCNT die Frequenz.
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.

von Jörn (Gast)


Lesenswert?

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

von Mätte (Gast)


Lesenswert?

>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 ...

von Johannes M. (johnny-m)


Lesenswert?

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.

von Johannes M. (johnny-m)


Lesenswert?

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!

von Mätte (Gast)


Lesenswert?

> 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.

von Johannes M. (johnny-m)


Lesenswert?

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!

von Mätte (Gast)


Lesenswert?

macht dem uC bei 300Hz ja nichts ...

von Johannes M. (johnny-m)


Lesenswert?

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.

von Jörn (Gast)


Lesenswert?

Mit welchem register lege ich denn nun die Top Value fest?

Laut datenblatt ICP1  doch damit funktinoniert es nicht

von Mätte (Gast)


Lesenswert?

>Der µC hat das alles eingebaut, also sollte man das auch nutzen.
Dem stimme ich zu ;)

von Johannes M. (johnny-m)


Lesenswert?

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.

von Johannes M. (johnny-m)


Lesenswert?

Mätte wrote:
>>Der µC hat das alles eingebaut, also sollte man das auch nutzen.
> Dem stimme ich zu ;)
Aha. Ich dachte schon, Du wärst einer von der Sorte, die ihr Auto nur im 
ersten Gang fahren, auch wenn es fünf Gänge hat...

von Jörn (Gast)


Lesenswert?

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 ;-)

von Johannes M. (johnny-m)


Lesenswert?

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...

von Jörn (Gast)


Lesenswert?

;-) 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

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.