Hallo zusammen,
ich hänge momentan an einem Problem bei der PWM Erzeugung auf einem
AT90CAN128 fest. Programmiert wird in C unter dem Atmel Studio 6.1, per
ISP oder JTAG. Die Fuses sind alle passend beim AT90 gesetzt (läuft mit
externen 16MHz), es läuft soweit (UART, andere Timer/Counter usw.)
alles. Erzeugen will ich mit dem Timer/Counter 1 eine PWM mit ca. 40KHz
und über die Pulsbreite ein Sinussignal. Dafür hab ich das ICR-1 als
max. Timer/Counter Value benutzt. Jeder Overflow wird also bei 40KHz
ausgelöst und in diesem Interrupt der jeweils nächste Wert für das OCR1A
Register aus einem Array geladen und PA1 auf High gesetzt. Im Compare
Match Interrupt wird der Pin dann auf low gesetzt.
Die Register sind folgendermaßen Initialisiert:
1
DDRA=0xff;
2
TCCR1A=0b00000010;
3
TCCR1B=0b00011001;//Fast PWM Mode und Prescaler 1
4
TCCR1C=0b00000000;
5
ICR1=405;//Im Fast PWM Mode, führt dies zu Interrupts mit ~40KHz
6
TIMSK1=0b00000011;
Die Interrupt Vektoren wie folgt:
1
ISR(TIMER1_OVF_vect)
2
{
3
PORTA=PORTA|0b00000001;
4
5
temp_divider++;//"Verlangsamung" der PWM
6
if(temp_divider>=200)
7
{
8
PWM_step=PWM_step+1;
9
10
sei();
11
if(PWM_step>1020)
12
{
13
PWM_step=0;
14
}
15
16
elseif(PWM_step<=255)
17
{
18
//OCR1A = PWM_1[PWM_step];
19
OCR1AH=(uint8_t)(PWM_1[PWM_step]>>8);
20
OCR1AL=(uint8_t)PWM_1[PWM_step];
21
}
22
23
elseif((PWM_step>255)&&(PWM_step<510))
24
{
25
//OCR1A = PWM_2[PWM_step-255];
26
OCR1AH=(uint8_t)(PWM_2[PWM_step-255]>>8);
27
OCR1AL=(uint8_t)PWM_2[PWM_step-255];
28
}
29
30
elseif((PWM_step>510)&&(PWM_step<765))
31
{
32
//OCR1A = PWM_3[PWM_step-510];
33
OCR1AH=(uint8_t)(PWM_3[PWM_step-510]>>8);
34
OCR1AL=(uint8_t)PWM_3[PWM_step-510];
35
}
36
37
elseif((PWM_step>765)&&(PWM_step<1020))
38
{
39
//OCR1A = PWM_4[PWM_step-765];
40
OCR1AH=(uint8_t)(PWM_4[PWM_step-765]>>8);
41
OCR1AL=(uint8_t)PWM_4[PWM_step-765];
42
}
43
cli();
44
temp_divider=0;
45
}
46
47
}
48
49
50
ISR(TIMER1_COMPA_vect)
51
{
52
PORTA=PORTA&0b11111110;
53
}
In den Arrays PWM_1 bis PWM_4 sind Werte von 1 bis 399 für die Breite
der PWM hinterlegt. Das Problem, welches ich habe ist, dass die PWM
Breite nicht unter einen Wert im OCR1A von ca. 50 geht und auch nicht
über ca. 360. Sprich ich seh auf dem Oszi zu lange bzw. zu kurze
Pulsbreiten. Ich habe auch schon versucht die OCR1A Werte fix zu setzen,
kein Unterschied. Unter einem Wert von 50 bleibt der Port einfach
trotzdem bis ca. 50 auf einem High Pegel.
Ist das dem AT90 einfach zu schnell, was ich mir eigentlich nicht
vorstellen kann? Oder liegt mein Fehler wo anders?
Grüße,
Philipp
Philipp L. schrieb:> Breite nicht unter einen Wert im OCR1A von ca. 50 geht
D.h. vom einschalten des Pins hier
1
ISR(TIMER1_OVF_vect)
2
{
3
PORTA=PORTA|0b00000001;
4
5
...
bis zum ausschalten des Pins hier
1
ISR(TIMER1_COMPA_vect)
2
{
3
PORTA=PORTA&0b11111110;
vergehen etwa 50 Takte.
da ist einmal der Epilog vom verlassen der Overlfow ISR und einmal der
Prolog beim betreten der Compare-ISR. (Und natürlich fallweise das
bischen rechnen in der Overflow-ISR).
50 kommt mir jetzt dafür ehrlich gesagt ein wenig hoch vor. Hast du den
Optimizer eingeschaltet?
Aber selbst dann wirst du kaum unter sagen wir mal 20 oder 25 kommen.
Warum versuchst du selber die PWM zu erzeugen und lässt das nicht die
Hardware machen? Die kommt problemlos auf Taktzyklenauflösung
(allerdings auch nicht auf exakt 0). Dazu hast du ja die PWM Hardware,
damit die dir diesen Teil abnimmt. Einzige Einschränkung: du bist an
bestimmte Pins gebunden. Das muss man eben beim Hardware Design
berücksichtigen und ist nicht so schlimm, wie es sich am Anfang anhört.
Karl Heinz schrieb:> 50 kommt mir jetzt dafür ehrlich gesagt ein wenig hoch vor. Hast du den> Optimizer eingeschaltet?
Habe es schon sowohl mit, als auch ohne probiert. Musste Leider auch
feststellen, dass entweder mein JTAGICE3 entweder nicht so wunderbar zum
debuggen geeignet ist oder ich irgendwas komplett falsch mache. Einige
Varbiablen sind beim durchsteppen nicht "auslesbar" bzw. "uexpexted
typedef" oder "optimized away".
Die Hardware ist leider, wie so oft, schon vorgegeben und, daher wird es
schwierig die OCPs zu verwenden und irgendwo muss ich ja so oder so
rechtzeitig den neuen Wert ins OCR laden.
Karl Heinz schrieb:> PS: if(PWM_step > 1020)> {> PWM_step=0;> }>> else if(PWM_step <= 255)>> den Wert PWM_1[0] gibst du nie aus. Aber das ist jetzt nicht das> Problem.
Ja, ich weiß bzw. ist zwischen allen Array wechseln jeweils ein Schritt
der nicht ausgeführt wird. Denke aber auch, dass das nicht das Problem
ist.
Mal von den Problemen die Du gerade hast abgesehen, ich würde sagen, das
ist einfach ein klein wenig zu hart für den 90CAN128.
Alle 405 Taktzyklen ein Interrupt - selbst wenn das funktioniert, der
wird kaum noch irgendetwas anderes machen können.
Gibt es für sowas nicht spezielle Chips?
>ISR(TIMER1_COMPA_vect)>{> PORTA = PORTA & 0b11111110;>}
Macht das irgendwas anderes als Taktzyklen zu fressen?
Philipp L. schrieb:> Die Hardware ist leider, wie so oft, schon vorgegeben und, daher wird es> schwierig die OCPs zu verwenden und irgendwo muss ich ja so oder so> rechtzeitig den neuen Wert ins OCR laden.
Es hat nichts mit dem Laden der OCR Register zu tun.
Auch ein 90CAN128 braucht seine Zeit um aus der einen ISR auszusteigen
und in die andere ISR einzusteigen. Das sind deine ca. 50 Takte.
> Die Hardware ist leider, wie so oft, schon vorgegeben
Dann lass sie ändern oder such dir einen PWM Pin, der noch frei ist.
Aber das ist Unsinn eine PWM selbst zu erzeugen, wenn du einen
Mords-Prozessor hast, der das locker in Hardware machen kann. Und zwar
ohne Probleme.
Rudolph schrieb:> Macht das irgendwas anderes als Taktzyklen zu fressen?
Oh, autsch, ich ziehe die Frage zurück, das ist quasi eine Soft-PWM auf
PA0 was so noch weniger Aussicht auf Erfolg haben wird wenn man
überlegt, dass dann ja offensichtlich noch mehr im Controller passieren
soll.
Philipp L. schrieb:> Gut, dann werde ich wohl die "Baustelle eröffnen"
Na ja.
2 Pins zu tauschen, sollte jetzt aber nicht das große Problem sein. Da
hat derjenige, der das gezeichnet hat nicht aufgepasst.
Auf deinem Entwicklungsbaurd ist die Sache mit einem scharfen Messer und
ein wenig Fädeldraht schnell soweit behoben, dass du nicht auf eine neue
Platinenversion warten musst.
Naa, ein großes Problem ist es nicht, erst recht nicht, da ich es
einfach selbst routen werde, aber die 15 Platinen "umzurüsten" wird ein
bisschen dauern. Auf den ersten Blick sieht das Oszibild auf jedenfall
schon mal wesentlich besser aus! ;)
Eine eigene Frage?
Dieser Thread ist über 12 Jahre alt.
Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.