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 с учётом его переполнения. Погрешность появилась из-за того что были потеряны насчитанные импульсы пока был вывод на экран.