Hallo allerseits,
Ich habe ein Problem und hoffe, ihr könnt mir helfen.
Und zwar folgendes:
Ich habe einen Mikrocontroller (ATmega328p-pu (der gleiche wie im
Arduino Uno)), und habe vor in naher Zukunft einen Motor mittels 8-Bit
Timer0 anzusteuern. Für Motoren gestaltet sich Phasenrichtige PWM als
nützlich, also hab ich´s damit versucht. Hier einmal mein C-Code
1 | //ATmega328p-pu
|
2 | #include <avr/io.h>
|
3 | #include <avr/interrupt.h>
|
4 |
|
5 | void phasecorrect_pwm();
|
6 |
|
7 | int main(void)
|
8 | {
|
9 | DDRD |= (1<<PIND6);
|
10 | phasecorrect_pwm();
|
11 |
|
12 | while(1);
|
13 | }
|
14 |
|
15 | // Interrupt subroutine timer 0 overflow
|
16 | ISR(TIMER0_OVF_vect)
|
17 | {
|
18 | PORTD ^= (1<<PIND5);
|
19 | // Toggle PD5
|
20 | }
|
21 |
|
22 | void phasecorrect_pwm()
|
23 | {
|
24 |
|
25 | OCR0A = 63;
|
26 | // Set Dutycycle to 75 %
|
27 |
|
28 | TCCR0A |= (1<<WGM00)|(1<<COM0A1)|(1<<COM0A0);
|
29 | // Start timer0 (PWM->Phasenkorrekt) mit TOP von 0xFF
|
30 | // in non inverting phase correct PWM mode
|
31 |
|
32 | TCCR0B |= (1<<CS00);
|
33 | //CPU CLock & Prescaller von 0
|
34 |
|
35 | TIMSK0 |= (1<<OCIE0B)/*|(1<<TOIE0)*/ ;
|
36 | // Enable Timer Compare match und overflow-Interrupt
|
37 |
|
38 | sei();
|
39 | // Set the I-bit in SREG -> start interrupts
|
40 |
|
41 | }
|
Was mich wundert ist, dass das ganze überhaupt funktioniert. Die
Interrupt-Subroutine hat ja den Vektor "TIMER0_OVF_vect", d.h. es ist
ein overflow-vector, d.h. die Subroutine wird jedesmal aufgerufen, wenn
ein Timeroverflow stattfindet, was laut Datenblatt immer dann geschieht,
wenn BOTTOM, also der Zählerstatus von 0 erreicht wird.
D.h. Der Timer Zählt: 0(BOTTOM) rauf-> 255(TOP) runter-> 0(BOTTOM)
Aber weil ich meinen Mikrocontroller mit dem Oszilloskop am PIND6
ausgemessen habe, bin ich draufgekommen, dass die Interrupt-Subroutine
wohl nicht nur im Falle des erreichens von BOTTOM aufgerufen wird(was
einen Duty-Cycle von 50% zur Folge hätte), sondern dass ich den
Duty-Cycle sehrwohl durch beschreiben (wie im obigen Codesnippet) des
OCR0A - Registers steuern kann.
Also warum wird die Interrupt-Subroutine doch immer durchlaufen, wenn
der Counter bei 63 angekommen ist, und nicht wenn ein einfacher Overflow
(BOTTOM) stattfindet ??
Anm.: im Datenblatt steht folgendes:
"The Timer/Counter Overflow Flag (TOV0) is set each time the counter
reaches BOTTOM. The
Interrupt Flag can be used to generate an interrupt each time the
counter reaches the BOTTOM
value."
Ich hoffe, ihr könnt mir helfen,
Danke schon mal im Voraus,
LG Felix