atmega8 измерение частоты
- Войдите на сайт для отправки комментариев
Пт, 05/08/2016 - 17:57
Добрый день!
16-разрядный таймер Т1 вызывает прерывание раз в секунду (частота 12МГц внешний кварц, предделитель 256, 46875 тиков - 1 сек). 8-разрядный тактируется от внешнего сигнала (вход Т0), считает количество переполнений. В прерывании таймера 1 я считаю сколько пришло импульсов по формуле: Fin = TIM0_OVF_cnt * 256 + TCNT0. Значение выводится на lcd. В протеусе при входном сигнале 100 Гц показывает точно 100, при 500 Гц уже 499, при 1000 Гц показывает 9980. Так и должно быть, или это ошибка в коде/формуле/протеусе?
#define F_CPU 12000000UL #include <avr/io.h> #include <avr/interrupt.h> #include "lcd-lib.h" volatile unsigned int ovfCnt = 0; char freqBuff[20]; void timersInit() { // Timer 1 TIMSK = (1<<OCIE1A) | (1<<TOIE0); TCCR1B = (1<<WGM12) | (1<<CS12); // CTC mode, prescaler 256 TCNT1 = 0; OCR1A = 46875; // Timer 0 TCCR0 = (1<<CS02) | (1<<CS01) | (1<<CS00); // External clock source on T0, clock on rising edge } void gpioInit() { } void indication() { unsigned int freq = (ovfCnt * 256) + TCNT0; lcd_home(); sprintf(freqBuff, "%d", freq); lcd_string(freqBuff); } ISR (TIMER1_COMPA_vect) { indication(); ovfCnt = 0; TCNT0 = 0; } ISR (TIMER0_OVF_vect) { ovfCnt++; } int main(void) { gpioInit(); timersInit(); lcd_init(); sei(); while(1) { } }
Некропост конечно, но вдруг кому интересно. Нельзя обнулять TCNT0. Нужно продолжать считать, а при следующем вычислении частоты вычесть начальное значение TCNT0 с учётом его переполнения. Погрешность появилась из-за того что были потеряны насчитанные импульсы пока был вывод на экран.