реклама на сайте
подробности

 
 
> Прерывание от таймера STR91x+Keil MDK 3.22
Shuuura
сообщение Aug 30 2008, 13:01
Сообщение #1


Частый гость
**

Группа: Свой
Сообщений: 80
Регистрация: 23-08-05
Пользователь №: 7 902



Используется таймер TIM1, настраивается на output compare mode, прерывание разрешено:
Код
    TIM1->CR1 &= TIM_CLK_APB;
    TIM1->CR2 &=0xFF00;
    TIM1->CR2 |= 199;
    TIM1->OC1R = 60000;
    TIM_ITConfig(TIM1, TIM_IT_OC1, ENABLE);
    VIC_Config(TIM1_ITLine, VIC_IRQ, 0);
    VIC_ITCmd(TIM1_ITLine, ENABLE);
    TIM_CounterCmd(TIM1, TIM_START);

Обработчик прерывания просто перебрасывает состояние вывода - мигает светодиод.
Код
void TIM1_IRQHandler(void){
       TIM_ClearFlag(TIM1, TIM_FLAG_OC1);
       TIM_CounterCmd(TIM1, TIM_CLEAR);
       if (flag == 1){
        GPIO_WriteBit(GPIO6, GPIO_Pin_7, Bit_SET);
        flag = 0;}
      else{
        GPIO_WriteBit(GPIO6, GPIO_Pin_7, Bit_RESET);
        flag = 1;}
   VIC0->VAR = 0xFF;}

Проблема: прерывание исполняется два раза подряд, т.е. после окончания периода работы счетчика вызывается прерывание и перебрасывается состояние ножки. После этого сразу же вызывается обработчик повторно и возвращает состояние. Потом снова отрабатывается период и все по новой.
Если установить в обработчике точку останова и шагать в отладчике - все работает правильно.
Что я делаю не так?
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов (1 - 7)
koyodza
сообщение Aug 30 2008, 17:40
Сообщение #2


Местный
***

Группа: Свой
Сообщений: 213
Регистрация: 28-02-07
Из: Киев
Пользователь №: 25 744



ответил на телесистемах
Go to the top of the page
 
+Quote Post
vladimir_m
сообщение Sep 2 2008, 11:51
Сообщение #3


Участник
*

Группа: Новичок
Сообщений: 17
Регистрация: 9-07-08
Пользователь №: 38 830



Цитата(koyodza @ Aug 30 2008, 20:40) *
ответил на телесистемах


Я извиняюсь, это был мой вопрос, просто так получилось, что задавал не от своего имени...

Перечитал ваш ответ три раза, потом перечитал reference manual. Все таки своей ошибки я не вижу...
Вполне возможно, что лучше в данном случае работать по timer overflow (пробовал, работает), но не хочется оставлять за спиной такой странный хвост - мало чем вылезет в реальном проекте.
Я понимаю работу счетчика так: при достижении TIM_CNTR значения TIM_OC1R выставляется бит OCF1 и генерится прерывание. В обработчике сбрасывается бит OCF1 и ресетится счетчик в 0xFFFC. Откуда берется второе прерывание?

Сообщение отредактировал vladimir_m - Sep 2 2008, 12:01
Go to the top of the page
 
+Quote Post
koyodza
сообщение Sep 3 2008, 09:11
Сообщение #4


Местный
***

Группа: Свой
Сообщений: 213
Регистрация: 28-02-07
Из: Киев
Пользователь №: 25 744



Цитата(vladimir_m @ Sep 2 2008, 14:51) *
Откуда берется второе прерывание?

Вероятнее всего, из переполнения - сброс (если не ошибаюсь) тоже его вызывает. По виду ситуация очень похожа - прерывания будут идти "парами", с очень малым промежутком
Go to the top of the page
 
+Quote Post
vladimir_m
сообщение Sep 3 2008, 10:28
Сообщение #5


Участник
*

Группа: Новичок
Сообщений: 17
Регистрация: 9-07-08
Пользователь №: 38 830



Цитата(koyodza @ Sep 3 2008, 12:11) *
Вероятнее всего, из переполнения - сброс (если не ошибаюсь) тоже его вызывает.

Скорее всего так. Но в настройках таймера разрешено только прерывание от OC1. Как другие флаги попадают в VIC?
Go to the top of the page
 
+Quote Post
vladimir_m
сообщение Oct 6 2008, 14:53
Сообщение #6


Участник
*

Группа: Новичок
Сообщений: 17
Регистрация: 9-07-08
Пользователь №: 38 830



Я таки нарвался на старые грабли. Опять всплыла старая проблема.
Те же самые двойные прерывания. При более детальном исследовании обнаружено, что
проблема заключается в том, что сброс флага
Код
TIM_ClearFlag(TIM1, TIM_FLAG_OC1);

срабатывает ровно через раз.
Получается что при возникновении флага TIM_FLAG_OC1 вызывается прерывание, а флаг в нем не сбрасывается. Тут-же прерывание вызывается по новой. И флаг все таки сбрасывается.
Как это борется? Може кто сталкивался?

Все. Тема закрыта. Я вкурил в чем дело.
Сначала нужно сбрасывать счетчик, а потом обнулять флаг. Иначе получается, что обнуленный флаг сам восстанавливается.
Go to the top of the page
 
+Quote Post
koyodza
сообщение Oct 6 2008, 16:21
Сообщение #7


Местный
***

Группа: Свой
Сообщений: 213
Регистрация: 28-02-07
Из: Киев
Пользователь №: 25 744



Цитата(vladimir_m @ Oct 6 2008, 17:53) *
Сначала нужно сбрасывать счетчик, а потом обнулять флаг. Иначе получается, что обнуленный флаг сам восстанавливается.

lol.gif
Как я и говорил чуть выше, сброс счетчика вызывает прерывание (вернее, установку флага)
Go to the top of the page
 
+Quote Post
vladimir_m
сообщение Oct 7 2008, 13:17
Сообщение #8


Участник
*

Группа: Новичок
Сообщений: 17
Регистрация: 9-07-08
Пользователь №: 38 830



Вот именно, что не вызов прерывания, а установку флага. В моем случае вызов прерывания вызвано выполнением условия выставления флага. В обработчике я сбрасываю флаг, но условие его выставления остается - и флаг снова появляется. А если сначала сбросить счетчик - исчезает и условие выставления флага.
Короче, в обработчике нужно делать так:
Код
TIM_ClearFlag(TIM1, TIM_FLAG_OC1);
TIM_CounterCmd(TIM1, TIM_CLEAR);

smile.gif
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 21st July 2025 - 20:09
Рейтинг@Mail.ru


Страница сгенерированна за 0.0141 секунд с 7
ELECTRONIX ©2004-2016