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

Опубликовано lamazavr - вт, 03/04/2014 - 16:40
Body

Согласитесь, очень удобно пользоваться функциями 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

Добавить комментарий

Этот вопрос задается для того, чтобы выяснить, являетесь ли Вы человеком или представляете из себя автоматическую спам-рассылку.