Организация задержки в stm32

Согласитесь, очень удобно пользоваться функциями delay_ms() при работе с контроллерами AVR. Жаль, что таких функций нет для stm32.
Задержка в avr организована в виде двух циклов написанных на ассемблере. Расчет величины задержки выполняется при помощи директив учитывающих частоту процессора на этапе компиляции. В stm32 такой подход не является таким действенным из-за больших частот.

Производитель (тобеш STMicroelectronics) предлагает другой подход.
Запрограммируем прерывание sys_tick, а уже в нем будем выполнять цикл декрементирующий счетчик. При этом ввиду высокой частоты будем считать, что потери на выполнение цикла (операции перехода в ассемблере) не значительны.

Я буду пользоваться отладочной платой stm32f4 discovery.

#include <stm32f4xx.h>
#include <stm32f4_discovery.h>

// счетчик 
static __IO uint32_t TimingDelay;

// прототипы
void Delay(__IO uint32_t nTime);
void TimingDelay_Decrement(void);

Проект для stm32 устроен так (если вы соблюдали рекомендации), что перед выполнением функции main выполняется SystemInit(), которая настраивает тактирование микроконтроллера. Так что сразу после входа в main можно настроить прерывание SysTick. Весь код уже написан за нас.

  // 0.001 с = 1/1000 с = 1мс
  if (SysTick_Config(SystemCoreClock / 1000)){ 
    /* если вернулся не ноль - ошибка */ 
    while (1);
  }

Прерывание будет происходить каждую мс.
Теперь нам нужно две функции. Одну будем вставлять в код для вставки задержки, другая служебная и будет выполнять декремент счетчика из прерывания.

/* функция задержки */
void Delay(__IO uint32_t nTime){ 
  TimingDelay = nTime;
  while(TimingDelay != 0); // безконченый цикл пока значение счетчика не нулевое
}

/* декремент значения счетчика задержки, если он не равен нулю */
void TimingDelay_Decrement(void){
  if (TimingDelay != 0x00){ 
    TimingDelay--;
  }
}

Ну и конечно же нам понадобиться написать обработчик прерывания, который будет вызывать функцию TimingDelay_Decrement().

void SysTick_Handler(void) {
  TimingDelay_Decrement();
}

Теперь все готово к использованию.
Настроим светодиоды и поморгаем с необходимой задержкой.

  // инициализируем светодиоды 
  STM_EVAL_LEDInit(LED4);
  STM_EVAL_LEDInit(LED3);
  STM_EVAL_LEDInit(LED5);
  STM_EVAL_LEDInit(LED6);

  // Включаем LED4 и LED5 
  STM_EVAL_LEDOn(LED4);
  STM_EVAL_LEDOn(LED5);

  while(1) {
    Delay(1000); // задержка в 1с = 1000мс
    STM_EVAL_LEDToggle(LED3);  // переключение состояния светодиода 3
  }

Светодиод будем изменять свое состояние раз в секунду.

PS Функция SysTick_Config принимает на вход значение делителя для 24 битного таймера, а переменная SystemCoreClock содержит значение частоты работы микроконтроллера.

Скачать проект для IAR

 

Похожий код:

Фото аватара
Алексей Петров

Программист, разработчик с 5 летним опытом работы. Учусь на разработчика игр на Unity и разработчика VR&AR реальности (виртуальной реальности). Основные языки программирования: C#, C++.

Оцените автора
Бла, бла код
Добавить комментарий