STM32 HAL SysTick(System timer) как устроен, настройка и управление.
System timer или в простонародье SysTick, системный таймер практически как базовый периферийный таймер имеющий только основу и наделен простой функцией отсчёт импульсов в обратном направление(декремент), также генерирует прерывание от обнуление своего счётчика.

Системный таймер как и основная периферия тактируется от AHB шины, на входе имеет предделитель который может иметь два значения это входная частота делится на 1 или на 8.
Основную функцию в таймере выполняют счётчик(Counter) и регистр перезагрузки(Reload_Value), в регистр перезагрузки записывается значение для отсчёта нужного интервала времени, после того как таймер будет запущен значение из регистра перезагрузки автоматически загружается в счётчик и он начинает уменьшатся, достигнув нулевого значения перегружается заново и генерирует прерывание.
Прерывание SysTick как настроить.
В файле stm32f1xx_it.c имеется функция обработки прерывания, которую можно переместить в тело вашей программы для удобства, но не забудьте её тогда удалить в файле stm32f1xx_it.c.

Прерывание от SysTick настроено так, чтобы срабатывать каждую миллисекунду, функция HAL_IncTick() которая находится в обработчике прерывания увеличивает внутреннею переменную uwTick на uwTickFreq(по умолчанию 1), функция HAL_Delay(500) будет отслеживать пока uwTick не достигнет 500(полминуты).
Пример программы.
В примере кода показано как самому настроить SysTick самостоятельно или используйте одну из функций HAL_Init(), или HAL_InitTick(15U) которые за вас это сделают.
Настройка таймера осуществляется после выполнения функции HAL_InitTick которая выполняется в функции HAL_Init(), если код программы сгенерирован в STM32CubeMX то функция задержки HAL_Delay будет работать корректно иначе вам самим придется корректировать некоторые параметры./*ProgCont.ru*/
#include "main.h"
uint32_t count;
int main(void){
// HAL_Init();
// HAL_InitTick(15U);
/*Начало, самостоятельно настраиваем SysTick*/
SystemCoreClock = 8000000;//Частота контроллера
uwTickFreq = 1;//Задержка в миллисекундах
count = SystemCoreClock / (1000U / uwTickFreq);//Значение для регистра Reload
WRITE_REG( SysTick->LOAD, count);
HAL_NVIC_SetPriority(SysTick_IRQn, 15U, 0U);
SET_BIT( SysTick->CTRL, SysTick_CTRL_CLKSOURCE_Msk);//Устанавливаем предделитель в 1
SET_BIT( SysTick->CTRL, SysTick_CTRL_TICKINT_Msk);//Включаем прерывание
SET_BIT( SysTick->CTRL, SysTick_CTRL_ENABLE_Msk);//Включаем таймер
HAL_NVIC_DisableIRQ(SysTick_IRQn);
/*Конец, самостоятельно настраиваем SysTick*/
__HAL_RCC_GPIOC_CLK_ENABLE();
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = GPIO_PIN_13;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
while (1){
HAL_GPIO_TogglePin( GPIOC, GPIO_PIN_13); HAL_Delay(500);
}
}
void SysTick_Handler(void){
/*Внутрения функция функции HAL_Delay, не удалять!*/
HAL_IncTick();
}
#ifdef USE_FULL_ASSERT
void assert_failed(uint8_t *file, uint32_t line){}
#endif /* USE_FULL_ASSERT */Программа меняет состояние вывода GPIOC GPIO_PIN_13 на противоположно каждые пол секунды или если подключен светодиод то он мигает каждую секунду, отсчёт времени ведёт функция HAL_Delay(500).
Функции настройки системного таймера.
void HAL_Delay(uint32_t Delay) - функция предназначена для создание паузы в коде программы минимальное значение которой может быть миллисекунда, функция использует SysTick.
HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority) - функция настраивает автоматически SysTick, включает таймер и его прерывание если настройку используете сами без STM32CubeMX то придется корректировать значение переменной библиотеки HAL SystemCoreClock( частота работы AHB шины или контроллера если предделитель AHB=1).
void HAL_SuspendTick(void) - функция отключает прерывание от SysTick тем самым прекращает работу прерываний таймера, функция HAL_Delay работать больше не будет.
void HAL_ResumeTick(void) - функция включает прерывание от SysTick тем самым возобновляет работу прерывания от таймера. Данная функция используется если отключалось прерывание таймера функцией HAL_SuspendTick().
HAL_StatusTypeDef HAL_SetTickFreq(HAL_TickFreqTypeDef Freq) - функция изменяет частоту срабатывания прерывания от SysTick, по умолчанию таймер настроен на частоту 1KHz для отработки задержки от функции HAL_Delay в 1 миллисекунду. Перед использование данной функции измените значение переменной библиотеки HAL uwTickPrio = 15(устанавливается приоритет прерывания).
SET_BIT(REG, BIT) - функция напрямую настраивает регистр SysTick_CTRL, устанавливая нужные биты.
CLEAR_BIT(REG, BIT) - функция напрямую настраивает регистр SysTick_CTRL, сбрасывает нужные биты.
WRITE_REG(REG, VAL) - функция записывает новое значение в регистры Reload_Value и Counter.
READ_REG(REG) - функция читает данные из регистра Reload_Value и Counter.
uwTickFreq - переменная которая изменяет скорость отсчёта времени.
Описание функций.
void HAL_Delay(uint32_t Delay);
Принимаемое значение от 1 миллисекунды до зависит от частоты
/*Пример настройки задержки 1 секунда*/
HAL_Delay(1000);
HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority);
Функция принимает приоритет прерывания для SysTick
Если установлена 4 группа для прерываний функцией
HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);
То значение может быть
от 0 до 15, устанавливается обычно 15
/*Пример настройки*/
SystemCoreClock = 8000000;
HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);
HAL_InitTick(15);
void HAL_SuspendTick(void);
/*Пример использования*/
HAL_SuspendTick();
void HAL_ResumeTick(void);
/*Пример использования*/
HAL_ResumeTick();HAL_StatusTypeDef HAL_SetTickFreq(HAL_TickFreqTypeDef Freq);
Функция принимает значение частоты в KHz
/*Пример настройки на частоту 1KHz*/
uwTickPrio = 15;
HAL_SetTickFreq(1);SET_BIT(REG, BIT);
Функция принимает два параметра:
регистр контроля SysTick->CTRL
и маски для управления
SysTick_CTRL_CLKSOURCE_Msk - установит предделитель таймера в 1
SysTick_CTRL_TICKINT_Msk - включает прерывание
SysTick_CTRL_ENABLE_Msk - включает таймер
/*Пример*/
SET_BIT( SysTick->CTRL, SysTick_CTRL_ENABLE_Msk);CLEAR_BIT(REG, BIT);
Функция принимает два параметра:
регистр контроля SysTick->CTRL
и маски для управления
SysTick_CTRL_CLKSOURCE_Msk - установит предделитель таймера в 8
SysTick_CTRL_TICKINT_Msk - отключает прерывание
SysTick_CTRL_ENABLE_Msk - отключает таймер
/*Пример*/
CLEAR_BIT( SysTick->CTRL, SysTick_CTRL_ENABLE_Msk);WRITE_REG(REG, VAL);
Функция принимает регистр REG это
SysTick->LOAD - Reload Value( регистр перегрузки регистра счётчика)
SysTick->VAL - Current Value( регистр счётчик)
и второй параметр который принимает функция это значение VAL
которое может быть от 0 до 16777215
/*Пример*/
WRITE_REG( SysTick->LOAD, 10000);READ_REG(REG);
Функция принимает регистр REG это
SysTick->LOAD - Reload Value( регистр перегрузки регистра счётчика)
SysTick->VAL - Current Value( регистр счётчик)
Возвращает значение нужного регистра
/*Пример*/
uint32_t val = READ_REG(SysTick->VAL);uwTickFreq
внутренняя переменная HAL
Варианты:
HAL_TICK_FREQ_1KHZ - установлено по умолчанию
HAL_TICK_FREQ_100HZ - увеличивает скорость в 10 раз
HAL_TICK_FREQ_10HZ - увеличивает скорость в 100 раз
/*Пример использования*/
uwTickFreq = HAL_TICK_FREQ_100HZ;
HAL_Delay(500);


