Помимо таймеров общего назначения, о которых я расскажу немного позже, в микроконтроллерах STM32 существует еще и таймер SysTick. Этот таймер уже встроен в ядро Cortex M3 и он может отсчитывать произвольное количество тактов и формировать прерывание по факту окончания счета. Так, например, если ядро работает на частоте 64 МГц, а значение Reload регистра 64000, то 1000 раз в секунду SysTick будет обнуляться. Счетный регистр 24-битный, это значит, что можно отсчитывать и достаточно большие интервалы времени, например, 100 мс (Reload reg = 6 400 000). Таймер очень удобен для формирования неблокирующих задержек. Даже в HAL'е он активно используется для отсчета задержек HAL_Delay(). Любопытный факт: ни в Datasheet, ни в Reference Manual для своего STM32 вы не найдете информацию по работе с SysTick. А здесь найдете!
Предыдущий урок по ссылке https://ipasoft.info/index.php/articles/cmsis-stm32-urok-3-rabota-s-gpio
Подпишитесь на канал, чтобы получать новые публикации первым
Подробная информация о работе с SysTick, который является компонентом ядра, находится непосредственно в Cortex-M3 Technical Reference Manual на 144-ой странице. Но в более упрощенном виде я предоставлю её здесь, в этой статье.
В самом начале, в первом уроке (клик), при заготовке шаблона проекта мы создавали файл с обработчиками прерывания it.c. В нем есть обработчик
void SysTick_Handler(void) { }
Настроим системный таймер на ежемиллисекундное срабатывание. Именно в этот обработчик программа и будет прерываться. Поэтому резонно внутри него создать код установки флага прошествия 1 мс и флаг прошествия 100 мс.
extern bool t1ms;
extern bool t100ms;
void SysTick_Handler(void) {
static uint8_t t100msCntr = 0;
t1ms = true;
if (++t100msCntr >= 100) {
t100msCntr = 0;
t100ms = true;
}
}
А теперь перейдем непосредственно к настройке SysTick и прерываний от него.
// Настройка системного таймера
void SysTick_Setup(void) {
SysTick->LOAD = 64000;
// Счетчик включить, прерывания будут, источник тактирования SYSTEM OSC
SysTick->CTRL = SysTick_CTRL_ENABLE | SysTick_CTRL_TICKINT | SysTick_CTRL_CLKSOURCE;
NVIC_SetPriority(SysTick_IRQn, 15);
NVIC_EnableIRQ(SysTick_IRQn);
}
В этом примере SysTick настроен на формирование прерываний каждую миллисекунду при тактовой частоте ядра 64 МГц. Вы же можете настроить этот таймер как вам удобно. Обратите внимание на переменные в модуле it.c
extern bool t1ms;
extern bool t100ms;
Они объявлены на самом деле внутри main.c, а здесь мы явно указываем компилятору на прямую работу с переменными соседнего модуля. Внутри main.c эти переменные объявляются со служебным словом volatile
volatile bool t1ms;
volatile bool t100ms;
Это служебное слово говорит компилятору о том, что значение этой переменной будет меняться извне и оптимизировать работу с переменной нельзя. Особенно это касается циклов.
Посмотрите на пример работы с флагом прошествия 100 мс:
while(1) { // Бесконечный главный цикл
if (t100ms) {
t100ms = false;
if (GPIOD->IDR & 0x02) GPIOD->BSRR = 0x02 << 16;
else GPIOD->BSRR = 0x02;
}
}
Здесь каждые 100 мс будет меняться состояние выхода, например так можно мигать светодиодом. Отсчитывая разные интервалы времени и создавая временные события можно построить базовую операционную систему своего проекта.
Ничего сложного, правда ли?
Но если вам есть что сказать по этому поводу, то оставьте сообщение в этой теме в Telegram (клик).
Следующий урок 5 https://ipasoft.info/index.php/articles/cmsis-stm32-urok-5-rabota-s-uart

