Atmel AVR Mikrocontroller
Pulsweitenmodulation im Phase Correct PWM Mode
Register TCCRA AT90PWM316
Der Phase Correct PWM Mode wird z.B. beim AT90PWM316 im Register TCCRA und TCCRB mit den Bits WGM00, WGM01 und WGM02 eingestellt.
Wird das WGM00 Bit gesetzt, ist der TOP-Wert des Timer Zählregisters 0xFF also 255.
Wird das WGM02 Bit gesetzt (dieses befindet sich im Register TCCRB), ist der TOP-Wert jener Wert, der im Register OCRA als compare match eingestellt wurde.
Dieser Modus passiert auf dem dual-slope Prinzip. Der Zähler zählt von 0 bis TOP hinauf und anschließend von TOP auf 0 hinunter. TOP ist im Mode 1 als 0xFF definiert und im Mode 5 ist der TOP-Wert jener Wert im OCRA.
Hier ein Programmbeispiel zur Erzeugung eines PWM-Signals im Phase Correct Mode 1. Der TOP-Wert ist 255 (T = 255us) und der compare match wird auf 50 (T = 50us) gesetzt.
// PWM mit Timer in Phase correct mode
// Controller: ATMEL AT90PWM316
#include <avr/io.h>
#include <avr/interrupt.h>
#define F_CPU 8000000 // T system clock = 1 / 8MHz = 0,125us
int main(void)
{
DDRD |= (1<<PD3); // PD3 (OC0A) = Ausgang
TCCR0A |= (1<<COM0A1); // Clear OC0A on compare match
TCCR0A |= (1<<WGM00); // Mode 1 = PWM Phase correct, Top = 0xFF
TCCR0B |= (1<<CS01); // Prescaler = 8, T system clock = 1 / 1MHz = 1us
OCR0A = 50; // Compare match auf 50 (50us High Signal)
while(1)
{
asm ("NOP");
}
return 0;
}
Programmbeispiel automatisches Dimmen einer LED. Hier wird der compare match bei jedem Durchlauf um 1 erhöht.
// PWM mit Timer in Phase correct mode
// Controller: ATMEL AT90PWM316
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#define F_CPU 8000000 // T system clock = 1 / 8MHz = 0,125us
int main(void)
{
DDRD |= (1<<PD3); // PD3 (OC0A) = Ausgang
TCCR0A |= (1<<COM0A1); // Clear OC0A on compare match
TCCR0A |= (1<<WGM00); // Mode 1 = PWM Phase correct, Top = 0xFF
TCCR0B |= (1<<CS01); // Prescaler = 8, T system clock = 1 / 1MHz = 1us
OCR0A = 0; // Compare match auf 0
while(1)
{
OCR0A ++; // Compare match bei jedem Durchlauf um 1 erhöhen
_delay_ms(100);
}
return 0;
}