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

Проблема с обработчиком прерываний

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

Вот инит таймера.

static void TIM2_init(void)
{



	NVIC_EnableIRQ (TIM2_IRQn);
	NVIC_SetPriority(TIM2_IRQn, 0);
	/* Включаем тактирование на порту А GPIO */
	RCC->AHBENR |= (1<<17);

	/*Выставляем альтернативную функцию на РА1*/
	GPIOA->MODER |= GPIO_MODER_MODER1_1;
	GPIOA->PUPDR |= GPIO_PUPDR_PUPDR1_0;

	/*Задаем AF2 для PА1*/
	GPIOA->AFR[0] |= (1<<5);

	RCC->APB1ENR |=(1<<0); //включаем тактирование таймера 2
	TIM2->PSC = 7; //предделитель для получения тактовой частоты 1 МГц
	TIM2->CR1 |= TIM_CR1_ARPE; //TIM2_ARR register is buffered
	TIM2->ARR = 9100;

	 /*настраиваем СC1 на вход TI2*/
	 TIM2->CCMR1 |= TIM_CCMR1_CC1S_1;
	 TIM2->CCMR1 &= ~TIM_CCMR1_CC1S_0;

	 //TIM2->CCER &= ~TIM_CCER_CC1NP ; //активная полярность  канала передний фронт
	 TIM2->CCER &= ~(TIM_CCER_CC1NP | TIM_CCER_CC1P);


	 /*настраиваем СС2 на вход TI2*/
	 TIM2->CCMR1 |= TIM_CCMR1_CC2S_0;
	 TIM2->CCMR1 &= ~TIM_CCMR1_CC2S_1;

	 /*Устанавливаем срабатывание по заднему фронту (активная полярность)*/
	 TIM2->CCER |= TIM_CCER_CC2P;
	 TIM2->CCER |= TIM_CCER_CC1E ; //разрешаем захват

	   /*Выбрать TI2FP2 в качестве входа триггера */
	   TIM2->SMCR |=  (TIM_SMCR_TS_1| TIM_SMCR_TS_2);
	   TIM2->SMCR &= ~TIM_SMCR_TS_0;

	   /*reset mode*/
	   TIM2->SMCR |= TIM_SMCR_SMS_2  ;
	   TIM2->SMCR &= ~TIM_SMCR_SMS_0 | TIM_SMCR_SMS_1;

	   //TIM2->EGR |= TIM_EGR_UG;

	   TIM2->DIER |= TIM_DIER_CC1IE;

	   TIM2->EGR = TIM_EGR_UG;
	   TIM2->SR;
	   TIM2->SR = 0;

	   TIM_EnableCounter(TIM2);

}

А вот сам обработчик

void TIM2_IRQHandler(void)
{
	uint32_t sr = TIM2->SR;
	TIM2->SR = ~sr;

	if(sr & TIM_SR_CC1IF)
	  {

	      period = (TIM2->CCR1);

	  }
	  else if ((TIM2->SR & TIM_SR_CC1OF) != 0)  /* Check the overflow */
	  {

	    TIM2->SR = ~(TIM_SR_CC1OF | TIM_SR_CC1IF); /* Clear the flags */


	    return;
	  }

	printf("period is %lu\n", period);

	__ISB();
}

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

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


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

55 minutes ago, sith633 said:

В чем может быть затык?

Как минимум в принте в обработчике прерывания.

 

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


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

Чем же он мешает? Меня предупреждали, что это плохо, но не смертельно. Я его выносил в тело основной функции, но результат был примерно тем же

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

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


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

6 minutes ago, sith633 said:

Чем же он мешает? Меня предупреждали, что это плохо, но не смертельно. Я его выносил в тело основной функции, но результат был примерно тем же

Пока идет печать может произойти несколько событий.

И еще.

У вас в обработчике конструкция else if. Если одновременно произойдут оба события, то второе вы потеряете. Уберите else.

И к тому же, вы сначала сбрасываете флаги в регистре статуса, а потом проверяете это регистр статуса.

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


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

void TIM2_IRQHandler(void)
{

	TIM2->SR = ~TIM_SR_UIF;

	if ((TIM2->SR & TIM_SR_CC1IF) != 0)
	  {

	      period = (TIM2->CCR1);

	  }
	if ((TIM2->SR & TIM_SR_CC1OF) != 0)  /* Check the overflow */
	  {

	    TIM2->SR = ~(TIM_SR_CC1OF | TIM_SR_CC1IF); /* Clear the flags */


	    return;
	  }



	__ISB();
}

При таком виде обработчика принимается только стартовый бит

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


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

2 часа назад, sith633 сказал:

Чем же он мешает? Меня предупреждали, что это плохо, но не смертельно.

Если вы даже не понимаете почему printf() там в принципе недопустим, то прерываниями вам вообще рано заниматься.

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


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

Если тут сброс бита подразумевается:

TIM2->SR = ~TIM_SR_UIF;

то он не так делается, а так:

TIM2->SR &= ~TIM_SR_UIF;

В остальных местах та же ситуация.

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

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


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

1 минуту назад, Wasserati сказал:

Если тут сброс бита подразумевается:


TIM2->SR = ~TIM_SR_UIF;

	

то он не так делается, а так:


TIM2->SR &= ~TIM_SR_UIF;

	

В остальных местах та же ситуация.

Может вам всё-таки почитать мануал? Вместо того чтобы нести чушь.

Сброс бита UIF так и делается, как было: TIM2->SR = ~TIM_SR_UIF;

А то что вы изобразили - это сброс случайных битов в SR. Которым не повезло.

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


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

9 minutes ago, jcxz said:

Может вам всё-таки почитать мануал? Вместо того чтобы нести чушь.

Сброс бита UIF так и делается, как было: TIM2->SR = ~TIM_SR_UIF;

А то что вы изобразили - это сброс случайных битов в SR. Которым не повезло.

Я бы поспорил. Что-либо сбросить случайно второй вариант в принципе не может.

А вот посмотрев даташит могу утверждать, что обе конструкции дадут идентичный эффект, тут разницы не будет, да.

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


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

2 минуты назад, Wasserati сказал:

Я бы поспорил. Что-либо сбросить случайно второй вариант в принципе не может.

А вот посмотрев даташит могу утверждать, что обе конструкции дадут идентичный эффект, тут разницы не будет, да.

да ладно? А если немного подумать?

Ничего что &= - это чтение-модификация-запись? И что будет, если в момент чтения какой-то другой бит-флаг был =0, а сразу после чтения он установился =1? Что с ним сделает команда записи?

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


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

Переменная period объявлена с квалификатором volatile?

 

Ещё такой тупой совет. Сделайте в обработчике прерывания инверсию какого-либо свободного GPIO выхода и посмотрите логическим анализатором на то, как и когда вызывается обработчик при захвате сигнала.

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


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

21 hours ago, jcxz said:

да ладно? А если немного подумать?

Ничего что &= - это чтение-модификация-запись? И что будет, если в момент чтения какой-то другой бит-флаг был =0, а сразу после чтения он установился =1? Что с ним сделает команда записи?

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

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


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

12.11.2021 в 20:35, Sergey_Aleksandrovi4 сказал:

Переменная period объявлена с квалификатором volatile?

 

Ещё такой тупой совет. Сделайте в обработчике прерывания инверсию какого-либо свободного GPIO выхода и посмотрите логическим анализатором на то, как и когда вызывается обработчик при захвате сигнала.

Совет оказался дельным, я, признаться, об этом как-то не подумал. Прерывания срабатывали как надо, все дело в printf было и в методе отладки(я использовал семихостинг и тыкал эти принты куда только можно) Разобравшись в том почему printf недопустима, я ее отовсюду убрал и... Все тут же заработало. Всем откликнувшимся спасибо.

 

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


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

Гость
Эта тема закрыта для публикации ответов.
×
×
  • Создать...