Микроконтроллеры

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.


Вы здесь » Микроконтроллеры » STM32: Вопросы » Переключение режима таймера STM32F100 в процессе работы


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

Сообщений 1 страница 2 из 2

1

Здравствуйте. Программирую СТМки и в силу своих скудных знаний  столкнулся с проблемой.
Контроллер STM32F100C6(на RB на плате Discovery аналогичное поведение).
Подаю, к примеру, на ETR 200 герц скважность 2.
1. Настраиваю Таймер Т2 на счет импульсов со входа ETR (частотомер), период задается таймером Т3 1 сек(мастер для Т2). Счет работает.

Код:
void EXT_FrequencyCounterConfig(void)                                 
{
	// TIM3 master counter, period 0.1, 1, 10, 100 sec
	EXT_Timer2_ResetRegisters();

	RCC->APB1ENR |= RCC_APB1ENR_TIM3EN;
	TIM3->CR1 &= ~TIM_CR1_CEN;
  NVIC_DisableIRQ(TIM3_IRQn);
	TIM3->PSC = 2400-1; // TIM3 clock 10 kHz
	TIM3->ARR = 10000-1; // TIM3 count 10000 so period 1 sec
	TIM3->CR1 |= TIM_CR1_DIR; // count down to 0
	TIM3->CR1 |= TIM_CR1_OPM; //counter stops counting at the next update event
	TIM3->CR2 |= TIM_CR2_MMS_0; //COUNTER_ENABLE signal to TIM1, used as trigger output (TRGO)
	TIM3->DIER |= TIM_DIER_UIE; //enable interrupt
	
	// TIM2 slave counter, count impulses from TIM2_ETR
	RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;
	TIM2->CR1 &= ~TIM_CR1_CEN;
  NVIC_DisableIRQ(TIM2_IRQn);
  TIM2->PSC = 0;
  TIM2->ARR = 0xFFFF; //counter max value
	TIM2->CR1 = 0 ;
  TIM2->CR2 = TIM_CR2_MMS_1; //update event is selected as trigger output to TIM1
  TIM2->SMCR = TIM_SMCR_ECE | TIM_SMCR_TS_1 | TIM_SMCR_SMS_0 | TIM_SMCR_SMS_2; //ext. clock mode2 enabled, counter is clocked by ETRF signal
	// TIM1 additional counter for TIM2 to make 32 bit counter
	RCC->APB2ENR |= RCC_APB2ENR_TIM1EN;
	TIM1->CR1 &= ~TIM_CR1_CEN;
	TIM1->PSC = 0;
  TIM1->ARR = 0xFFFF; //counter max value
  TIM1->CR1  &= ~TIM_CR1_DIR; //used as upcounter
  TIM1->SMCR &= ~TIM_SMCR_ETPS; //no external trigger prescaller
  TIM1->SMCR &= ~TIM_SMCR_ETF; //no external trigger filter
	TIM1->SMCR |=TIM_SMCR_TS_0;
  TIM1->SMCR |= TIM_SMCR_SMS_0 | TIM_SMCR_SMS_1 | TIM_SMCR_SMS_2; //TIM1 (TRGI) clock the counter
	
	return;
}
//

void EXT_FrequencyCounterRun(void)
{
  NVIC_DisableIRQ(TIM2_IRQn);
  NVIC_EnableIRQ(TIM3_IRQn);
  TIM1->CR1       |= TIM_CR1_CEN;
  TIM2->CR1       |= TIM_CR1_CEN;
  TIM3->CR1       |= TIM_CR1_CEN;
}
//

2. Пробую запустить таймер Т2 для измерения периода между импульсами и заполнение(скважность) - работает.

Код:
void EXT_PeriodCounterConfig(void)
{
	EXT_Timer2_ResetRegisters();
	// TIM2 count period and duty on TI1 input
	RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;
	TIM2->CR1 &= ~TIM_CR1_CEN;
	TIM2->PSC = 240-1; // TIM2 clock 100 kHz
	TIM2->ARR = 0xffff;
//	TIM2->CR1 |= TIM_CR1_OPM; //counter stops counting at the next update event
	TIM2->CCMR1 |= TIM_CCMR1_CC1S_0 | TIM_CCMR1_CC2S_1;
// TIM2->SMCR |= TIM_SMCR_TS_2 | TIM_SMCR_TS_0 | TIM_SMCR_SMS_2; //
 TIM2->SMCR |= TIM_SMCR_TS_2 | TIM_SMCR_TS_0 ; //
 TIM2->SMCR |=  TIM_SMCR_SMS_2; //
	TIM2->CCER  |= TIM_CCER_CC2P | TIM_CCER_CC2E | TIM_CCER_CC1E ;
	TIM2->DIER |= TIM_DIER_CC1IE;//enable interrupt

	return;
}
//

void EXT_PeriodCounterRun(void)
{
  NVIC_DisableIRQ(TIM3_IRQn);
  NVIC_EnableIRQ(TIM2_IRQn);
  TIM3->CR1       &= ~TIM_CR1_CEN;
  TIM1->CR1       &= ~TIM_CR1_CEN;
  TIM2->CR1       |= TIM_CR1_CEN;
	RCC->APB1ENR &= ~RCC_APB1ENR_TIM3EN;
	RCC->APB2ENR &= ~RCC_APB2ENR_TIM1EN;
	RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;
	
	
}

Обработчики прерываний таймеров 2 и 3:

Код:
void TIM3_IRQHandler(void)
{
  TIM3->SR &= ~TIM_SR_UIF; //reset interrupt flag

  RawFreq = ((u32)(TIM1->CNT) << 16) | ((u32)(TIM2->CNT));
  DataReady = SET;
  TIM2->CNT = 0;
  TIM1->CNT = 0;

  TIM3->CR1 |= TIM_CR1_CEN; //another circle
	iii++;
}
//
void TIM2_IRQHandler(void)
{
	if((TIM2->SR & (TIM_SR_CC1IF | TIM_SR_CC1OF))==(TIM_SR_CC1IF))
	{
    if(TIM2->CCR1 !=0)
    {
    	RawPeriod = (uint32_t)TIM2->CCR1;
    	RawDuty = (uint32_t)TIM2->CCR2;
    	DataReadyP = SET;
    	error = 0;
    	jjj++;
    }
	}
	else if ((TIM2->SR & TIM_SR_CC1OF) != 0)  /* Check the overflow */
	{
    error = ERROR_OVERFLOW;
    DataReadyP = SET;
    TIM2->SR &= ~(TIM_SR_CC1OF | TIM_SR_CC1IF); /* Clear the flags */
    return;
	}
	else
  {
    error = ERROR_UNEXPECTED_IT; /* Report an error */
  }
	return;
}
//


3. При попытке переключить таймер Т2 из режима измерения периода на режим измерения числа пришедших импульсов таймер считает, но гораздо медленнее(как будто включается скрытый делитель на входе ЕТR). В отладчике регистр TIM2->CNT принимает значение 1, хотя в случае (1) показывает значения в районе 200.

для запуска счета импульсов (1) в основном коде запускаю

Код:
EXT_FrequencyCounterConfig();
  EXT_FrequencyCounterRun();


для вычисления периода (2)запускаю

Код:
EXT_PeriodCounterConfig();
  EXT_PeriodCounterRun();

Когда стал разбираться, в начале программы попробовал настроить таймер на режим (2), через некоторое время перенастраивал на режим (1).

Код:
	EXT_PeriodCounterConfig();
  EXT_PeriodCounterRun();
	countFnotT=FALSE;
	
	Delay_us(14030);	
	
	EXT_FrequencyCounterConfig();
  EXT_FrequencyCounterRun();
	countFnotT=TRUE;

	__enable_irq();

При этом если задержку (в коде выше функция Delay_us()) делать небольшую - таймер считает правильно, если увеличивать задержку - включается непонятный  "делитель и измеренное количество импульсов оказывается гораздо меньше"
В отладчике при сравнении значений регистров таймеров режима 1 и режима 3 (переключение из режима 2 в режим 1) они одинаковы.
Вопрос - подскажите, кто может, где я неправильно меняю настройки таймера Т2.
Программу пишу в кейл 4.73

Дополнение:
Проблема решилась по подсказке на другом форуме. Оказалось, что некоторые регистры таймеров не обновляются при записи в них нового значения, а требуют еще использования бита генерации обновления и сброса таймера TIM_EGR_UG в регистре EGR таймера. Вывод: надо внимательно читать референс мануал на контроллер, в RM0041 об этом написано, хотя и не совсем ясно. А вот в аппноте AN4776 более прозрачно с указанием всех регистров, на которые оказывает влияние этот бит

Отредактировано busannovmail (2017-11-20 09:07:48)

2

Перенёс топик в STM32: Вопросы, поскольку по сути вопрос


Вы здесь » Микроконтроллеры » STM32: Вопросы » Переключение режима таймера STM32F100 в процессе работы