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

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

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

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

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

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

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

 
Опции темы
Непрочитано 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,835
Сказал спасибо: 919
Сказали Спасибо 4,308 раз(а) в 2,573 сообщении(ях)
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, время: 20:22.


Powered by vBulletin® Version 3.8.4
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd. Перевод: zCarot