STM32. Часть 4. Задержки, таймеры, системный таймер SysTick
Задержки в STM32.
Задержки можно реализовывать с помощью пустого цикла и с помощью прерываний.
При организации задержки с помощью пустого цикла МК ничего не делает некоторое количество тактов.
При организации задержки с помощью таймеров повышается точность. Таймер при этом настраивается в режиме одного импульса, устанавливается предделитель и число, до которого следует считать. Затем проверяется установка флага.
Для организации периодичности выполнения задач имеет смысл настраивать таймеры по переполнению в обычном режиме (не в режиме 1 импульса), чтобы прерывание вызывалось с периодичностью каждые n тактов (мкс, мс, с).
Как вариант реализации периодичности выполнения команд имеет смысл рассматривать системный таймер SysTick, функция инициализации и настройки которого имеется в самой CMSIS (stm32f10x.h).
Программная задержка.
while(time)
time--;
Задержка на таймере. Условимся использовать для задержек на таймере таймер TIM7 (когда свободен SysTick, то его)
RCC->APB1ENR |= RCC_APB1ENR_TIM7EN; // вкл тактирование ТИМ7
Для формирования задержек, кратных мкс или мс, необходимо настроить предделитель, для этого частоту делим на 1000 (для миллисекунд) или на 1000000 (для микросекунд). Затем из полученного числа обязательно отнимаем 1. Например, если наш МК работает на частоте 24МГц, то для того, чтобы таймер тикал 1 раз в 1 мкс надо настроить предделитель как 24-1, а 1мс - как 24000-1.
TIM7->PSC = 24000-1; // 1 мс
TIM7->CR1 |= TIM_CR1_OPM; // одноимпульсный режим
TIM7->ARR = ms; // инициализируем значение, до которого считать
TIM7->CNT = 0; // сбрасываем счетчик
TIM7->CR1 |= TIM_CR1_CEN; // Запускаем таймер
while(!(TIM7->SR & TIM_SR_UIF)); // Ожидаем флаг прерывания
TIM7->SR &= ~TIM_SR_UIF; // Сбрасываем флаг
SysTick. 24-битный таймер. Системный таймер также годится для формирования задержек. В случаях, когда не требуется периодически выполнять какие-либо действия с постоянным интервалом, например, каждые 100мс, то чтобы не занимать таймеры, можно использовать системный.
Тактовую частоту можем получить из 32-битной переменной SystemCoreClock.
#define SYSTICK_MAX 0xFFFFFF
// ...
void delay(uint32_t time) {
// Защита от неправильных значений
if (time > SYSTICK_MAX || time == 0)
return;
SysTick->CTRL &= ~SysTick_CTRL_TICKINT_Msk;
SysTick->CTRL |= SysTick_CTRL_CLKSOURCE_Msk;
SysTick->LOAD = (SystemCoreClock * time / 1000); // ms
SysTick->LOAD = (SystemCoreClock * time / 1000000); // us
SysTick->VAL = 0;
SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;
while (!(SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk));
SysTick->CTRL &= ~SysTick_CTRL_COUNTFLAG_Msk;
SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;
}
Когда требуется периодически выполнять какие-либо действия с определенным интервалом, необходимо настраивать таймеры с генерацией прерываний с определенной частотой. Так как это очень простая задача, а базовые и другие таймеры умеют много чего, то чтобы их не занимать, будем использовать системный таймер SysTick, тем более, его инициализация и запуск уже описаны в файле ядра core:
__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks);
Тактовую частоту можем получить из 32-битной переменной SystemCoreClock.
Таким образом, инициализация таймера будет выглядеть следующим образом:
SysTick_Config(SystemCoreClock / OF_per_sec);
где OF_per_sec - количество перегрузок в секунду, т.е., если нужны прерывания каждую 1мс, то OF_per_sec = 1000, 1 мкс: OF_per_sec = 1000000.
Обработчик прерывания:
void SysTick_Handler(void);
Задержки можно реализовывать с помощью пустого цикла и с помощью прерываний.
При организации задержки с помощью пустого цикла МК ничего не делает некоторое количество тактов.
При организации задержки с помощью таймеров повышается точность. Таймер при этом настраивается в режиме одного импульса, устанавливается предделитель и число, до которого следует считать. Затем проверяется установка флага.
Для организации периодичности выполнения задач имеет смысл настраивать таймеры по переполнению в обычном режиме (не в режиме 1 импульса), чтобы прерывание вызывалось с периодичностью каждые n тактов (мкс, мс, с).
Как вариант реализации периодичности выполнения команд имеет смысл рассматривать системный таймер SysTick, функция инициализации и настройки которого имеется в самой CMSIS (stm32f10x.h).
Программная задержка.
while(time)
time--;
Задержка на таймере. Условимся использовать для задержек на таймере таймер TIM7 (когда свободен SysTick, то его)
RCC->APB1ENR |= RCC_APB1ENR_TIM7EN; // вкл тактирование ТИМ7
Для формирования задержек, кратных мкс или мс, необходимо настроить предделитель, для этого частоту делим на 1000 (для миллисекунд) или на 1000000 (для микросекунд). Затем из полученного числа обязательно отнимаем 1. Например, если наш МК работает на частоте 24МГц, то для того, чтобы таймер тикал 1 раз в 1 мкс надо настроить предделитель как 24-1, а 1мс - как 24000-1.
TIM7->PSC = 24000-1; // 1 мс
TIM7->CR1 |= TIM_CR1_OPM; // одноимпульсный режим
TIM7->ARR = ms; // инициализируем значение, до которого считать
TIM7->CNT = 0; // сбрасываем счетчик
TIM7->CR1 |= TIM_CR1_CEN; // Запускаем таймер
while(!(TIM7->SR & TIM_SR_UIF)); // Ожидаем флаг прерывания
TIM7->SR &= ~TIM_SR_UIF; // Сбрасываем флаг
SysTick. 24-битный таймер. Системный таймер также годится для формирования задержек. В случаях, когда не требуется периодически выполнять какие-либо действия с постоянным интервалом, например, каждые 100мс, то чтобы не занимать таймеры, можно использовать системный.
Тактовую частоту можем получить из 32-битной переменной SystemCoreClock.
#define SYSTICK_MAX 0xFFFFFF
// ...
void delay(uint32_t time) {
// Защита от неправильных значений
if (time > SYSTICK_MAX || time == 0)
return;
SysTick->CTRL &= ~SysTick_CTRL_TICKINT_Msk;
SysTick->CTRL |= SysTick_CTRL_CLKSOURCE_Msk;
SysTick->LOAD = (SystemCoreClock * time / 1000); // ms
SysTick->LOAD = (SystemCoreClock * time / 1000000); // us
SysTick->VAL = 0;
SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;
while (!(SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk));
SysTick->CTRL &= ~SysTick_CTRL_COUNTFLAG_Msk;
SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;
}
Когда требуется периодически выполнять какие-либо действия с определенным интервалом, необходимо настраивать таймеры с генерацией прерываний с определенной частотой. Так как это очень простая задача, а базовые и другие таймеры умеют много чего, то чтобы их не занимать, будем использовать системный таймер SysTick, тем более, его инициализация и запуск уже описаны в файле ядра core:
__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks);
Тактовую частоту можем получить из 32-битной переменной SystemCoreClock.
Таким образом, инициализация таймера будет выглядеть следующим образом:
SysTick_Config(SystemCoreClock / OF_per_sec);
где OF_per_sec - количество перегрузок в секунду, т.е., если нужны прерывания каждую 1мс, то OF_per_sec = 1000, 1 мкс: OF_per_sec = 1000000.
Обработчик прерывания:
void SysTick_Handler(void);
Комментарии
Отправить комментарий