:::: MENU ::::

Реализация задержек в мс и мкс через timer 6

Вначале настраиваем таймер

NOTE: Код приведен для частоты тактирования МК = 16МГц. Для другой частоты заменить 16 на нужное значение частоты, в МГц (см. код).

// инициализация таймера - делитель на 16 (при 16МГц - 1 мкс)
void timer_6_init(void)
{
  TIM_TimeBaseInitTypeDef TIMER_InitStructure;
  NVIC_InitTypeDef  NVIC_InitStructure;
    
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE);
  TIM_TimeBaseStructInit(&TIMER_InitStructure);
    
  TIMER_InitStructure.TIM_CounterMode = TIM_CounterMode_Up;
  TIMER_InitStructure.TIM_Period = 16;
  TIMER_InitStructure.TIM_Prescaler = 1;
  TIM_TimeBaseInit(TIM6, &TIMER_InitStructure);
    
  NVIC_InitStructure.NVIC_IRQChannel = TIM6_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
    
  // считаем один раз 
  TIM_SelectOnePulseMode(TIM6, TIM_OPMode_Single);
}

После реализуем две функции задержки, в которые можно передавать время — на которое вызывается задержка в мс и мкс.

uint8_t volatile f_timer_6_end;

void wait_us(uint32_t n_usec)
{   
  f_timer_6_end = 0;
 
  TIM6->PSC = 0;
  TIM6->ARR = (uint16_t)(16 * n_usec);
  TIM_Cmd(TIM6, ENABLE);
 
  // для того чтобы установился PSC
  TIM6->EGR |= TIM_EGR_UG;
  TIM6->SR &= ~TIM_SR_UIF;
 
  TIM_ITConfig(TIM6, TIM_IT_Update, ENABLE);
  TIM_Cmd(TIM6, ENABLE);
 
  while(f_timer_6_end == 0); 
}

void wait_ms(uint32_t n_msec)
{   
  f_timer_6_end = 0;
 
  TIM6->PSC = 1000 - 1;
  TIM6->ARR = (uint16_t)(16 * n_msec);
  // для того чтобы установился PSC
  TIM6->EGR |= TIM_EGR_UG;
  TIM6->SR &= ~TIM_SR_UIF;
 
  TIM_ITConfig(TIM6, TIM_IT_Update, ENABLE);
  TIM_Cmd(TIM6, ENABLE);
 
  while(f_timer_6_end == 0); 
}

Данные функции настраивают параметр таймера — число до которого нужно считать. И включает таймер, и уходит в цикл

while(f_timer_6_end == 0){}

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

void TIM6_IRQHandler(void)
{
  extern uint8_t volatile f_timer_6_end;
 
  TIM_ClearITPendingBit(TIM6, TIM_IT_Update);
  TIM6->SR &= ~TIM_SR_UIF;
  f_timer_6_end = 1;
 
  TIM_Cmd(TIM6, DISABLE);
  TIM_ITConfig(TIM6, TIM_IT_Update, DISABLE);
}