Требуется программист в Зеленограде
- обработка данных с датчиков; ColdFire; 40 тыс. e-mail:jobsmp@pochta.ru |
//----------------------------------------------------------------------------
//Модуль измерения частоты входного сигнала
//Сигнал подается на вход захвата таймера 1.
//----------------------------------------------------------------------------
#include "Main.h"
#include "Count.h"
//--------------------------- Константы: -------------------------------------
#define COMPL_TM 10 //время на завершение измерения, * T_SYS
#define PRESCALER 4 //коэффициент деления входного прескалера
enum { ST_STOP, ST_START, ST_COUNT, ST_COMPL, ST_READY };
//--------------------------- Переменные: ------------------------------------
static char State; //текущее состояние частотмера
static int Interval; //длительность интервала, * T_SYS
static bool Ready; //флаг готовности частотомера
static long Count_N; //количество входных периодов
static char Count_M; //количество переполнений опорного счетчика
static unsigned int Tb, Te; //захваченные в начале и в конце значения
static long Freq; //измеренная частота
//-------------------------- Прототипы функций: ------------------------------
#pragma vector = TIMER1_CAPT_vect
__interrupt void Capture(void); //прерывание по захвату
#pragma vector = TIMER1_OVF_vect
__interrupt void Overflow(void); //прерывание по переполнению
void Count_Clear(void); //очистка счетчиков
void Get_Freq(void); //вычисление частоты
//---------------- Инициализация модуля измерения частоты: -------------------
void Count_Init(void)
{
//разрешение таймера 1, CK/1:
TCCR1B = (1 << CS10);
//очистка отложенных прерываний:
TIFR = (1 << TOV1) | (1 << ICF1);
//разрешение прерываний по захвату и переполнению:
TIMSK |= (1 << TOIE1) | (1 << TICIE1);
Interval = 100; //начальный интервал измерения
State = ST_STOP; //счет остановлен
}
//----------------------- Процесс измерения частоты: -------------------------
void Count_Exe(bool t)
{
static int IntervTm = 0;
if(t)
{
if(IntervTm) IntervTm--;
}
Ready = 0; //сброс флага готовности
switch(State)
{
case ST_COUNT: if(!IntervTm) //если интервал закончился,
{ IntervTm = COMPL_TM; //загрузка интервала завершения счета
State = ST_COMPL; } //процесс завершения счета
break;
case ST_COMPL:
case ST_START: if(IntervTm) break; //если интервал не закончился, ждем,
State = ST_READY; //иначе прекращаем ожидание
Count_Clear(); //частота равна нулю
case ST_READY: Get_Freq(); //вычисление частоты
Ready = 1; //установка флага готовности
case ST_STOP: Count_Clear(); //очистка счетчиков
IntervTm = Interval; //загрузка нового интервала
State = ST_START; //запуск измерения
break;
}
}
//------------------------ Прерывание по захвату: ----------------------------
#pragma vector = TIMER1_CAPT_vect
__interrupt void Capture(void)
{
switch(State)
{
case ST_START: //фаза запуска измерения
{
Tb = ICR1; //захват начала интервала
if(!(Tb & 0x8000) && (TIFR & (1 << TOV1)))
Count_M--; //коррекция, если переполнение было до захвата
State = ST_COUNT; //следующая фаза - фаза счета
break;
}
case ST_COUNT: //фаза счета
{
Count_N++; //счет периодов входного сигнала
break;
}
case ST_COMPL: //фаза завершения измерения
{
Te = ICR1; //захват конца интервала
if(!(Te & 0x8000) && (TIFR & (1 << TOV1)))
Count_M++; //коррекция, если переполнение было до захвата
Count_N++; //счет последнего периода
State = ST_READY; //следующая фаза - фаза готовности
break;
}
}
}
//---------------------- Прерывание по переполнению: -------------------------
#pragma vector = TIMER1_OVF_vect
__interrupt void Overflow(void)
{
if(State == ST_COUNT || State == ST_COMPL)
Count_M++; //счет переполнений
}
//--------------------------- Очистка счетчиков: -----------------------------
void Count_Clear(void)
{
Count_N = 0;
Count_M = 0;
Tb = 0;
Te = 0;
}
//-------------------------- Вычисление частоты: -----------------------------
void Get_Freq(void)
{
long m = (long)Count_M * 65536L + Te - Tb; //интервал
if(m)
Freq = (long long)Count_N * (F_CLK * 1E8 * PRESCALER) / m ;
else Freq = 0;
if(Freq > 99999999) Freq = 99999999; //ограничение частоты
}
//----------------- Установка интервала измерения частоты: -------------------
void Count_SetT(int t)
{
State = ST_STOP;
Interval = t;
}
//--------------------- Чтение готовности частотомера: -----------------------
bool Count_Ready(void)
{
return(Ready);
}
//----------------------- Чтение измеренной частоты: -------------------------
long Count_GetF(void)
{
return(Freq);
}
//----------------------------------------------------------------------------