Кто любит RISC в жизни, заходим, не стесняемся.
Ответить

Не работает переключение режима таймера STM32F100

Чт ноя 16, 2017 16:27:15

Здравствуйте. Программирую СТМки в силу своих скудных знаний и столкнулся с проблемой.
Контроллер 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, проект прилагаю.

upd: добавил куски кода из проекта в сообщение.
Вложения
Project01_s6d0129_FcounterTestTimers.zip
проект в кейл 4.73
(978.18 KiB) Скачиваний: 49

Re: Не работает переключение режима таймера STM32F100

Пн ноя 20, 2017 08:05:01

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