Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: 32stmf0 timer interrupts
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
alexf
Прошу прощения ели тема поднималась - не нашел.
Проект на 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)
}

На разных форумах читал что похожая фигня на других линейках, но ответа нигде не нашел. Вдруг тут повезет?
ViKo
Попробуйте очистить SR до того, как разрешите работу.
jcxz
Перед тем как разрешать прерывания надо чистить и регистр флагов таймера и соответствующий бит в регистре NVIC.CLRPEND.
AHTOXA
Цитата(alexf @ Sep 28 2016, 07:20) *
Проект на STM32F070. Timer3 используется для задержки. Простейший режим: считаем вверх до ARR, прерывание по переполнению. Почему то после инициализации первое прерывание происходит СРАЗУ. Вне зависимости от прескалера и ARR. А дальше все как и положено.

Дело в том, что регистр PSC (как и ARR, если мне не изменяет память) буферизован, и обновляется только при переполнении таймера.
Чтобы изменить прескалер немедленно, надо сгенерировать событие переполнения:
Код
    TIM3->EGR = TIM_EGR_UG;
alexf
Цитата(jcxz @ Sep 27 2016, 21:51) *
Перед тем как разрешать прерывания надо чистить и регистр флагов таймера и соответствующий бит в регистре NVIC.CLRPEND.


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

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


Я так понял что ARR может быть буферизован или нет в зависимости от CR1->ARPE. Но проблема не в PSC.
AHTOXA
Цитата(alexf @ Sep 28 2016, 12:58) *
Я так понял что ARR может быть буферизован или нет в зависимости от CR1->ARPE. Но проблема не в PSC.

Да, буферизация ARR отключается. (И вы ее отключили). А вот буферизация PSC - нет. Таким образом, вы думаете, что PSC равен PrescalerValue, а в действительности он у вас равен 0. Поэтому, когда вы задаёте ARR 2, то таймер срабатывает через 2 цикла.
alexf
Цитата(AHTOXA @ Sep 28 2016, 02:49) *
Да, буферизация ARR отключается. (И вы ее отключили). А вот буферизация PSC - нет. Таким образом, вы думаете, что PSC равен PrescalerValue, а в действительности он у вас равен 0. Поэтому, когда вы задаёте ARR 2, то таймер срабатывает через 2 цикла.


Задаю ARR=2 я специально, когда ХОЧУ чтобы первое переполнение было быстрее. А пока этого не делал, в ARR записывал 1500, но все равно СРАЗУ происходило первое переполнение.
Возможно это делается специально чтобы записались ARR и PSC. В общем мой костыль работает надежно, так и оставлю.
AHTOXA
Цитата(alexf @ Sep 29 2016, 02:08) *
В общем мой костыль работает надежно, так и оставлю.

Так вот вместо этого вашего костыля (ждать, когда наступит переполнение), ST придумали специальный битик TIM_EGR_UG, который вызывает переполнение сразу, без ожидания.
KnightIgor
Цитата(AHTOXA @ Sep 29 2016, 00:10) *
Так вот вместо этого вашего костыля (ждать, когда наступит переполнение), ST придумали специальный битик TIM_EGR_UG, который вызывает переполнение сразу, без ожидания.

Так продолжи: проинициализировать ARR, PSC, взвести _UG, почистить флаги прерываний, разрешить оные, - и поехали...
ViKo
Я так запускаю:
Код
  TIM7->PSC = нечто...;
  TIM7->ARR = нечто...;
  TIM7->EGR = TIM_EGR_UG;
  TIM7->SR = 0;        
  TIM7->CR1 |= TIM_CR1_CEN;

А. Прерывания не использовал. Просто ждал, когда в статусе появится флаг.
alexf
Цитата(AHTOXA @ Sep 28 2016, 15:10) *
Так вот вместо этого вашего костыля (ждать, когда наступит переполнение), ST придумали специальный битик TIM_EGR_UG, который вызывает переполнение сразу, без ожидания.


Да, спасибо. Нашел уже этот битик.
x893
Можно установить
DBGMCU_APB1_FZ_DBG_TIM3_STOP
и отладчиком пройтись - сразу видно будет
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.