Это не имеет ничего общего с ST-Link.
По умолчанию функции задержки работают, отслеживая переменную, которая увеличивается при прерывании по таймеру.Если это прерывание по таймеру заблокировано, то переменная не увеличивается, и функция задержки никогда не завершится.Есть несколько способов обойти это.
Позвольте прерыванию таймера опередить обработчик последовательного прерывания
Убедитесь, что прерывание таймера имеет более высокий приоритет, чем последовательное прерывание.По умолчанию HAL устанавливает прерывание таймера на минимально возможный приоритет (довольно глупая идея IMO) в stm32f4xx_hal_conf.h
#define TICK_INT_PRIORITY 0x0FU /*!< tick interrupt priority */
, изменяет его на более низкое значение (более высокий приоритет) и устанавливает приоритет UART.прерывать до более высокого значения (с более низким приоритетом).Теперь HAL_Delay()
будет работать даже в обработчике прерываний UART.
Заставить HAL_Delay()
работать без прерываний
HAL_Delay()
работает, многократно вызывая HAL_GetTick()
довремя задержки истекло.HAL_GetTick()
должно возвращать время, прошедшее с момента запуска в миллисекундах, в виде 32-разрядного значения без знака.Вы можете предоставить собственную реализацию HAL_GetTick()
, которая использует 32-разрядный аппаратный таймер для определения текущего времени.
Существует два 32-разрядных таймера, TIM2
и TIM5
, выберите один из них.Установите значение перезагрузки на тактовую частоту APB1, деленную на 1000 минус 1 (83999 с настройками часов по умолчанию), начните отсчет вверх.Теперь HAL_GetTick()
может просто вернуть регистр счетчика таймера.
uint32_t HAL_GetTick(void) {
return TIM2->CNT; // or TIM5->CNT
}
Написать собственную функцию задержки
Например, вы можете использовать счетчик циклов для коротких задержек или пустой цикл for
для приблизительных задержек, запуска таймера однократного запуска, ожидания до завершения и т. Д.