Hallo,
habe mir das demoprogramm aus dem Tutorial Bereich mal angeschaut zur
PWM und LED Fading.
Möchte erstmal das Programm mit einer Fast PWm 8bit laufen lassen. Dazu
habe ich mir den Quelltext angepasst in C auf das STK500 bzw habe ich
versucht.
1 | //*****************************************************************************
| 2 | //*
| 3 | //* LED fading test
| 4 | //* uses exponential PWM settings to achive visual linear brightness
| 5 | //*
| 6 | //* ATmega32 @ 8 MHz
| 7 | //*
| 8 | //*
| 9 | //*****************************************************************************
| 10 |
| 11 | #define F_CPU 8000000L
| 12 |
| 13 | #define true 1
| 14 | #define false 0
| 15 |
| 16 | #define STK500 true
| 17 |
| 18 | #include <inttypes.h>
| 19 | #include <avr/io.h>
| 20 | #include <util/delay.h>
| 21 | #include <avr/pgmspace.h>
| 22 |
| 23 | // global variables
| 24 |
| 25 | uint16_t pwmtable_8C[16] PROGMEM = {0, 2, 3, 4, 6, 8, 11, 16, 23, 32, 45, 64,
| 26 | 90, 128, 181, 255};
| 27 |
| 28 | // long delays
| 29 |
| 30 | void my_delay(uint16_t milliseconds) {
| 31 | for(; milliseconds>0; milliseconds--) _delay_ms(1);
| 32 | }
| 33 |
| 34 |
| 35 |
| 36 | // 8-Bit PWM with 16 different settings
| 37 |
| 38 | void pwm_8_16(uint16_t delay){
| 39 |
| 40 | int16_t tmp;
| 41 |
| 42 | #if STK500
| 43 | TCCR1A = (0<<PWM11)|(1<<PWM10)|(1<<COM1A1)|(1<<COM1A0); // inverted PWM on OC1A, 8 Bit Fast PWM
| 44 | #else
| 45 | TCCR1A = 0x81; // non-inverted PWM on OC1A, 8 Bit Fast PWM
| 46 | #endif
| 47 | TCCR1B = 0x08;
| 48 |
| 49 | TCCR1B &= ~0x7; // clear clk setting
| 50 | TCCR1B = (1<<CS12); // precaler 256 -> ~122 Hz PWM frequency
| 51 |
| 52 | for(tmp=0; tmp<=15; tmp++){
| 53 | OCR1A = pgm_read_word(pwmtable_8C+tmp);
| 54 | my_delay(delay);
| 55 | }
| 56 |
| 57 | for(tmp=15; tmp>=0; tmp--){
| 58 | OCR1A = pgm_read_word(pwmtable_8C+tmp);
| 59 | my_delay(delay);
| 60 | }
| 61 | }
| 62 |
| 63 |
| 64 | int main(void)
| 65 | {
| 66 | int16_t i;
| 67 | int16_t step_time=400; // delay in millisecond for one fading step
| 68 |
| 69 | DDRD |= (1<<PD0); // LED uses OC1A
| 70 |
| 71 | // test all fading routines
| 72 |
| 73 | while(1) {
| 74 |
| 75 |
| 76 | for(i=0; i<3; i++) pwm_8_16(step_time/4);
| 77 | my_delay(1000);
| 78 |
| 79 | };
| 80 |
| 81 | return 0;
| 82 | }
|
Da das Tutorial ja auf einen Atmega32 angepasst ist, habe ich aus dem
Datenblatt des Atmega8 versucht die Settings für TCCR1A rauszusuchen und
habe die oben eingesetzt. Wie ich TCCR1B setzen muss weiss ich nicht.
Kann mir da jemand weiterhelfen?
Zur Grundfunktion möchte ich noch wissen folgendes wissen: Wozu ist der
PWM Table gedacht, durch die beiden Vorschleifen wird die Led ja in 16
stufen hell geschaltet und nachher wieder runtergedimmt. Was ist das für
ein Wert? Und wie funktioniert das Programm in Bezug auf OCR1A?
Vielen Dank im vorraus
Hallo,
so richtig kann ich dir auch nicht helfen, aber das ASM Tutorial ist für
den ATmega8 geschrieben, vielleicht findest du dort die Einstellungen
für den C Code, mansche Dinge sehen doch ähnlich aus.
http://www.mikrocontroller.net/articles/AVR-Tutorial:_PWM
Schöne Grüße
Thomas
Christian S. schrieb:
> Da das Tutorial ja auf einen Atmega32 angepasst ist, habe ich aus dem
> Datenblatt des Atmega8 versucht die Settings für TCCR1A rauszusuchen und
> habe die oben eingesetzt. Wie ich TCCR1B setzen muss weiss ich nicht.
Dazu müsste ich auch erstmal das ursprüngliche Programm analysieren und
dann im Datenblatt des Ziel-Controllers schauen, wie die Timer zu
initialisieren sind. Im besten Fall reicht es, dieselben Flags zu
setzen, es kann aber auch sein, dass sich die Flags PWMxx und COMxx beim
atmega8 in verschiedenen control registern befinden. Wie gesagt,
Datenblatt anschauen!
> Zur Grundfunktion möchte ich noch wissen folgendes wissen: Wozu ist der
> PWM Table gedacht, durch die beiden Vorschleifen wird die Led ja in 16
> stufen hell geschaltet und nachher wieder runtergedimmt. Was ist das für
> ein Wert?
Die wahrgenommene Helligkeit ist nicht linear mit der Pulsdauer. Durch
die Tabelle wird das korrigiert.
> Und wie funktioniert das Programm in Bezug auf OCR1A?
Vermutlich wird darüber die Pulsweite gesteuert. Der Timer läuft ja im
PWM Modus. Schau dir das Datenblatt an, Kapitel über Timer1.
Das hatten wir doch schon mal. Da mus kaum was geändert werden.
Lediglich das Ausgangspin.
Beitrag "LED-Fading Tutorial nicht übertragbar?"
MfG
Falk
Tom M. schrieb:
>> Zur Grundfunktion möchte ich noch wissen folgendes wissen: Wozu ist der
>> PWM Table gedacht, durch die beiden Vorschleifen wird die Led ja in 16
>> stufen hell geschaltet und nachher wieder runtergedimmt. Was ist das für
>> ein Wert?
>
> Die wahrgenommene Helligkeit ist nicht linear mit der Pulsdauer. Durch
> die Tabelle wird das korrigiert.
@TO
Dazu ist es am allerbesten, du vergisst jetzt erst mal die super duper
Komfortlösung und machst eine ganz banale, plain vanilla PWM mit der du
auf die LED gehst.
Also: LED an den PWM Ausgang. Timer einstellen und einfach verschiedene
Werte für OCR1A ausprobieren.
Dann merkst du nämlich sehr schnell, was das Problem ist.
Und dann kannst du auch ermessen, warum da eigentlich so ein Aufwand
getrieben wird und verstehst dann auch was da eigentlich passiert.
Ausserdem ist es eine Übung im Datenblattlesen und im Umgang mit Timern.
Und das kann ja erst mal nicht schlecht sein, wenn man zunächst bei den
Grundlagen anfängt anstatt sich gleich auf die Lösung zu stürzen, die
man erstens nicht versteht und die zweitens Probleme zu lösen versuchst,
von deren Existenz du noch gar nichts weißt.
Hallo,
vielen Dank für die Antworten.
Ich werde die Sachen mal durchackern, habe vor ein paar Tagen mit
Versuchen zur Programmierung angefangen.
LEDs an und ausschalten gehen schonmal. Das wäre jetzt so der nächste
Schritt mit dem ich mich gerne beschäftigen möchte.
Hallo nochmal,
ich habe mich nochmal mit der PWm beschäftigt und es auch ans laufen
bekommen. Ich habe nur noch eine prinzipielle Frage und zwar:
Werden mit der Zuweisung eines Wertes an OCR1A die Pulsweiten
eingestellt? So wie ich verstanden habe, wird damit ja der Compare Wert
eingestellt, ab dem der Timer von vorne anfängt zu zählen. Bei einem
niedrigen Wert von OCR1A hätte ich dann viele schmale Pulse, bei einem
höheren Wert von OCR1A dann die breitesten?
Zudem habe ich noch eine Codefrage:
Was wird mit den folgenden Anweisungen erreich?:
TCCR1B = 0x08; // Prescaler einstellen
TCCR1B &= ~0x7; // clear clk setting
TCCR1B |= 4; // precaler 256 -> ~122 Hz PWM frequency
Was bedeuten die Operatoren &= und |=, die habe ich bis jetzt noch nicht
gesehen?
Bei der Anweisung TCCR1B |= 4; könnte ich mir vorstellen, dass nur das
letzte Byte des 8 Bit Registers gesetzt wird?
Christian S. schrieb:
> Werden mit der Zuweisung eines Wertes an OCR1A die Pulsweiten
> eingestellt? So wie ich verstanden habe, wird damit ja der Compare Wert
> eingestellt, ab dem der Timer von vorne anfängt zu zählen.
Nicht notwendigerweise.
Das hängt vom Modus ab, in dem der Timer läuft.
Im Datenblatt des Prozessors gibt es da eine wunderschöne Tabelle aus
der man entnehmen kann welches Register (wenn überhaupt) für die Zahl
zuständig ist, bis zu der der Timer zählt.
> Bei einem
> niedrigen Wert von OCR1A hätte ich dann viele schmale Pulse, bei einem
> höheren Wert von OCR1A dann die breitesten?
No.
So funktioniert PWM nicht.
Für PWM ist einzig und alleine das Verhältnis von Puls-High zu Puls-Low
ausschlaggebend.
> Was bedeuten die Operatoren &= und |=, die habe ich bis jetzt noch nicht
> gesehen?
Dann wirds Zeit, dass du noch einmal zu den Grundlagen zurückgehst.
Diese beiden Operationen müssen dir in Fleisch und Blut übergehen! Da
frag ich mich, wie du gezielt einen Port so manipulierst, dass du nur
ein einzelnes Bit, nur ein einziges, manipulierst und alle anderen in
Ruhe lässt.
@Christian S. (kruemel)
>Werden mit der Zuweisung eines Wertes an OCR1A die Pulsweiten
>eingestellt?
Ist das SOOOO schwer aus dem Quelltext abzulesen?
> So wie ich verstanden habe, wird damit ja der Compare Wert
>eingestellt, ab dem der Timer von vorne anfängt zu zählen.
In dem im Tutorial verwendeten Modus nicht. Der Wert in OCR1A bestimmt,
wann das Ausgangspin auf LOW geschaltet wird.
>Was bedeuten die Operatoren &= und |=, die habe ich bis jetzt noch nicht
>gesehen?
Siehe Bitmanipulation.
MFG
Falk
Ja okay, ich habe den Timer auf eine 8 Bit Fast PWM eingestellt, das
heisst der Timer zählt hier bis 255 und fängt dann wieder bei 0 an.
Okay und nochmal zu breiten und schmalen Pulsen:
Ich meinte mit schmalen und breiten Pulsen die high-Pulse, das sollte
heißen, bei schmalen high-pulsen, habe ich breite low pulse und
umgekehrt. Sodass ich im Verhältnis mehr low als high Zustand habe.
Bei einer sehr gedimmten LED sind doch dann schmale high pulse, jedoch
breite lowpulse vorhanden? Und die Pulslänge, also wie lange die LED
leuchtet bevor sie wieder ausgeht wird ,je nach Art ob inverting oder
non inverting dann über OCR1A bestimmt?
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
|