Перейти к содержанию
    

32stmf0 timer interrupts

Прошу прощения ели тема поднималась - не нашел.

Проект на STM32F070. Timer3 используется для задержки. Простейший режим: считаем вверх до ARR, прерывание по переполнению. Почему то после инициализации первое прерывание происходит СРАЗУ. Вне зависимости от прескалера и ARR. А дальше все как и положено.

 

После долгих упражнений решил обмануть - первый раз жду переполнения, благо ждать микросекунды, и сбрасываю. Так работает, но как то коряво. В чем собственно корень зла?

Пробовал инизиализачию и через HAL и напрямую. Без разницы.

void Timer3Init(void){

    int PrescalerValue = (uint32_t)(SystemCoreClock / 100000) - 1;
    TIM3->CR1 = 0;   // disable timer
    TIM3->PSC = PrescalerValue;
    TIM3->ARR = 2;
    TIM3->CR1 = TIM_CR1_CEN;   // Enable timer
    while((TIM3->SR & 1) == 0); // <*************** танец с бубном тут
    TIM3->CR1 = 0;   // disable timer
    NVIC_ClearPendingIRQ(TIM3_IRQn);
    NVIC_EnableIRQ(TIM3_IRQn); // Enable interrupt from TIM3 (NVIC level)
}

void StartTimer3(int timeout){
  Timer3Expired = 0;
  TIM3->CR1 = 0;   // disable timer
  TIM3->ARR = timeout / 10;
  TIM3->CR1 = TIM_CR1_CEN;   // Enable timer
  TIM3->SR = 0; // clear interrupt flag
  TIM3->DIER = TIM_DIER_UIE; // Enable update interrupt (timer level)
}

На разных форумах читал что похожая фигня на других линейках, но ответа нигде не нашел. Вдруг тут повезет?

Изменено пользователем IgorKossak

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Попробуйте очистить SR до того, как разрешите работу.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Перед тем как разрешать прерывания надо чистить и регистр флагов таймера и соответствующий бит в регистре NVIC.CLRPEND.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Проект на STM32F070. Timer3 используется для задержки. Простейший режим: считаем вверх до ARR, прерывание по переполнению. Почему то после инициализации первое прерывание происходит СРАЗУ. Вне зависимости от прескалера и ARR. А дальше все как и положено.

Дело в том, что регистр PSC (как и ARR, если мне не изменяет память) буферизован, и обновляется только при переполнении таймера.

Чтобы изменить прескалер немедленно, надо сгенерировать событие переполнения:

    TIM3->EGR = TIM_EGR_UG;

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Перед тем как разрешать прерывания надо чистить и регистр флагов таймера и соответствующий бит в регистре NVIC.CLRPEND.

 

А "NVIC_ClearPendingIRQ(TIM3_IRQn);" не это делает?

 

SR чистил, не помогло.

Дело в том, что регистр PSC (как и ARR, если мне не изменяет память) буферизован,

 

Я так понял что ARR может быть буферизован или нет в зависимости от CR1->ARPE. Но проблема не в PSC.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я так понял что ARR может быть буферизован или нет в зависимости от CR1->ARPE. Но проблема не в PSC.

Да, буферизация ARR отключается. (И вы ее отключили). А вот буферизация PSC - нет. Таким образом, вы думаете, что PSC равен PrescalerValue, а в действительности он у вас равен 0. Поэтому, когда вы задаёте ARR 2, то таймер срабатывает через 2 цикла.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Да, буферизация ARR отключается. (И вы ее отключили). А вот буферизация PSC - нет. Таким образом, вы думаете, что PSC равен PrescalerValue, а в действительности он у вас равен 0. Поэтому, когда вы задаёте ARR 2, то таймер срабатывает через 2 цикла.

 

Задаю ARR=2 я специально, когда ХОЧУ чтобы первое переполнение было быстрее. А пока этого не делал, в ARR записывал 1500, но все равно СРАЗУ происходило первое переполнение.

Возможно это делается специально чтобы записались ARR и PSC. В общем мой костыль работает надежно, так и оставлю.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В общем мой костыль работает надежно, так и оставлю.

Так вот вместо этого вашего костыля (ждать, когда наступит переполнение), ST придумали специальный битик TIM_EGR_UG, который вызывает переполнение сразу, без ожидания.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Так вот вместо этого вашего костыля (ждать, когда наступит переполнение), ST придумали специальный битик TIM_EGR_UG, который вызывает переполнение сразу, без ожидания.

Так продолжи: проинициализировать ARR, PSC, взвести _UG, почистить флаги прерываний, разрешить оные, - и поехали...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я так запускаю:

  TIM7->PSC = нечто...;
  TIM7->ARR = нечто...;
  TIM7->EGR = TIM_EGR_UG;
  TIM7->SR = 0;        
  TIM7->CR1 |= TIM_CR1_CEN;

А. Прерывания не использовал. Просто ждал, когда в статусе появится флаг.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Так вот вместо этого вашего костыля (ждать, когда наступит переполнение), ST придумали специальный битик TIM_EGR_UG, который вызывает переполнение сразу, без ожидания.

 

Да, спасибо. Нашел уже этот битик.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Можно установить

DBGMCU_APB1_FZ_DBG_TIM3_STOP

и отладчиком пройтись - сразу видно будет

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...