ВходНаше всё Теги codebook 无线电组件 Поиск Опросы Закон Среда
24 апреля
426540 Топик полностью
Лeoнид Ивaнoвич (22.07.2013 20:07, просмотров: 244) ответил Юрий_СВ на Логика перывания такая :
У меня модуль тахометра выглядит так:  //---------------------------------------------------------------------------- //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++; //подсчет переполнений } //----------------------------------------------------------------------------