PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Timer und PWM



Spongebob85
17.08.2007, 21:17
Moin!!! Ich lese mich grade durch den artikel AVR PWM auf der Seite www.microcontroller.net und bin grade bei "Clear Timer on Compare".
Für mich klingt völlig logisch das man den Takt der vom Prescaler kommt damit bequem teilen kann. Ich mache mir nur die ganze Zeit gedanke, weil da steht:

Für PWM:

Wenn eingestellt ist, dass der OC-Ausgang bei jedem Match umschaltet (toggle), entspricht der eingestellt Wert dem Pulsweitenverhältnis. Bei OCRnx=128 des 8 Bit T/C wäre also etwa die Hälfte der Zeit der Pin eingeschaltet.

Meiner meinung nach ist das keine PWM, da die einschalt und ausschaltzeit doch immer 1:1 ist.
Wenn der zähler z.B. bis 128 zählt und der OC-Ausgang ausschaltet, läuft der Zähler doch neu los und der OC-Ausgang schaltet auch bei 128 wieder ein (toggle halt).

Dadrunter kommt dann gleich der Abschnitt
Fast PWM.
Dort steht

Zählt von BOTTOM bis TOP, wobei TOP entweder 0xFF oder OCRnx sein kann.

Bei einem Match wird im

a) nicht-invertierenden Modus der Zähler gelöscht, und bei BOTTOM gesetzt

b) invertierenden Modus der Zähler gesetzt, und bei BOTTOM gelöscht.

Klingt theoretisch kompliziert, praktisch invertiert es nur den Ausgang.

Dazu:
Was heißt der Zähler wird gelöscht? Oder soll das heißen der Ausgang wird z.B. im nicht-invertierendem modus bei Match auf 0 gesetzt, bei Bottom wieder auf 1? Dann wäre das ja auf jeden Fall eine PWM, falls der Zähler dann bis 0xff weiterzählt bevor er wieder bei Bottom anfängt.

Hoffe ihr habt meine Frage überhaupt verstanden 8-[
MfG Jan

Spongebob85
17.08.2007, 22:18
Hab hier jetzt mal ein kleines Programm geschrieben. Funktioniert natürlich mal wieder gar nix!!!



#include <avr/io.h>
#include <stdint.h>
#define CPU_F 1000000UL

int main(void)
{
while(1)
{
DDRB |= (1<<DDB3); //Damit ist PB4 (OC0 PWM-Ausgang) als Ausgang gesetzt
PORTB |= (1<<PB3);

TCCR0 |= ((1<<WGM00) | (1<<WGM01)); //hier stelle ich Modus 3 ein (fast PWM)
TCCR0 |= ((1<<COM00) | (1<<COM01)); //Set OC0 on Compare Match, Clear OC0 on Top
TCCR0 |= ((1<<TSC00) | (1<<TSC02)); //Takt kommt vom Vorteiler (prescaler) setzt
//die ZählerFrequenz auf ca. 1kHz (teilung durch 1024)
TCNT0 = 0xff; //Zähler soll von 0 bis 255 zählen
OCR0 = 0x80; //Match soll bei 128 erfolgen, Match ist doch aber gleich Top, oder?
//(bottom = 0), (Match = 128), (Top=Max=255)???
}
}

//LED müsste ca. halb hell leuchten


Kann mir jemand sagen wieso? Kann mir jemand was zu meinem Beitrag oben sagen, stimmen die Kommentare?
Hoffe irgendjemand kann mir helfen.
MfG Jan

izaseba
17.08.2007, 22:40
Hallo Jan,
dann unterhalten wir zwei uns mal wieder ;-)

CTC hast Du recht, dieser Modus ist eigentlich nicht dazugedacht PWM zu erzeugen, sonder einen ziemlich genauen Takt.
PWM kommt erst richtig gut, wenn der Timer frei durchlaufen kann, und Du nur die Pulsweite mit OCR verstellst...
Fast PWM...
Ja ich benutze den eigentlich nur, die anderen sind mir zu kompliziert
Aber auf die schnelle erklärt:
Du kannst Ihn einstellen, daß der Ausgang bei Bottom HIGH geht, und bei Comparematch LOW, das wäre dann der normale Modus, oder aber bei Bottom LOW und bei Compare Match HIGH das wäre dann der invertierte Modus...
Uff, ich hoffe, daß es soweit richtig ist, habe im Moment keine Lost Dattenblatt rauszuholen...
Zu deinem Programm,
mach den Timerinit außerhalb der while(1) Schleife, so ist das Käse, ich weiß nicht, ob er das mag ständig eingestellt zu werden ;-)
Den TCNT0 würde ich auch in Ruhe lassen.
Gruß Sebastian
P.S. Was hast Du für Kontroller, bist Dir sicher, daß der Timer 0 PWM hat ?
P.P.S Hm, wird wohl so sein, wenn der Kompiler nicht jamert...

Spongebob85
17.08.2007, 22:56
Jetzt hab ich wieder ein richtig blödes Problem.
Hab einen Neuen Ordner angelegt. Da hab ich mein Prog (pwm.c) reingespeichert. Hab mir einen neuen Makefile gemacht (die gleichen einstellungen wie beim alten) und den auch da rein gespeichert.
Wenn ich auf Makeall drücke kommt die Meldung:

make.exe: *** No rule to make target `obj/main.o', needed by `pwm.elf'. Stop.

> Process Exit Code: 2
> Time Taken: 00:01

Das is bestimmt wieder was richtig blödes. Aber ich komm wieder nicht klar.

Der Code jetzt:



#include <avr/io.h>
#include <stdint.h>
#define F_CPU 1000000UL

int main(void)
{
DDRB |= (1<<DDB3); //Damit ist PB4 (OC0 PWM-Ausgang) als Ausgang gesetzt
PORTB |= (1<<PB3);

TCCR0 |= ((1<<WGM00) | (1<<WGM01)); //hier stelle ich Modus 3 ein (fast PWM)
TCCR0 |= ((1<<COM00) | (1<<COM01)); //Set OC0 on Compare Match, Clear OC0 on Top
TCCR0 |= ((1<<TSC00) | (1<<TSC02)); //Takt kommt vom Vorteiler (prescaler) setzt
//die ZählerFrequenz auf ca. 1kHz (teilung durch 1024)

while(1)
{

OCR0 = 0x80; //Match soll bei 128 erfolgen, Match ist doch aber gleich Top, oder?
//(bottom = 0), (Match = 128), (Top=Max=255)
}
}

//LED müsste ca. halb hell leuchten


Ach ja. Ich hab ein ATMega32
Im datenblatt steht 8-bit Timer/Counter0 with PWM.

Bis jetzt bin ich ja immer gut ums Datenblatt rumgekommen, aber heut hab ich´s echt mal gelesen :-)

MfG Jan

izaseba
17.08.2007, 23:11
make.exe: *** No rule to make target `obj/main.o', needed by `pwm.elf'. Stop.

main.o pwm.elf ist hier nicht was faul ??
Ach ja OCR0 kannst Du auch aus der main werfen...
Ehm und TCCR0 könntest Du auch in einer Zeile setzen, dann aber ohne |
Das ist gut ins Dattenblatt zu schauen, man muß nicht unbedingt alle Seiten Lesen, nur das was einen interessiert...
Gruß Sebastian

P.S. Dein Programm sieht schon nicht schlecht aus, man sieht, das Du Dattenblatt gelesen hast ;-)
P.P.S die DDR Register kannst Du auch ohne | setzen.

Spongebob85
18.08.2007, 00:51
Ja, würde nur gern wissen was da schon wieder faul ist.
ORC0 aus der main werfen?
Du meinst sicher aus der While-schleife, oder?
TCCR0 in eine Zeile ohne | ?
So?


#include <avr/io.h>
#include <stdint.h>
#define F_CPU 1000000UL

int main(void)
{
DDRB = (1<<DDB3); //geaendert
PORTB |= (1<<PB3);

TCCR0 |=(1<<WGM00)(1<<WGM01)
(1<<COM00)(1<<COM01) //geaendert
(1<<TSC00)(1<<TSC02);

OCR0 = 0x80; //geaendert

while(1)
{
}
}

//LED müsste ca. halb hell leuchten


MfG

P.S. Wenn ich mein Programm als main.c speichere geht das alles mit brennen und so. Jetzt Funzt alles aber man sieht die LED sogar blinken. Ich probiers mal mit ner kleineren vorfrequenzteilerzahl.

Spongebob85
18.08.2007, 01:22
Was jetzt noch cool wäre, wäre wenn die led heller und dunkler werden würde. Ich kann ja leider keine variable nehmen, die ich von 00 bis ff hochzählen kann. Da gibts doch bestimmt etwas, oder?

Gruß Jan

izaseba
18.08.2007, 12:36
Du meinst sicher aus der While-schleife, oder?
Ja das meinte ich (vielleicht sollte man nicht zu viel gleichzeitig machen...)


PORTB |= (1<<PB3);

TCCR0 |=(1<<WGM00)(1<<WGM01)
(1<<COM00)(1<<COM01) //geaendert
(1<<TSC00)(1<<TSC02);

Warum veroderst Du alles?


PORTB = (1<<PB3);

TCCR0 =(1<<WGM00)(1<<WGM01)
(1<<COM00)(1<<COM01) //geaendert
(1<<TSC00)(1<<TSC02);
So finde ich das schon besser....


Ich kann ja leider keine variable nehmen, die ich von 00 bis ff hochzählen kann. Da gibts doch bestimmt etwas, oder?
Warum kannst Du keine Variablen nehmen ?



uint8_t pwm=0;
while(1){
OCR0 =pwm++;
_delay_ms(10);
}

zum Beispiel...
oder ?
Gruß Sebastian

Spongebob85
18.08.2007, 14:10
Aber mit der PWM Variablen wird doch dezimal hochgezählt. Kann das Register OCR0 denn z.B. mit 250 was anfanden? Wenn ja, woher weiß das denn, wenn ich OCR0 = 80; schreibe, ob ich dezimal 80 oder hexadezimal 80 (was ja dezimal 128 sind) meine? Oder nimmt das die informationen aus der Variablen, und weis dadurch das die uint ist das das dezimal ist?
Oder denke ich nur wieder zu konfus?

Gruß Jan

izaseba
18.08.2007, 14:38
Oder denke ich nur wieder zu konfus? ;-)

Wenn Du OCR0 = 80 schreibst wird der dezimale Wert geschrieben,
Wenn Du OCR0 = 0x80 schreibts wird hex 0x80 dez 128 geschrieben
Im Endefekt ist es doch egal ob so oder so, wenn es Spaß macht kannst Du mein Beispiel von oben hexadezimal schreiben


uint8_t pwm=0x00;
while(1){
OCR0 =pwm++;
_delay_ms(10);
}
Der Kompile weiß anhand 0x wie Du das meinst

Spongebob85
18.08.2007, 15:13
Das is ja echt cool!!!
Dann geht das ja sicher auch mit DDRx.
Wenn ich z.B. Port0 und Port7 aus ausgang setzen will kann ich also auch
DDRx = 129; schreiben?
So hat man ja echt voll viele Möglichkeiten.

Dann werde ich mich mal mit bald mal mit ADC auseinandersetzen.

Ich will mir bald einen Fernsteuerpanzer bestellen und den umbauen, so das
der hindernisse erkennt und so, fehlt also bald nur noch das Geld. :-)

Gruß Jan

fluchtpunkt
18.08.2007, 15:44
TCCR0 =(1<<WGM00)(1<<WGM01)
(1<<COM00)(1<<COM01) //geaendert
(1<<TSC00)(1<<TSC02);
Und das funktioniert so? So ganz ohne "|"?

EDIT:


Wenn ich z.B. Port0 und Port7 aus ausgang setzen will kann ich also auch
DDRx = 129; schreiben?
So hat man ja echt voll viele Möglichkeiten.
Ich hoffe du bist gut im Kopfrechnen. Viel Spass dabei irgendwann noch Zuordnungen vom Stile DDRx = 219; zu durchschauen. Und ich hoffe das du nie vorhast auf was 32bittiges Umzusteigen. DDRx = 2890509849;
Es hat schon nen Sinn warum man das Hexadezimalsystem eingefuehrt hat...

izaseba
18.08.2007, 15:47
Das is ja echt cool!!!
:-s ..... :cheesy: :cheesy:

Wenn ich z.B. Port0 und Port7 aus ausgang setzen will kann ich also auch
DDRx = 129; schreiben?
Tja, da geb ich Dir recht, Du kannst auch DDRX=0x81 schreiben :-#
oder, was meinst Du was bei (1<<<Px7)|(1<<Px0) rauskommt ?
Tip.
Es hat moch keinem geschadet sich mal die includes anzuschauen...
Schau mal rein, und such darin, wie z.B PB0 oder PD7 definiert sind...
Bei M32 müßte das die m32io.h sein :-k

Gruß Sebastian

izaseba
18.08.2007, 15:51
Und das funktioniert so? So ganz ohne "|"?

Nein!
Ich meine ohne PORTD | =....... die anderen | müßen schon bleiben.

Wo der Unterschied zwischen PORTD |=.... und PORTD= liegt kannst Du selber rausfinden...

Spongebob85
18.08.2007, 22:04
Wnn ich nur wüsste wo man diese Includes ansehen kann. Hab nur eine Seite und zwar http://www.nongnu.org/avr-libc/user-manual/index.html
aber da ist z.B. m32io.h nicht.
Gruß Jan

Roberto
11.11.2007, 02:08
Hallo
Versuche mich auch gerade in PWM
TCCR0 =(1<<WGM00)(1<<WGM01)
(1<<COM00)(1<<COM01) //geaendert
(1<<TSC00)(1<<TSC02);
Ist das sicher mit dem TSC00/02 ?
Ich finde im Datenblatt das nirgends :-k
Meint Ihr vielleicht CS02/00 ?

l.G. Roberto

roboterheld
11.11.2007, 09:43
...DDRx = 129; schreiben? ......


nicht zu empfehlen bei c so eine wald und wiesenproggerei.