Forum: Mikrocontroller und Digitale Elektronik Timer0/ PWM auf Atmega48/88


von oyla (Gast)


Lesenswert?

Ahoi!
So langsam bin ich am Ende mit meinen Nerven:

Habe gestern den Umstieg von Bascom auf C gewagt, heute versuche den 
ganzen Nachmittag schon den Timer0 vom ATmega48 so zum laufen zu 
bekommen, dass ich eine Frequenz um die 440Hz zu hören bekomme. Der 
Piezo ist an PB1 (OC1A) angeschlossen und läuft auch (Testprogramm via 
delay).
Bei den ganzen Registern wird man wahnsinnig...

Ich habs sowohl über den weg Software-PWM als auch direkt per Fast-PWM 
versucht, auch hab ich mir schon nen Wolf gegoogled.

Meine Frage: Hat jemand einen Beispielcode, den ich nachvollziehen kann, 
am besten für mein Problem? Ich glaub per Reverse-engineering komme ich 
besser an die Sache, und was google ausspuckt ist entweder für ältere 
Prozessoren oder nicht für Fast-Pwm oder,oder.... :/

Schöne Restwoche!
oyla

von spess53 (Gast)


Lesenswert?

Hi

>und was google ausspuckt ist entweder für ältere
>Prozessoren oder nicht für Fast-Pwm oder,oder.... :/

Zum Erzeugen von Frequenzen ist CTC besser als Fast PWM geeignet. Und 
der erste Anlaufpunkt ist nicht Gurgel sondern das Datenblatt.

MfG Spess

von Matthias (Gast)


Lesenswert?

Für Soundausgabe per PWM nehme ich prinzipiell den PFC-PWM Mode.
Die CMP-Register liefern den Signalausgang und das ICR-Register ist der 
TOP
Wert (CMP = (TOP/2)).
Man muss nur dem Prescaler einen sinnvollen Wert verpassen und den 
Output Compare Mode korrekt einstellen (Achtung, da hats im Datenblatt 
haufenweise Tabellen für alle Modis - also nix durcheinander bringen!)

von oyla (Gast)


Lesenswert?

> Und
> der erste Anlaufpunkt ist nicht Gurgel sondern das Datenblatt.

Wenn ich mich komplett neu einfuchsen muss, ziehe ich erst, meist 
verständlichere Anleitungen zu rate, natürlich im Vergleich mit dem 
Datenblatt. Für den Einstieg an sich ist das Datenblatt einfach zu 
komplex teilweise (und mit meinen nicht flüssigen aber gut ausreichenden 
Sprachkenntnissen auch nich unbedingt einfachst zu lesen). Aber ohne 
gehts nicht, das stimmt schon.

>Zum Erzeugen von Frequenzen ist CTC besser als Fast PWM geeignet.

Dann versuch ichs mal...

von spess53 (Gast)


Lesenswert?

Hi

>Wenn ich mich komplett neu einfuchsen muss, ziehe ich erst, meist
>verständlichere Anleitungen zu rate, natürlich im Vergleich mit dem
>Datenblatt.

Datenblätter sind zwar nicht immer fehlerfrei. Aber immer tausend mal 
besser als der Müll den man so im www findet.

MfG Spess

von Karl H. (kbuchegg)


Lesenswert?

oyla schrieb:
>> Und
>> der erste Anlaufpunkt ist nicht Gurgel sondern das Datenblatt.
>
> Wenn ich mich komplett neu einfuchsen muss, ziehe ich erst, meist
> verständlichere Anleitungen zu rate, natürlich im Vergleich mit dem
> Datenblatt. Für den Einstieg an sich ist das Datenblatt einfach zu
> komplex teilweise (und mit meinen nicht flüssigen aber gut ausreichenden
> Sprachkenntnissen auch nich unbedingt einfachst zu lesen). Aber ohne
> gehts nicht, das stimmt schon.

Das kann ich verstehen. Die Kapitel sind schon sehr umfangreich im 
Datenblatt. Wenn man aber erst einmal weiß, welcher Modus was macht, 
dann ist es eigentlich sehr einfach.

Das interessante Kapitel bei jedem Timer ist das Kapitel "Register 
Summary". Dort sind alle Modi aufgeführt, die der jeweilige Timer kann. 
Dort suchst du dir den Modus raus, den du haben willst. Aus der Tabelle 
erhältst du so die Bitnamen der Bits (und ihre) Werte, die du setzen 
musst, damit dieser Modus ausgewählt wird. Mit diesen Bitnamen scrollst 
du etwas zurück und siehst nach, in welchem der Konfigurationsregister 
welches Bit beheimatet ist. So viele Konfigurationsregister gibt es ja 
normalerweise nicht - das geht also schnell.
Je nach Modus sind unter Umständen auch noch andere Register beteiligt. 
Welche das sind, steht ebenfalls in der ersten Tabelle bzw. ergibt sich 
aus dem Modus.
Wenn ein Ausgansgpin beteiligt ist (PWM), sucht man sich noch die zum 
Timer-Modus gehörende Tabelle für die Ausgangspins und ermittelt die zu 
setzenden Bits um dem Ausgansgpin ein bestimmtes Verhalten aufzuzwingen.

Dann noch den Vorteiler setzen (erst dann läuft der Timer tatsächlich) 
und das wars.

http://www.mikrocontroller.net/articles/FAQ#Timer

von oyla (Gast)


Lesenswert?

Das war schonmal eine sehr gute Hilfe, danke! Es will noch nicht 
anlaufen, irgendwas habe ich wohl noch nicht ganz bedacht. Hier der 
Code:
1
#include <avr/io.h>
2
#include <util/delay.h>
3
#include <avr/interrupt.h>
4
5
6
int main() {
7
  DDRB = 0xff; PORTB = 0xFF; // alles auf Ausgang und An
8
  DDRC = 0xff; PORTC = 0xFF;
9
10
  TCCR0A |= (1<<COM0A0); // Toggle OC1A
11
  TCCR0A |= (1<<WGM01); //Modus wählen (CTC) - WGM02 ist in TCCR0B, gerade unwichtig
12
13
  TCCR0B |= (1<<CS01) | (1<<CS00); //Taktquelle und Prescale (64)
14
15
  OCR0A = 15;
16
  
17
  sei(); //Erlaube inter. (nötig?)
18
19
  while(1){}
20
21
22
}

Wo ist der grobe Verstoß? :)

von oyla (Gast)


Lesenswert?

Edit:

Ich bin davon ausgegangen, dass ich bei 1000000/64 (Pres.) / 15 auf 
1040Hz komme, sollte hörbar sein.

von Stefan E. (sternst)


Lesenswert?

1
  TCCR0A |= (1<<COM0A0); // Toggle OC1A
Nein. Timer0 kann keinen Pin toggeln, der zu Timer1 gehört. Was hier 
getoggelt wird, ist OC0A.

von Thomas E. (thomase)


Lesenswert?

oyla schrieb:
> TCCR0A |= (1<<COM0A0); // Toggle OC1A
Damit kannst du PB1(OC1A) lange lauschen. OC1A ist für Timer1.
Deine Einstellung toggelt OC0A(PD6).

mfg.

von oyla (Gast)


Lesenswert?

oh. Das scheint ein Kommentarfehler zu sein. Laut Datenblatt Seite 101 
siehts so aus:

COM0A1 COM0A0 Description
  0      1    Toggle OC0A on compare match
...

und das habe ich ja getan, denke ich?

von Stefan E. (sternst)


Lesenswert?

oyla schrieb:
> oh. Das scheint ein Kommentarfehler zu sein. Laut Datenblatt Seite 101
> siehts so aus:
>
> COM0A1 COM0A0 Description
>   0      1    Toggle OC0A on compare match
> ...
>
> und das habe ich ja getan, denke ich?

Ja, aber wo genau hängt der Piezo denn nun dran? Im ersten Post steht:
> Der Piezo ist an PB1 (OC1A) angeschlossen

Und wenn er nun doch tatsächlich an OC0A hängt, dann musst du den Pin 
noch zum Ausgang machen.

von Thomas E. (thomase)


Lesenswert?

oyla schrieb:
> und das habe ich ja getan, denke ich?
PD6 muß auf Ausgang stehen. sonst toggelt der nicht. Wo ist dein Piepser 
denn jetzt angeschlossen?

oyla schrieb:
> Piezo ist an PB1 (OC1A) angeschlossen und läuft auch (Testprogramm via
> delay).

mfg.

Edit: @Stefan Ernst: Nächstes Mal bin ich schneller.

von oyla (Gast)


Lesenswert?

Es läuft! :)

Tut mir leid! Ihr hattet recht, ich hatte den Piezzo falsch angeklemmt. 
Eobei ich eben geguckt habe, die Versuche die ich vorher gemacht hatte, 
sind dennoch nicht funktionstüchtig. Erstmal soweit :)

Hier für die, die den selben Leidenweg haben der richtige Code:
1
#include <avr/io.h>
2
3
int main() {
4
5
  DDRB = 0xff; PORTB = 0xFF; //Datenrichtungen
6
  DDRC = 0xff; PORTC = 0xFF;
7
  DDRD = 0xff; PORTD = 0xFF;
8
9
  TCCR0A |= (1<<COM0A0); // Toggle OC0A (PD6)
10
  TCCR0A |= (1<<WGM01); //Modus wählen (CTC) - WGM02 ist in TCCR0B, gerade unwichtig
11
12
  TCCR0B |= (1<<CS01) | (1<<CS00); //Taktquelle und Prescale (64)
13
14
  OCR0A = 15; //Zählgrenze
15
16
  while(1){
17
    //Hauptprogramm
18
  }
19
20
21
}

Dankesehr! Nun kann ich doch ruhig schlafen :)
Schöne Restwoche!

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.