У меня модуль тахометра выглядит так:
//----------------------------------------------------------------------------
//Tacho - модуль тахометра
//----------------------------------------------------------------------------
#include "Main.h"
#include "Meter.h"
#include "Display.h"
//---------------- Используемые модулем аппаратные ресурсы: ------------------
//Измеритель использует прерывание по захвату таймера 1 (вывод ICP)
//и прерывание по переполнению таймера 1. Исходное состояние
//измерителя - FM_IDLE.
//Из этого состояния он переводится в FM_START, в программный таймер FmTimer
//загружается интервал измерения.
//Когда приходит входной импульс, происходит захват таймера в переменную Tb,
//обнуляется количество входных импульсов Np и начинается процесс
//измерение частоты FM_COUNT.
//При этом с приходом каждого входного импульса увеличивается значение Np.
//События переполнения таймера 1 считаются в переменной Tn.
//Когда измерительный интервал истекает, производится перевод процесса
//в состояние FM_STOP.
//По следующему входному импульсу происходит захват таймера в переменную Te,
//и процесс измерения частоты заканчивается (FM_DONE).
//После этого основная программа вычисляет длительность серии импульсов
//как Tcap = Te - Tb + Tn * (TIMER_MAX + 1)
//и частоту вращения Freq = (Np * F_CLK * 60) / (Tcap * BLADES).
//Если в состоянии FM_START или FM_STOP переполняется таймер FmTimer,
//это означает, что входных импульсов нет или их частота слишком низкая.
//При этом принимается Freq = 0.
//----------------------------- Константы: -----------------------------------
#define BLADES 30 //количество лопастей прерывателя
#define FM_MAX 500 //максимальный период измерения, мс
#define TIMER_MAX 0xFFFF
#define MAX_CNT (TIMER_MAX / 2)
enum { FM_IDLE, FM_START, FM_COUNT, FM_STOP, FM_DONE };
//----------------------------- Переменные: ----------------------------------
volatile char State; //состояние измерителя частоты
static int FmTimer; //таймер измерителя частоты
static int Tn; //количество переполнений таймера
static unsigned int Tb, Te; //захваченные значения начала и конца интервала
static int Np; //количество входных импульсов
static int Freq; //частота вращения
//-------------------------- Прототипы функций: ------------------------------
#pragma vector = TIMER1_CAPT_vect
__interrupt void Timer_Cap(void); //прерывание по захвату
#pragma vector = TIMER1_OVF_vect
__interrupt void Timer_Ovf(void); //прерывание по переполнению
//------------------ Инициализация подсистемы измерителя: --------------------
void Meter_Init(void)
{
//CK/1:
TCCR1B = (1 << CS10);
//разрешение прерываний:
TIFR = (1 << ICF1) | (1 << TOV1);
TIMSK |= (1 << TICIE1) | (1 << TOIE1);
//инициализация переменных:
State = FM_IDLE;
}
//------------------------- Процесс измерения: -------------------------------
void Meter_Exe(bool t)
{
if(t) //проверка начала нового системного тика (0.5 мс)
{
if(State == FM_IDLE) //если измеритель остановлен,
{
FmTimer = ms2sys(FM_MAX); //загрузка интервала (в системных тиках)
State = FM_START; //запуск измерителя
}
if(FmTimer) FmTimer--; //обработка таймера
else //если таймер переполнился
{
switch(State)
{
case FM_START:
{
Freq = 0; //нет входных импульсов
State = FM_DONE;
break;
}
case FM_COUNT:
{
FmTimer = ms2sys(FM_MAX); //загрузка интервала
State = FM_STOP; //требование завершения счета
break;
}
case FM_STOP:
{
Freq = 0; //нет входных импульсов
State = FM_DONE;
break;
}
}
}
if(State == FM_DONE) //если счет завершен,
{
long Tcap = (long)Te - (long)Tb + (long)Tn * (TIMER_MAX + 1L);
Freq = (Np * (long long)(F_CLK * 1E6 * 120)) / (Tcap * BLADES);
Freq = (Freq + 1) / 2; //округление
Display_Val(Freq); //индикация частоты вращения
State = FM_IDLE;
}
}
}
//------------------------- Прерывание по захвату: ---------------------------
#pragma vector = TIMER1_CAPT_vect
__interrupt void Timer_Cap(void)
{
switch(State)
{
case FM_START: //фаза запуска измерения частоты
{
Tb = ICR1; //захват таймера в начале интервала
Tn = 0; //инициализация количества переполнений
if(Tb < MAX_CNT && (TIFR & (1 << TOV1)))
Tn--; //коррекция, если переполнение было до захвата
Np = 0; //инициализация количества импульсов
State = FM_COUNT; //переход к фазе измерения частоты
break;
}
case FM_COUNT: //фаза измерения частоты
{
Np++;
break;
}
case FM_STOP: //фаза завершения измерения частоты
{
Te = ICR1; //захват таймера в конце интервала
if(Te < MAX_CNT && (TIFR & (1 << TOV1)))
Tn++; //коррекция, если переполнение было до захвата
Np++;
State = FM_DONE; //измерение частоты закончено
break;
}
}
}
//----------------------- Прерывание по переполнению: ------------------------
#pragma vector = TIMER1_OVF_vect
__interrupt void Timer_Ovf(void)
{
if((State == FM_COUNT) || (State == FM_STOP)) Tn++; //подсчет переполнений
}
//----------------------------------------------------------------------------
-
- А я-то подумала, что там картинка :) - Ксения(22.07.2013 20:44)
- Картинка выглядит так: Лeoнид Ивaнoвич(22.07.2013 20:51)
- А я-то подумала, что там картинка :) - Ксения(22.07.2013 20:44)