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