Witam wszystkich!
Aktualnie bawię się trybami PWM atmegi32.
Na timerze0 robię phase correct pwm, zaś na timerze2 zegar systemowy.
PWM jest software'owy i ustawianie poziomu logicznego znajduje się w przerwaniu od OCR0.
Czas systemowy to po prostu inkrementowana zmienna globalna w przerwaniu od OCR2, gdzie licznik pracuje w trybie CTC.
Mój problem polega na tym, że nie bardzo potrafię rozszyfrowac dla czego gdy pominę inicjalizację system_clock_init() PWM działa OK, zaś gdy zainicjalizuję licznik od czasu systemowego, częstotliwość PWM maleje i poziom jasności LED'a się zmienia (rozjaśnia się).
dzięki za podpowiedzi.
kod poniżej:
Aktualnie bawię się trybami PWM atmegi32.
Na timerze0 robię phase correct pwm, zaś na timerze2 zegar systemowy.
PWM jest software'owy i ustawianie poziomu logicznego znajduje się w przerwaniu od OCR0.
Czas systemowy to po prostu inkrementowana zmienna globalna w przerwaniu od OCR2, gdzie licznik pracuje w trybie CTC.
Mój problem polega na tym, że nie bardzo potrafię rozszyfrowac dla czego gdy pominę inicjalizację system_clock_init() PWM działa OK, zaś gdy zainicjalizuję licznik od czasu systemowego, częstotliwość PWM maleje i poziom jasności LED'a się zmienia (rozjaśnia się).
dzięki za podpowiedzi.
kod poniżej:
#define F_CPU 10000000UL
#define LED PC2 //pin where LED is connected
#include <avr/io.h>
#include <avr/interrupt.h>
volatile uint8_t system_clock; //global system clock
void phase_correct_pwm_init(void)
{
TCNT0 = 1; //workaround after errata (so TCNT is not 0xFF or 0x00 causing interrupt losing problem)
TCCR0 |= ((1<<CS00) || (1<<CS01)); //clock=F_CLK/64 (tick=6.4us)
TCCR0 |= (1<<WGM00); //timer0 phase correct PWM mode
SFIOR |= (1<<PSR10); //prescaler reset
TIMSK |= (1<<OCIE0); //timer0 compare match int. enable
OCR0 = 4; //initial PWM
}
ISR(TIMER0_COMP_vect)
{
static uint8_t ocr_counter;
if(ocr_counter) {
PORTC &= ~(1<<LED); //reset LED on 2nd OCR
ocr_counter = 0; //reset counter
} else {
PORTC |= (1<<LED); //set LED on 1st OCR
ocr_counter++; //set counter
}
}
void system_clock_init(void)
{
TCNT2 = 1; //workaround after errata (so TCNT is not 0xFF or 0x00 causing interrupt losing problem)
TCCR2 |= (1<<CS21); //prescaler = 8 (tick=0.8us)
TCCR2 |= (1<<WGM21); //timer2 CTC mode
SFIOR |= (1<<PSR2); //prescaler reset
TIMSK |= (1<<OCIE2); //timer2 OCR interrupt enable
OCR2 = 249; //OCR interrupt every 0.8us*250=200us
}
ISR(TIMER2_COMP_vect, ISR_NOBLOCK) //interrupt every 200us
{
system_clock++;
}
int main(void)
{
DDRC |= (1<<LED); //led pin output direction
system_clock_init();
phase_correct_pwm_init();
sei();
while(1)
{
}
}