Цель моего приложения - использовать ATMEGA328P в качестве ядра синусоидального генератора Digital Direct Synthesis 400 Hertz. Импульсы от микропроцессора отправляются на затворы четырех высоковольтных N-MOSFET, соединенных в виде полного H-моста. 16-bitTimer1 использует режим WGM 10 и управляет MOSFET на северо-востоке и северо-западе. 8-bitTimer0 и 8-bitTimer2 используют режим 5 и управляют MOSFET для юго-востока и юго-запада соответственно. Мне удалось генерировать импульсы с правильной шириной, но я не смог правильно их синхронизировать. Между импульсами Timer1 и соответствующими импульсами Timer0 и Timer2 наблюдается одно или два проскальзывания часов.
У меня не было успеха, когда я пытался компенсировать эту задержку, устанавливая начальные значения Timer0 и Timer2.
#define CPU_FREQ 16000000UL
#define OUT_FREQ 400UL
#define SAMPLE_FREQ 40000UL
#define SAMPLE_COUNT SAMPLE_FREQ/OUT_FREQ/2
#define SAMPLE_MAX CPU_FREQ/SAMPLE_FREQ/2 - 1
#define TIMER0_MAX 255
#define TIMER2_MAX 255
#define TIMER0_DELAY 1
#define TIMER2_DELAY 1
void setupTimers() {
cli(); // disable global interrupts;
GTCCR = bit(TSM) | bit(PSRASY) | bit( PSRSYNC);
setupTimer0();
setupTimer1();
setupTimer2();
sei(); // enable global interrupts;
GTCCR = 0;
}
void setupTimer0() {
// Waveform Generation Mode 5, PWM, Phase Correct
// TOP = OCR0A, OCR1B updated at TOP, TOV1 Flag set on BOTTOM
// Set OC0B on Compare Match when up-counting.
// Clear OC0B on Compare Match when down-counting
// Clock Source Mode 1, No prescaling
// OCIE0B, OCIE0A, TOIE0 interrupts disaabled
// No Force Output Compare A or B
// TCNT0 initial count compensation for OCR0A as TOP delay
TCCR0A = bit(COM0B1) | bit(COM0B0) | bit(WGM00);
TCCR0B = bit(CS00) | bit(WGM02) ;
TCNT0 = TIMER0_DELAY;
OCR0A = SAMPLE_MAX;
OCR0B = nextOCR0B;
TIMSK0 = 0;
}
void setupTimer1() {
// Waveform Generation Mode 10, PWM, Phase Correct
// TOP = ICR1, OCR1A and OCR1B updated at TOP, TOV1 Flag set on TOP
// Clear OC1A on Compare Match when upcounting.
// Set OC1A on Compare Match when downcounting
// Clear OC1B on Compare Match when upcounting.
// Set OC1B on Compare Match when downcounting
// Clock Source Mode 1, No prescaling
// OCIE1B, OCIE1A, TOIE1 interrupts disaabled
// No Force Output Compare A or B
TCCR1A = bit(COM1A1) | bit(COM1B1) | bit(WGM11) ;
TCCR1B = bit(CS10) | bit(WGM13);
TCCR1C = 0;
TCNT1 = 0;
OCR1A = nextOCR1A;
OCR1B = nextOCR1B;
ICR1 = SAMPLE_MAX;
TIMSK1 = 0;
}
void setupTimer2() {
// Waveform Generation Mode 5, PWM, Phase Correct
// TOP = OCR0A, OCR1B updated at TOP, TOV1 Flag set on BOTTOM
// Set OC0B on Compare Match when up-counting.
// Clear OC0B on Compare Match when down-counting
// Clock Source Mode 1, No prescaling
// OCIE0B, OCIE0A, TOIE0 interrupts disaabled
// No Force Output Compare A or B
// TCNT2 initial count compensation for OCR2A as TOP delay
TCCR2A = bit(COM2B1) | bit(COM2B0) | bit(WGM20);
TCCR2B = bit(CS20) | bit(WGM22) ;
TCNT2 = TIMER2_DELAY;
OCR2A = SAMPLE_MAX;
OCR2B = nextOCR2B;
TIMSK2 = 0;
}
Ожидаемые результаты: синхронизированные импульсы
Фактические результаты: несинхронизированные импульсы