А теперь сделаем обратную операцию — будем измерять частоту внешнего сигнала. Стандартный pulseIn() не может измерить частоту выше нескольких килогерц.
Хак: Используем Timer1 в режиме подсчета импульсов (Counter Mode). В этом режиме Timer1 считает каждый импульс на входе T1 (пин 5), а Timer2 используется как тактовый генератор для сброса счетчика раз в секунду.
Схема подключения:
- Входной сигнал подаем на пин 5 (T1 — вход таймера 1).
- Сигнал должен быть TTL-уровня (0-5В).
Код частотомера:
volatile uint32_t frequency = 0;
void setupFrequencyCounter() {
// Настраиваем пин 5 (PD5) как вход
DDRD &= ~(1 << PD5);
PORTD &= ~(1 << PD5); // Отключаем подтяжку
// Настройка Timer1 как счетчик импульсов
TCCR1A = 0;
TCCR1B = 0;
TCNT1 = 0; // Сбрасываем счетчик
TCCR1B |= (1 << CS10) | (1 << CS11) | (1 << CS12); // Внешний тактовый сигнал (пин T1)
// БИТЫ: CS12=1, CS11=1, CS10=1 -> счет по внешнему сигналу
// Настройка Timer2 для прерывания раз в секунду
TCCR2A = 0;
TCCR2B = 0;
TCNT2 = 0;
OCR2A = 249; // (16 МГц / 64 / 250) = 1000 Гц
TCCR2A |= (1 << WGM21); // Режим CTC
TCCR2B |= (1 << CS22); // Прескалер 64
TIMSK2 |= (1 << OCIE2A); // Включаем прерывание по совпадению
sei();
}
// Обработчик прерывания раз в секунду
ISR(TIMER2_COMPA_vect) {
// Читаем счетчик и сбрасываем
frequency = TCNT1;
TCNT1 = 0;
}
void loop() {
// Выводим частоту раз в 100 мс
static uint32_t lastPrint = 0;
if (millis() - lastPrint > 100) {
Serial.print("Частота: ");
Serial.print(frequency);
Serial.println(" Гц");
lastPrint = millis();
}
}
Результат: Вы получаете точный частотомер, который работает до 6 МГц (максимальная частота для Timer1). Отличный инструмент для отладки генераторов, энкодеров и датчиков Холла!