Timer0 Problem atmega8

Gast #973545
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
#973557
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.
Gast #973702
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
#973710
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.
#973713
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!
#973729
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!
#973775
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.
Gast #973793
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 ;-)

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren