Авторизация


...

Кто на сайте?

Сейчас 96 гостей и ни одного зарегистрированного пользователя на сайте

Статистика

-Посетители : 23007
-Материалы : 209

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

   AV-S2G4B

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

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

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


Давайте разберём это на примере.
Что нам нужно ? Нам нужно создать переменную, которая будет счётчиком ,и флаг состояния таймера.
Можно объявить 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

Программирование c нуля в AVRStudio 5 (ч.9)

15-10-2012 Радик

Программирование c нуля в AVRStudio 5 (ч.9)

Перейдем к изучению встроенных таймеров. Изучение прерываний и особенно таймеров в микроконтроллерах представляет определенную сложность из за их многофункциональности. Сегодня постараемся разобраться в терминах и названиях. В микроконтроллерах AVR могут быть от одного до 4-х таймеров, восьмиразрядные или шестнадцатиразрядные. Упрощенно таймеры обозначаются буквой...

Применения системы приоритета прерываний в м/к PIC18XXXX

03-09-2013 Николай Викторов

Применения системы приоритета прерываний в м/к PIC18XXXX

Если в вашем приложении включена приоритетная система прерывания, то при составлении программы необходимо придерживаться определенных рекомендаций. Как мы помним у  прерывания с высоким приоритетом  вектор сброса 08h  в памяти программ, а с низким 18h, т.е. для написания кода в высоком...

Сравнения двух беззнаковых 16-разрядных чисел

21-09-2011 Александр Милевский

Простое сравнения двух беззнаковых 16-разрядных чисел  X и Y. старший байт H, младший байт L   movf    HX,W subwf   HY,W btfss   STATUS,C goto    Xbol     ; результат: X > Y btfss...

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

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

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

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


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

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