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

Очистка флага прерывания по переполнению в таймере общего назначения. STM32F105RC

Добрый день, возникла проблема с обработкой прерывания по переполнению от таймера общего назначения TIM6 в микроконтроллере STM32F105RC. Среда разработки CooCox. TIM_ClearITPendingBit(TIM6, TIM_IT_Update) не сбрасывает флаг прерывания и я соответсвенно попдаю в него снова, но уже не по времени,которое мне необходимо,если верить системному таймеру. Данную строку двигал в разные часть обработчика прерывания, но в показанном мной коде,она должна стоять в этом месте,как я выяснил из литературы(проверяем, что прерывание от таймера и затем чистим(насколько я выяснил это надо сделать как можно быстрее)). Так же меня скорость тиков таймера с требуемых 100us до 1ms, так как думал,что не успеваю очистить и попадаю снова в прерывание из-за скорости. Результат один и тот же. По идее мне нужны настройки тиков таймера каждые 0,1ms и дальше период прерываний задается конфигурированием, пока работаю с конфигурацией,что прерывание должно быть каждые 96ms, те период 960 тиков или 96ms. Вопрос , что я сделал неправильно,что таймер так себя ведет?

void TIM6_IRQHandler(void)    // обработчик прерывания
{
    time = portGetTickCount(); // тут получаем время от системного таймера
    //TIM6 ->SR &= ~TIM_SR_UIF;
    //TIM_ClearITPendingBit(TIM6, TIM_IT_Update);
    if (TIM_GetITStatus(TIM6, TIM_IT_Update) != RESET)
    {
        TIM_ClearITPendingBit(TIM6, TIM_IT_Update);			// ДАННАЯ СТРОКА судя по отладчику не сбрасывает флаг прерывания
        if (sync_timer_callbacks[0])
        {
            if ( sync_timer_callbacks[0]() )
            {
            }
        }
    }
}

//настройка таймера
void sync_timer_now_setup(uint16 alarm, uint16 ticks, uint16 period)
{
	uint16 now;
	NVIC_InitTypeDef NVIC_InitStructure;
	sync_timer_periods[alarm]=period;
	now = portGetTickCnt();
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
	switch (alarm) {
		case 0:


			RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE);									//beacon timer setup
			TIM_TimeBaseStructInit(&base_timer0);
			base_timer0.TIM_Prescaler =(3600)-1;                        //one tick every 100us
			base_timer0.TIM_Period = ticks;
			TIM_TimeBaseInit(TIM6, &base_timer0);
			TIM_ITConfig(TIM6, TIM_IT_Update, ENABLE);
			TIM_Cmd(TIM6, ENABLE);
			NVIC_InitStructure_timer0.NVIC_IRQChannel = TIM6_IRQn;
			NVIC_InitStructure_timer0.NVIC_IRQChannelPreemptionPriority = 13;
			NVIC_InitStructure_timer0.NVIC_IRQChannelSubPriority = 0;
			NVIC_InitStructure_timer0.NVIC_IRQChannelCmd = ENABLE;
			NVIC_Init(&NVIC_InitStructure_timer0);
			break;
		case 1:

			RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);						// timeout timer
			TIM_TimeBaseStructInit(&base_timer1);
			base_timer1.TIM_Prescaler = 3600-1;
			base_timer1.TIM_Period = ticks;
			TIM_TimeBaseInit(TIM3, &base_timer1);
			TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);
			TIM_Cmd(TIM3, ENABLE);
			NVIC_InitStructure_timer1.NVIC_IRQChannel = TIM3_IRQn;
			NVIC_InitStructure_timer1.NVIC_IRQChannelPreemptionPriority = 14;
			NVIC_InitStructure_timer1.NVIC_IRQChannelSubPriority = 0;
			NVIC_InitStructure_timer1.NVIC_IRQChannelCmd = ENABLE;
			NVIC_Init(&NVIC_InitStructure_timer1);
			break;
		case 2:

			RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);					//timer for sending in nodes
			TIM_TimeBaseStructInit(&base_timer2);
			base_timer2.TIM_Prescaler = 3600-1;
			base_timer2.TIM_Period = ticks;
			TIM_TimeBaseInit(TIM4, &base_timer2);
			TIM_ITConfig(TIM4, TIM_IT_Update, ENABLE);
			TIM_Cmd(TIM4, ENABLE);
			NVIC_InitStructure_timer2.NVIC_IRQChannel = TIM4_IRQn;
			NVIC_InitStructure_timer2.NVIC_IRQChannelPreemptionPriority = 12;
			NVIC_InitStructure_timer2.NVIC_IRQChannelSubPriority = 0;
			NVIC_InitStructure_timer2.NVIC_IRQChannelCmd = ENABLE;
			NVIC_Init(&NVIC_InitStructure_timer2);
			break;
		default:
			break;
	}
}

//настройка системной частоты, выбор источников тактирования
int RCC_Configuration(void)
{
	ErrorStatus HSEStartUpStatus;
	RCC_ClocksTypeDef RCC_ClockFreq;
	/* RCC system reset(for debug purpose) */
	RCC_DeInit();
	/* Enable HSE */
	RCC_HSEConfig(RCC_HSE_ON);
	/* Wait till HSE is ready */
	HSEStartUpStatus = RCC_WaitForHSEStartUp();
	if(HSEStartUpStatus != ERROR)
	{
		/* Enable Prefetch Buffer */
		FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
		/****************************************************************/
		/*
		 * HCLK=72MHz, PCLK2=72MHz, PCLK1=36MHz 						*/
		/****************************************************************/
		/* Flash 2 wait state */
		FLASH_SetLatency(FLASH_Latency_2);
		/* HCLK = SYSCLK */
		RCC_HCLKConfig(RCC_SYSCLK_Div1);
		/* PCLK2 = HCLK */
		RCC_PCLK2Config(RCC_HCLK_Div1);
		/* PCLK1 = HCLK/2 */
		RCC_PCLK1Config(RCC_HCLK_Div2);
		/*  ADCCLK = PCLK2/4 */
		RCC_ADCCLKConfig(RCC_PCLK2_Div6);
		/* Configure PLLs *********************************************************/
		/* PLL2 configuration: PLL2CLK = (HSE / 4) * 8 = 24 MHz */
		RCC_PREDIV2Config(RCC_PREDIV2_Div4);
		RCC_PLL2Config(RCC_PLL2Mul_8);
		/* Enable PLL2 */
		RCC_PLL2Cmd(ENABLE);
		/* Wait till PLL2 is ready */
		while (RCC_GetFlagStatus(RCC_FLAG_PLL2RDY) == RESET){}
		/* PLL1 configuration: PLLCLK = (PLL2 / 3) * 9 = 72 MHz */
		RCC_PREDIV1Config(RCC_PREDIV1_Source_PLL2, RCC_PREDIV1_Div3);
		RCC_PLLConfig(RCC_PLLSource_PREDIV1, RCC_PLLMul_9);
		/* Enable PLL */
		RCC_PLLCmd(ENABLE);
		/* Wait till PLL is ready */
		while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET){}
		/* Select PLL as system clock source */
		RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
		/* Wait till PLL is used as system clock source */
		while (RCC_GetSYSCLKSource() != 0x08){}
	}
	RCC_GetClocksFreq(&RCC_ClockFreq);
	/* Enable SPI1 clock */
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
	/* Enable SPI2 clock */
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
	/* Enable GPIOs clocks */
	RCC_APB2PeriphClockCmd(
						RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB |
						RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD |
						RCC_APB2Periph_GPIOE | RCC_APB2Periph_AFIO,
						ENABLE);

	return 0;
}
//запуск системного таймера
int SysTick_Configuration(void)
{
	if (SysTick_Config(SystemCoreClock / CLOCKS_PER_SEC))
	{
		/* Capture error */
		while (1);
	}
	NVIC_SetPriority (SysTick_IRQn, 0);
	return 0;
}

 

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


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

18 minutes ago, Arlleex said:

В регистрах DEBUG-модуля заморожено тактирование таймеров во время отладки?

Настройки по-умолчанию в CooCox, вроде бы тактирование продолжается(значения в Value меняются при пошаговой отладке, хотя в принципе так и должно быть), но сказать точно не могу. Можете подсказать где это проверить?

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


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

33 минуты назад, evsx1 сказал:

TIM_ClearITPendingBit(TIM6, TIM_IT_Update); // ДАННАЯ СТРОКА судя по отладчику не сбрасывает флаг прерывания

Так pending bit - это не бит прерывания TIM_SR_UIF. Эх, плодятся и множатся "кубисты", увеличивают энтропию вселенной.

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


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

Только что, evsx1 сказал:

Настройки по-умолчанию в CooCox, вроде бы тактирование продолжается(значения в Value меняются при пошаговой отладке, хотя в принципе так и должно быть), но сказать точно не могу. Можете подсказать где это проверить?

image.png.188808c365474e61af075a6b39387a41.png

 

Не знаю как в CooCox, в Keil (ды везде примерно одинаково) заходите в модуль DBG, и ставите галочку напротив таймера, тактирование которого при отладке надо заморозить (остановить). Иначе он будет работать даже при остановленном отладчиком процессоре, и, естественно, Вы будете попадать бесконечно в это прерывание.

 

Только что, ViKo сказал:

Так pending bit - это не бит прерывания TIM_SR_UIF.

У него правильно сделано. А та строка с TIM_SR_UIF тоже верная.

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


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

3 минуты назад, Arlleex сказал:

У него правильно сделано. А та строка с TIM_SR_UIF тоже верная.

Верная, но закомментирована.

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


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

Только что, ViKo сказал:

Верная, но закомментирована.

TIM_ClearITPendingBit(TIM6, TIM_IT_Update);

делает то же самое. Посмотрите внимательнее:wink:

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


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

Just now, ViKo said:

Верная, но закомментирована.

как написано в начале поста,я пробовал и с ней. не помогло.

6 minutes ago, Arlleex said:

image.png.188808c365474e61af075a6b39387a41.png

 

Не знаю как в CooCox, в Keil (ды везде примерно одинаково) заходите в модуль DBG, и ставите галочку напротив таймера, тактирование которого при отладке надо заморозить (остановить). Иначе он будет работать даже при остановленном отладчиком процессоре, и, естественно, Вы будете попадать бесконечно в это прерывание.

 

У него правильно сделано. А та строка с TIM_SR_UIF тоже верная.

Видимо, CooCox устарел уже,не вижу я таких регистров в описании МК. но за подсказку спасибо. В настройках таймера явных ошибок нет?

image.png

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


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

Только что, evsx1 сказал:

как написано в начале поста,я пробовал и с ней. не помогло.

Дык остановите бедный таймер! Он молотит не останавливаясь, когда Вы на точке останова.

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


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

1 minute ago, Arlleex said:

Дык остановите бедный таймер! Он молотит не останавливаясь, когда Вы на точке останова.

Спасибо,вот сейчас пытаюсь разобраться как это делается

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


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

Только что, evsx1 сказал:

Спасибо,вот сейчас пытаюсь разобраться как это делается

DBG->CR для Вашего МК.

image.png.6b01a7ffafdbea623bcce24cfa11806e.png

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


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

4 minutes ago, Arlleex said:

DBG->CR для Вашего МК.

image.png.6b01a7ffafdbea623bcce24cfa11806e.png

Большое спасибо! Использование данных функций SPL которые конфигурируют этот регистр,помогло увидеть сброс прерывания у этого таймера

DBGMCU_Config(DBGMCU_TIM3_STOP,ENABLE);

DBGMCU_Config(DBGMCU_TIM4_STOP,ENABLE);

DBGMCU_Config(DBGMCU_TIM6_STOP,ENABLE);

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


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

16 минут назад, Arlleex сказал:

TIM_ClearITPendingBit(TIM6, TIM_IT_Update);

делает то же самое. Посмотрите внимательнее:wink:

ClearITPendingBit означает стереть pending bit в контроллере прерываний. Он сам стирается, когда выполняется прерывание. А нужно стереть источник запроса прерывания. 

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


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

1 minute ago, ViKo said:

ClearITPendingBit означает стереть pending bit в контроллере прерываний. Он сам стирается, когда выполняется прерывание. А нужно стереть источник запроса прерывания. 

 

3 minutes ago, ViKo said:

ClearITPendingBit означает стереть pending bit в контроллере прерываний. Он сам стирается, когда выполняется прерывание. А нужно стереть источник запроса прерывания. 

Каким образом он сам сотрется ? просто из-за того что прерывание выполненыно? нет.

image.thumb.png.67025d0d29ad685955ffea166c1f3be8.png

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


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

Ага. При входе в прерывание. Автоматически.

Похоже, у вас таймер молотит чаще, чем вы успеваете обработать его запросы прерывания. Это если стираете TIM_SR_UIF.

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


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

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