Problem bei PWM mit TC1 auf AT90CAN128

OP #3428131
Lesenswert?

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
    else if(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
    else if((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
    else if ((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
    else if ((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
#3428149
Lesenswert?

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.
OP #3428158
Lesenswert?

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.
Gast #3428166
Lesenswert?

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?
#3428168
Lesenswert?

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.
Gast #3428170
Lesenswert?

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.
#3428180
Lesenswert?

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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren