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
staticvolatileintanalog,frequenz,strom=0;
9
intpwm=0;
10
11
intmain(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(inti=0;i<2;i++){
27
_delay_ms(1000);
28
}
29
//PWM starten...
30
uint8_tzaehler=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(inti=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
return0;
46
}
47
48
ISR(ADC_vect){
49
//Auslesen des AD-Wandlers mit 10 bit
50
uint8_tlowByte=ADCL;
51
analog=ADCH<<8|lowByte;
52
//Umaschalten zwischen 2 Kanälen
53
switch(ADMUX){
54
case0x40:
55
ADMUX=0x41;
56
strom=analog;
57
break;
58
59
case0x41:
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!