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