Реклама на сайте DatasheetsDatasheets

KAZUS.RUN - Электронный портал. Принципиальные схемы, Datasheets, Форум по электронике

Новости электроники Новости Литература, электронные книги Литература Документация, даташиты Документация Поиск даташитов (datasheets)Поиск PDF
  От производителей
Новости поставщиков
В мире электроники

  Сборник статей
Книги и журналы
FAQ по электронике

  Datasheets
Поиск SMD
Онлайн справочник

Принципиальные схемы Схемы Каталоги программ, сайтов Каталоги Общение, форум Общение Ваш аккаунтАккаунт
  Каталог схем
Схемы и проекты
Принципиальные схемы
  Программы
Каталог сайтов
Калькуляторы
  Форумы по электронике
Помощь проекту

Микроконтроллеры, АЦП, память и т.д Темы касающиеся микроконтроллеров разных производителей, памяти, АЦП/ЦАП, периферийных модулей...

 
Опции темы

Прерывания таймера

Непрочитано 01.12.2010, 11:25  
radistor
Частый гость
 
Регистрация: 07.10.2007
Сообщений: 14
Сказал спасибо: 5
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
radistor на пути к лучшему
По умолчанию Прерывания таймера

Уважаемые форумчане, прошу вашей помощи, уже голову сломал почему не работает должным образом прерывания от таймера.
Вообщем по порядку:
Пишу программу на atmega128. Среда разработки - AVR Studio + WinAVR.
Проблема в следующем - есть прервания от таймера с переодичностью 5мс. В обработчике прерываний инкрементируется переменная, которая затем проверяется в главном цикле программы. По положительному результату проверки вызывается функция в которой делается довольно долгое действие (несколько десятков мс).
Так вот, получается что величина переодичности изменяется на велечину этой задержки.
Специально создал простенькую программу, листинг которой приведу ниже:
Код:
#include ‹util/delay.h›
#include ‹avr/io.h›
#include ‹avr/interrupt.h›

//объявляем глобальную переменную
volatile uint8_t t = 0;
//инициализируем таймер, тиканье с периодом 5мс (частота кварца 16МГц)
void InitTimer(void)
{
    cli();
    OCR1A=1249;
    TCNT1=0;
    TCCR1C=0x00;
    TCCR1A=0x00;
    TCCR1B=0x0B;
    TIMSK=TIMSK | (1‹‹OCIE1A);
    sei();
}
//тут меняем пин порта B и делаем тупую задержку
void test (void)
{
    PORTB = ~PORTB;
    _delay_ms(20);
}
//в прерывании таймера только инкрементируем переменную
ISR(TIMER1_COMPA_vect)
{
    t++;
}

int main(void)
{
    DDRB  |= 0b10000000;
    PORTB |= 0b10000000;
    InitTimer();
    while(1){
        ждем 5*20=100мс
        if (t==20){
            test();
            t=0;
        }
    }
}
По идеи изменения порта B должны происходить каждые 100мс, но на самом деле происходят 100+20=120мс.
Реклама:
radistor вне форума  
Непрочитано 01.12.2010, 11:36  
sasareccer
Частый гость
 
Аватар для sasareccer
 
Регистрация: 20.07.2006
Сообщений: 37
Сказал спасибо: 2
Сказали Спасибо 7 раз(а) в 4 сообщении(ях)
sasareccer на пути к лучшему
По умолчанию Re: Прерывания таймера

в
void test (void)
убери строку:

_delay_ms(20);
sasareccer вне форума  
Непрочитано 01.12.2010, 11:41  
radistor
Частый гость
 
Регистрация: 07.10.2007
Сообщений: 14
Сказал спасибо: 5
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
radistor на пути к лучшему
По умолчанию Re: Прерывания таймера

Сообщение от sasareccer Посмотреть сообщение
в
void test (void)
убери строку:

_delay_ms(20);
Эту строку я специально поставил. Это упрощенный листинг (который тоже тестировался). А в основной программе вместо _delay_ms(20); вызываются различные функции общей длительностью порядка 20-25мс.
Если убрать эту задержку, то тогда все естественно работает нормально. Кстати забыл написать, что обработчик прерывания работает нормально, т.е тикает каждые 5 мс, и ничего ему не мешает.
radistor вне форума  
Непрочитано 01.12.2010, 11:48  
Easyrider83
Гуру портала
 
Аватар для Easyrider83
 
Регистрация: 27.10.2008
Адрес: ЕС
Сообщений: 10,821
Сказал спасибо: 919
Сказали Спасибо 4,289 раз(а) в 2,570 сообщении(ях)
Easyrider83 на пути к лучшему
По умолчанию Re: Прерывания таймера

Выбросите проверку t в основном цикле и закиньте ее в прерывание. Там поднимайте флаг (переменная boolean) и по флагу идите дальше в основном теле.
Easyrider83 вне форума  
Непрочитано 01.12.2010, 12:04  
radistor
Частый гость
 
Регистрация: 07.10.2007
Сообщений: 14
Сказал спасибо: 5
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
radistor на пути к лучшему
По умолчанию Re: Прерывания таймера

Сообщение от Easyrider83 Посмотреть сообщение
Выбросите проверку t в основном цикле и закиньте ее в прерывание. Там поднимайте флаг (переменная boolean) и по флагу идите дальше в основном теле.
Сделал по вашему совету, всеравно одно и тоже - задержка 120мс. Я уже замучился с этим бороться. (
Кстати и на реальном устройстве и в отладке AVR Studio задержка одинаковая. Из-за чего она берется я никак понять не могу.

Т.е как должно работать в идеале - каждые 100мс происходит переход на пользовательскую функцию. В этой функции может быть любая задержка ‹100мс. Контроллер обработает эту функцию, дождется следующих 100мс и заново повторит.
radistor вне форума  
Непрочитано 01.12.2010, 12:08  
sasareccer
Частый гость
 
Аватар для sasareccer
 
Регистрация: 20.07.2006
Сообщений: 37
Сказал спасибо: 2
Сказали Спасибо 7 раз(а) в 4 сообщении(ях)
sasareccer на пути к лучшему
По умолчанию Re: Прерывания таймера

если
_delay_ms(20);
так необходима, тогда просто надо поменять местами строки

test();
t=0;

и получится следующее

while(1){
//ждем 5*20=100мс
if (t==20){
t=0;
test();
}
}

Могу пояснить почему так:
Переменная t досчитала до =20, сработал if, Вы отправили на выполнение функцию test(); внутри которой есть задержка, а счетчик-то так и не обнулился, он обнулится только через "четыре раза" таймера (4х5мс), когда дойдет дело до строки t=0;, т.е. успеет посчитать до t=24, вот и получается в плюс 20мс. А если сразу после срабатывания if обнулять в первую очередь t, а потом уже делать что-то в функции test(); - то все будет OK.

Последний раз редактировалось sasareccer; 01.12.2010 в 12:15.
sasareccer вне форума  
Сказали "Спасибо" sasareccer
radistor (01.12.2010)
Непрочитано 01.12.2010, 12:17  
radistor
Частый гость
 
Регистрация: 07.10.2007
Сообщений: 14
Сказал спасибо: 5
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
radistor на пути к лучшему
По умолчанию Re: Прерывания таймера

[QUOTE=sasareccer;286114]если
_delay_ms(20);
так необходима, тогда просто надо поменять местами строки
test();
t=0;
QUOTE]

Спасибо за подсказку, действительно не просчитал что t обнуляется потом. НО(!) сейчас переделал и всеравно 120мс.
radistor вне форума  
Непрочитано 01.12.2010, 12:29  
radistor
Частый гость
 
Регистрация: 07.10.2007
Сообщений: 14
Сказал спасибо: 5
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
radistor на пути к лучшему
По умолчанию Re: Прерывания таймера

sasareccer все нормально, это я поспешил просто проверить результат. Что то я конкретно ступил, наверное сказывается усталость. )
Действительно в не том месте обнулял переменную, а начал грешить на контроллер,программатор и компилятор )))
Еще раз спасибо!
radistor вне форума  
 

Метки
atmega128, прерывания, таймер
Опции темы

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.

Быстрый переход

Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
"Глюк" AVR таймера от кварца 32768 Гц alexgap Коллекция глюков 23 16.09.2013 07:29
Прерывания PIC milssky Микроконтроллеры, АЦП, память и т.д 12 10.10.2010 13:31
Обработка прерывания таймера T0 ATtiny2313 DimanVIP Микроконтроллеры, АЦП, память и т.д 10 03.06.2010 11:54
Вложенные прерывания HITECH PIC16 picavr Микроконтроллеры, АЦП, память и т.д 17 07.03.2010 17:39
Вход в прерывания для PIC микроконтроллеров dimmich Микроконтроллеры, АЦП, память и т.д 4 06.12.2009 17:17


Часовой пояс GMT +4, время: 14:48.


Powered by vBulletin® Version 3.8.4
Copyright ©2000 - 2026, Jelsoft Enterprises Ltd.