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
voidinit(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
intmain(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
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.
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.
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.
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
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.
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.
>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 ...
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.
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!
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!
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.
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.
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...
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 ;-)
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...
;-) 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