Eksperymentuję właśnie z generowaniem przebiegu sinusoidalnego za pomocą Atmegi8. Oparłem się na drugim przykładzie z tej strony:
Wzór przebiegu znajduje się w tabeli, wypełnionej w następujący sposób:
for (i=0; i<256; i++) sinus_buffer[i]=128+126*sin(6.26/256*1);
PWM generowany jest za pomocą TIMER1 ustawionego na Fast PWM (tryb 14). Funkcja włączająca generowanie przebiegu wygląda następująco:
void StartDialtone (void) { TCCR1A |= _BV(COM1A1) | _BV(WGM11); TCCR1B |= _BV(WGM13) | _BV(WGM12) | _BV(CS10); ICR1 = 255; OCR1A = 0; sinus_ind = 0; TCNT0 = 182; TCCR0 |= _BV(CS00); TIMSK |= _BV(TOIE0); }
Z kolei wyłączająca wygląda następująco:
void StopDialtone (void) { TCCR0 &= ~_BV(CS00); TIMSK &= ~_BV(TOIE0); TCCR1A &= ~(_BV(COM1A1) | _BV(WGM11)); TCCR1B &= ~(_BV(WGM13) | _BV(WGM12) | _BV(CS10)); ICR1 = 0; PORTB &= ~_BV(1); }
Zmiana współczynnika wypełnienia odbywa się w przerwaniu, po przepełnieniu TIMER0:
ISR (TIMER0_OVF_vect) { OCR1A = sinus_buffer[sinus_ind]; if (sinus_ind < 255) sinus_ind++; else sinus_ind=0; TCNT0 = 182; }
Za wyjściem PB1/OC1A znajduje się filtr dolnoprzepustowy RC złożony z rezystora 330 omów oraz kondensatora 1uF do masy. Za filtrem nie mam jednak sinusoidy, a coś przypominające trójkąt: