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






