CMSIS STM32 Урок 4. Использование системного таймера SysTick

Помимо таймеров общего назначения, о которых я расскажу немного позже, в микроконтроллерах 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 

Tags: ,