Телесистемы
 Разработка, производство и продажа радиоэлектронной аппаратуры
На главную   | Карта сайта | Пишите нам | В избранное
Требуется программист в Зеленограде
- обработка данных с датчиков; ColdFire; 40 тыс.
e-mail:jobsmp@pochta.ru

Телесистемы | Электроника | Конференция «Микроконтроллеры и их применение»

Чтобы относительная точность оставалась неизменной, нужно фиксировать не число оборотов, а измерительный интервал. А число оборотов - сколько туда поместится. Вот моя реализация:

Отправлено Леонид Иванович 21 мая 2009, г. 17:54
В ответ на: я делал тахометр (+) отправлено пользователем werewolf 21 мая 2009, г. 15:16


//----------------------------------------------------------------------------

//Модуль измерения частоты входного сигнала
//Сигнал подается на вход захвата таймера 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);
}

//----------------------------------------------------------------------------


Составить ответ | Вернуться на конференцию.

Ответы


Отправка ответа
Имя*: 
Пароль: 
E-mail: 
Тема*:

Сообщение:

Ссылка на URL: 
URL изображения: 

если вы незарегистрированный на форуме пользователь, то
для успешного добавления сообщения заполните поле, как указано ниже:
введите число 89:

Перейти к списку ответов | Конференция | Раздел "Электроника" | Главная страница | Карта сайта

Rambler's Top100 Рейтинг@Mail.ru
 
Web telesys.ru