Hallo, ich habe ein kleines Problem: Mein Atmega8 soll ein PWM-Signal erzeugen, welches zur Laufzeit ein- und ausschaltbar sein soll. Das PWM läuft mit dem Timer1 (Toggle on Compare Match)... Gleichzeitig habe ich eine AD-Wandlung in der ISR laufen. Wenn ich die Interrupts (sei() ) nicht aktiviert habe, habe ich keine Probleme. Sobald jeadoch sei() gemacht wird, kommt beim BEENDEN des PWMs eine Art "Glitch", die Signalform sieht beim letzten Puls ungefähr so aus: __|''|__|''|__|''|__|'''''''''|____________________ Beendet wird das PWM bei mir zunächst dadurch, dass das Register ICR1 = 0 gesetzt wird. Dadurch stoppt es auch. Zusätzlich setze ich den Pin, über den das PWM ausgegeben wird als als Eingang. Das Problem tritt in beiden Fällen auf. Auch ein vorheriges cli() bringt keine Verbesserung, das Problem besteht weiterhin. Nur wenn ich die Interrupts gar nicht erst aktiviere, tritt der Fehler nicht auf. Wie wird eigentlich das PWM korrekterweise beendet, habe ich es überhaupt richtig gemacht? Ich hoffe dass es so halbwegs verständlich ist was ich sagen wollte ;) Weiss einer, was ich falsch mache?... Würde mich über jeden Ratschlag freuen, thx!
zeig mal komplett wie du deinen Timer konfigurierst! Um die PWM abzuschalten ist das einfachste den OCx-Pin vom Timer abzukoppeln, damit ist für den Pin wieder die Einstellung DDRx und PORTx wirksam. Sascha
hallo Sascha! der Timer wird bei mir so konfiguriert: TCCR1A |= 1<<WGM11 | 1<<COM1A1 | 1<<COM1A0; TCCR1B |= 1<<WGM12 | 1<<WGM13 | 1<<CS10; das mit dem abkoppeln OCx habe ich noch nicht probiert, dafür das Abschalten von CSx, hat auch funktioniert jedoch brachte das keine Besserung..
nicht Gast schrieb: > Hallo, ich habe ein kleines Problem: > > Mein Atmega8 soll ein PWM-Signal erzeugen, welches zur Laufzeit ein- und > ausschaltbar sein soll. Das PWM läuft mit dem Timer1 (Toggle on Compare > Match)... > > Gleichzeitig habe ich eine AD-Wandlung in der ISR laufen. Wenn ich die > Interrupts (sei() ) nicht aktiviert habe, habe ich keine Probleme. Sei() in der ISR? Son Quatsch! > Beendet wird das PWM bei mir zunächst dadurch, dass das Register ICR1 = > 0 gesetzt wird. Dadurch stoppt es auch. Zusätzlich setze ich den Pin, > über den das PWM ausgegeben wird als als Eingang. In welcher ISR verwendest du den ADC? Name? Zeig einfach dein Programm! Das ist immer besser als rumzustochern. Es liegt definitv am Programm!
STK500-Besitzer schrieb: > nicht Gast schrieb: >> Hallo, ich habe ein kleines Problem: >> >> Mein Atmega8 soll ein PWM-Signal erzeugen, welches zur Laufzeit ein- und >> ausschaltbar sein soll. Das PWM läuft mit dem Timer1 (Toggle on Compare >> Match)... >> >> Gleichzeitig habe ich eine AD-Wandlung in der ISR laufen. Wenn ich die >> Interrupts (sei() ) nicht aktiviert habe, habe ich keine Probleme. > > Sei() in der ISR? Son Quatsch! sorry das war ein missverständnis, das sei() steht natürlich nicht in der ISR sondern in der main() STK500-Besitzer schrieb: >> Beendet wird das PWM bei mir zunächst dadurch, dass das Register ICR1 = >> 0 gesetzt wird. Dadurch stoppt es auch. Zusätzlich setze ich den Pin, >> über den das PWM ausgegeben wird als als Eingang. > > In welcher ISR verwendest du den ADC? Name? Es war die ADC_Vect.... Leider habe ich den Stick mit dem Programm nicht bei mir :( Dass es am Programm liegt denke ich ja auch..
nicht Gast schrieb: > hallo Sascha! > > der Timer wird bei mir so konfiguriert: > > TCCR1A |= 1<<WGM11 | 1<<COM1A1 | 1<<COM1A0; > TCCR1B |= 1<<WGM12 | 1<<WGM13 | 1<<CS10; ok - Fast-PWM mit ICR als TOP-Wert > das mit dem abkoppeln OCx habe ich noch nicht probiert, dafür das > Abschalten von CSx, hat auch funktioniert jedoch brachte das keine > Besserung.. du kannst den Ausgang abschalten indem du COM1A0 und COM1A1 auf Null setzt, dann läuft die PWM intern weiter am Controllerpin tut sich nix mehr. Wenn du die CS-Bit's auf Null setzt dann bleit der Timer an der Stelle stehen und damit sollte sich auch am Ausgang nichts ändern. Eine Änderung von OC1x oder ICR könnte aber u.U. eine Änderung des Ausgangszustands hervorrufen. Ohne dein Program kommen wir hier nicht weiter. Sascha
Hallo, ich habe mich heute noch ein wenig mit dem Programm beschäftigt, hab es euch auch angehängt.. (ist natürlich noch Work in Progress, also noch alles andere als Fertig..)..
1 | #ifndef F_CPU
|
2 | #define F_CPU 4000000UL
|
3 | #endif
|
4 | #include <avr/io.h> |
5 | #include <util/delay.h> |
6 | #include <avr/interrupt.h> |
7 | |
8 | static volatile int analog, frequenz, strom = 0; |
9 | int pwm = 0; |
10 | |
11 | int main(void) { |
12 | //Ausgang fuer die PWM
|
13 | DDRB |= 1<<PINB1; |
14 | //Timer initialisiern
|
15 | TCCR1A |= 1<<WGM11 | 1<<COM1A1 | 1<<COM1A0; |
16 | TCCR1B |= 1<<WGM12 | 1<<WGM13 | 1<<CS10; |
17 | //AD-Wandler initialisieren
|
18 | ADCSRA |= 1<<ADPS2 | 1<<ADPS1; |
19 | ADMUX |= 1<<REFS0; |
20 | ADCSRA |= 1<<ADIE; |
21 | ADCSRA |= 1<<ADEN; |
22 | |
23 | sei(); |
24 | ADCSRA |= 1<<ADSC; |
25 | //2 Sekunden warten
|
26 | for(int i = 0; i < 2; i++) { |
27 | _delay_ms(1000); |
28 | }
|
29 | //PWM starten...
|
30 | uint8_t zaehler = 40; |
31 | OCR1A = zaehler/2; //Wert für den Tastgrad, für 50 % eingestellt |
32 | ICR1 = zaehler; //Wert für die Periode |
33 | //5 Sekunden Warten...
|
34 | for(int i = 0; i < 5; i++) { |
35 | _delay_ms(1000); |
36 | }
|
37 | //PWM ausschalten mit unterschiedlichen Methoden...
|
38 | cli(); |
39 | TCCR1B &= ~(1<<CS10); |
40 | ICR1 = 0; |
41 | OCR1A = 0; |
42 | DDRB &= ~(1<<PINB1); |
43 | |
44 | while(1); |
45 | return 0; |
46 | }
|
47 | |
48 | ISR(ADC_vect) { |
49 | //Auslesen des AD-Wandlers mit 10 bit
|
50 | uint8_t lowByte = ADCL; |
51 | analog = ADCH<<8 | lowByte; |
52 | //Umaschalten zwischen 2 Kanälen
|
53 | switch(ADMUX) { |
54 | case 0x40: |
55 | ADMUX = 0x41; |
56 | strom = analog; |
57 | break; |
58 | |
59 | case 0x41: |
60 | ADMUX = 0x40; |
61 | frequenz = analog; |
62 | break; |
63 | |
64 | default:
|
65 | break; |
66 | }
|
67 | ADCSRA |= 1<<ADSC; // Nächste AD-Wandlung starten |
68 | }
|
Momentan soll das PWM über das _delay() eine Zeit lang am Leben gehalten werden, später wird das dann durch einen Analogwert ersetzt. Bei dem _delay() ist mir aufgefallen, dass es nicht bei allen Werten dieses Problem gibt.. Bei einem Delay von 5 Sekunden z.B. habe ich den Fehler, bei 4 Sekunden wiederum nicht.. Könnte es eventuell nur an der _delay()-Funkton liegen? eine andere Möglichkeit der zeitlichen Veränderung kann ich momentan leider schlecht testen... thx!
nicht Gast schrieb: > //PWM ausschalten mit unterschiedlichen Methoden... > cli(); > TCCR1B &= ~(1<<CS10); > ICR1 = 0; > OCR1A = 0; damit hast du erst mal nur den Timer angehalten. Aber: Die Ausgabepins sind immer noch an den Timer gekoppelt, der sie unter seiner Fuchtel hat. Und solange du das hier TCCR1A |= ..... 1<<COM1A1 | 1<<COM1A0 ..... nicht rückgängig machst, bleibt das auch so. Erst indem du die Pins durch Abschalten der COM... Bits wieder vom Timer entkoppelt hast, kriegst du wieder die Kontrolle darüber.
Hallo, ich glaube das hat jetzt gewirkt. Wenn ich die COM pins abschalte, dann scheint das PWM bisher immer korrekt abzuschalten. Ist es dann eigentlich notwendig, den Timer noch zu stoppen bzw noch auf andere Weise sicherzustellen dass der Pin, an dem das PWM ausgegeben wird, nicht doch noch verrückt spielt?
nicht Gast schrieb: > Hallo, ich glaube das hat jetzt gewirkt. Wenn ich die COM pins > abschalte, dann scheint das PWM bisher immer korrekt abzuschalten. Ist > es dann eigentlich notwendig, den Timer noch zu stoppen bzw noch auf > andere Weise sicherzustellen dass der Pin, an dem das PWM ausgegeben > wird, nicht doch noch verrückt spielt? den Timer kannst du im Hintergrund ruhig weiterlaufen lassen, sind die COM-Bits auf 0 dann hat der Pin den durch DDRx,PORTx vorgegebenen Zustand. Auch anhalten den Timers mit CSxy=0 sollte die PWM sicher stoppen, allerdings sollte man dann die ICR, OCR Register nicht mehr ändern. Sascha
ok das klingt schonmal gut. Dann würde ich den Pin anfangs auf 0 setzen, denn meine einzige Sorge ist, dass er irgendwann auf 1 geht und dort bleibt, das wäre für meine Anwendung nicht so gut! danke schonmal!
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.