Авторизация


...

Кто на сайте?

Сейчас один гость и 2 зарегистрированных пользователей на сайте

  • elwhidbynath
  • magierskadal

Статистика

-Посетители : 28029
-Материалы : 210

Пользователь сайта продает...

  ENC28J60

Пользователь сайта покупает...

Программные таймеры

Автор: Alex Просмотров: 3712


Давайте разберём это на примере.
Что нам нужно ? Нам нужно создать переменную, которая будет счётчиком ,и флаг состояния таймера.
Можно объявить 2 переменных. Одна будет счётчик(например unsigned int), другая - типа bit. Но мы пойдём немного другим путём. Мы будем использовать старший бит переменной как бит состояния. Т.е. знак переменной у нас будет состоянием таймера. Но, тут есть один минус. Разрешение нашего таймера сократиться ровно в 2 раза, т.к. один бит будет занят. Т.е., если переменная = 2 байтам, то считать мы сможем только до 32767.

Создаём 2-х байтную знаковую переменную. Именно знаковую, т.к. знак у нас - состояние таймера.

 

  signed int volatile cnt;

Далее, нам необходимо создать обработчик прерываний от любого, имеющегося на "борту" МК, таймера.
Возьмём за основу 1-й таймер. Тактовая частота МК = 20Мгц. Таймер настраиваем на 1 мс.

Возьмём за основу 1-й таймер. Тактовая частота МК = 20Мгц. Таймер настраиваем на 1 мс.

  void interrupt _isr(void){
if(TMR1IF){      // Если событие от таймера
TMR1IF=0;           // Сбрасываем флаг события
TMR1-=5000;       // Переустанавливаем таймер на 5000 тактов (при 20Мгц - 1мс.).
}
}

Системные тики имеем. Теперь нам нужно их считать, т.е. сделать обработчик нашего программного таймера.
Сделаем проверку флага состояния, и, если таймер запущен, уменьшим счётчик на единицу.
Добавляем в ОП системного таймера такой код

  if(cnt < 0)     // Если таймер запущен
cnt++;             // Уменьшаем его счётчик на единицу.

Проверяем переменную на отрицательность (старший бит переменной). Тем самым, мы проверяем состояние таймера, и, если переменная отрицательна(<0) - уменьшаем счётчик таймера на еденицу.
Увеличение, как Вы заметили, переменной cnt - не ошибка. Счётчик у нас будет считать от -n до 0. Где n-это устанавливаемое значение таймера. Поэтому мы делаем инкремент переменной(это и есть уменьшение счётчика таймера на единицу).
Программный таймер и его обработка созданы. Осталось всё это применить на деле.
В процедуре main() инициализируем системный таймер(TMR1) и разрешаем прерывания.

  TMR1ON=1;         // Включить TMR1
TMR1IF=0;          // Сбросить флаг от TMR1
TMR1IE=1;          // Разрешить прерывания от TMR1
TMR1=-5000;      // Установить TMR1 на 5000 тактов/

PEIE=1;                // Разрешаем прерывания от перефирии
GIE=1;                 // и глобально

Далее зацикливаем программу

  while(1){              // Бесконечный цикл

}

В этом цикле установим программный таймер на 500 тиков и будем ждать окончания его счёта. По окончанию счёта, проинвертируем один из ПИНов порта.

  while(1){              // Бесконечный цикл
cnt = -500;          // Установка таймера на 500 тиков
while(cnt< 0)        // Ждём отсчёта таймера, т.б. когда он не будет < 0
continue;              //
RB0=!RB0;           // Инверсия RB0
}

И у нас получится мигалка с частотой в 1Гц
Скачать пример (49,56К)

Естественно, для мигания светодиода зацикливать программу, в ожидании окончания отсчёта таймера, глупо. Но мы можем не зацикливать программу, а просто проверять флаг состояния и мигать светодиодом. А программа, после проверки флага будет продолжать работать дальше.
Например, установим таймер, будем его проверять и продолжать выполнять программу дальше. Если проверка прошла, перезапустим таймер заново и проинвертируем пин светодиода.

  cnt = -500;                // Предустановка таймера на 500 тиков
while(1){                    // Бесконечный цикл
if(cnt >= 0){          // Если таймер отсчитал, т.е. значение счётчика не отрицательное
cnt = -500;       // Устанавливаем таймер заново на 500 тиков
RB0 = !RB0;      // и проинвертируем RB0
}
/*** Тут программа продолжает работу ****/
NOP();
NOP();
NOP();

/****************************************/
}


В итоге, результат получился как и в предыдущем примере, но программа не зациклена, она продолжает свою работу. А LED инвертируется, только когда отсчитает таймер. В том и прелесть программных таймеров, что они считают "в фоне", а проверяем их только по необходимости.
Скачать пример (48,97К)

Для справочки, кусочек дизасма:

  40: if(cnt>=0){          // Если таймер отсчитал, т.е. значение счётчика не отрицательное
033    1BA1 BTFSC  0x21, 0x7
034    283B GOTO  0x3b
41: cnt = -500;         // Устанавливаем таймер заново на 500 тиков
035    300C MOVLW 0xc
036    00A0 MOVWF 0x20
037    30FE MOVLW 0xfe
038    00A1 MOVWF 0x21
42: RB0=!RB0;       // и проинвертируем RB0
039    3001 MOVLW 0x1
03A    0686 XORWF 0x6, F

Заметьте, компилятор не делает никаких ужасных вычислений, он просто проверяет старший бит переменной.

 

  Используемый софт для примеров:
Компилятор HI-TECH PICC
Среда разработки MPlab
Отладчик Proteus

Обсуждение статьи тут

Случайные статьи....

Prev Next

Модуль регулятора и счетчика оборотов коллекторного двигателя

18-02-2012 Александр Милевский

Модуль регулятора и счетчика оборотов коллекторного двигателя

Данное устройство разрабатывалось как устройство стабилизации двигателя насоса для домашней производственной установки. Предназначено для жесткой фиксации скорости перекачивания жидкости насосом. Два объемных насоса должны качать жидкости в определенном соотношении, и никакие внешние воздействия не должны это соотношение менять. Жидкости разные...

Ремонт помпы BEKA-MAX

27-05-2013 Super User

Ремонт помпы BEKA-MAX

Эти помпы используются для централизованной смазки различных механизмов и узлов техники. Поломка заключалась в отсутствии признаков жизни у чипа BEKA-MAX. Соответственно, отсутствовало и управление двигателем помпы. Так как заменить плату или чип на новый, не представлялось возможным, был поставлен простой выключатель...

Быстрое Преобразование Фурье

23-04-2011 Алексей

Быстрое Преобразование Фурье

АЛГОРИТМ БЫСТРОГО ВЫЧИСЛЕНИЯ ДИСКРЕТНОГО ПРЕОБРАЗОВАНИЯ ФУРЬЕ. Очень важно понимать, что БПФ, это не самостоятельное вычисление, а всего лишь быстрый алгоритм вычисления Дискретного преобразования Фурье. К примеру, для вычисления ДПФ в лоб, вектора длиной 8, необходимо 64 комплексных умножения. Для его же...

Библиотека для динамической индикации (АСМ)

02-05-2011 Alex

Библиотека для динамической индикации (АСМ)

Привязка библиотеки под нужный индикатор и схему подключения. #define ind_size x ; Кол-во индикаторов Эта строчка отвечает за кол-во используемых индикаторов, где x это число индикаторов. Их может быть от 1 до 8 штук.  #define ind_invert   ; Инверсия общего...


Все права принадлежат ChipMK.ru. При копировании материала ссылка обязательна. 2011-2017 © ChipMK.ru

ChipMk.ru Яндекс.Метрика
PRCY.ru