сайт для палких паяльників

Системный таймер STM32 SysTick

У микроконтроллеров STM32 есть системный таймер SysTick. Это простейший вычитающий счетчик с автоматической загрузкой начального значения при достижении счетчиком 0. Каждый раз, когда счетчик достигает нуля вызывается прерывание. Для обработки прерывания потребуется описать обработчик SysTick_Handler. Вот и все что умеет делать этот таймер. Тем не менее он достаточно часто применяется для решения различных задач. В этой статье мы задействуем его для реализации простой задержки.

Инициализация таймера выполняется одной строкой:

SysTick_Config(SystemCoreClock/1000);

Здесь задается частота, с которой таймер будет вызывать прерывание, и соответственно, вызывать SysTick_Handler. В данном случае мы задаем 1000 герц. Т.е. прерывание будет генерироваться 1000 раз в секунду. Далее у нас объявлена переменная sysTickCount, в которую мы будем загружать количество миллисекунд, а обработчик прерывания таймера будет уменьшать значение переменной на 1 каждую миллисекунду. Нам остается только подождать пока значение sysTickCount не будет равнятся 0.

Пример функций задержки для STM32 с использованием SysTick:

stm32f10x.h:

#ifndef SYSTICKDELAY_H_
#define SYSTICKDELAY_H_

void sysTickDalayInit();
void sysTickDalay(uint32_t nTime);
void sysTickSet(uint32_t nTime);
uint32_t sysTickGet();

#endif

stm32f10x.c:

#include "stm32f10x.h"

static volatile uint32_t sysTickCount = 0;

void SysTick_Handler()
{
  if (sysTickCount != 0) {
    sysTickCount--;
  }
}

void sysTickDalayInit() {
  SysTick_Config(SystemCoreClock/1000);
}

void sysTickDalay(uint32_t nTime)
{
  sysTickCount = nTime;
  while(sysTickCount != 0);
}

void sysTickSet(uint32_t nTime)
{
  sysTickCount = nTime;
}

uint32_t sysTickGet()
{
  return sysTickCount;
}

В данном примере предложено два способа:

1. использовать функцию sysTickDalay. В этом случае микроконтроллер будет просто ждать. Такая задержка годится если при включении Вашего устройства требуется сделать небольшую паузу. Например, Вы вывели на экран заставку или приветствие и желаете чтобы пользователь успел насладиться ее красотой. А микроконтроллеру в это время решительно нечего делать.

2. использовать две функции sysTickSet и sysTickGet. sysTickSet задает значение переменной, которая определяет время задержки, а sysTickGet возвращает ее текущее значение.
Например, микроконтроллер выполняет в цикле какую то процедуру, но периодически, например 1 раз в секунду, нужно выполнять какие-то дополнительные операции. Сначала задаем необходимое время, например одну секунду sysTickSet(1000); а затем в цикле опрашиваем состояние переменной:

if (sysTickGet() == 0) {
  // Что-то, что надо делать раз в секунду
  sysTickSet(1000);
}

Пример мигания светодиодом с применением задержки с помощью системного таймера SysTick:

#include "stm32f10x.h"

#include "sysclk.h"
#include "systickdelay.h"

int main(void)
{
	uint32_t i;

	// Set clock
	SetSysClockTo72();

	// SysTick Init
	sysTickDalayInit();

	GPIO_InitTypeDef  GPIO_InitStructure;

	/* Initialize LED which connected to PC13 */
	// Enable PORTC Clock
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
	/* Configure the GPIO_LED pin */
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
	GPIO_Init(GPIOC, &GPIO_InitStructure);

    /* Toggle LED which connected to PC13*/
	for (i = 0; i < 10; i++) {
		GPIOC->ODR ^= GPIO_Pin_13;
    	sysTickDalay(500); // Delay & wait
	}

	while (1) {
		// do something
		// ..

		if (sysTickGet() == 0) {
			sysTickSet(1000);
			GPIOC->ODR ^= GPIO_Pin_13;
		}
	}
}

Разумеется, точность задержки в предложенном примере достаточна только для помигать светодиодом и прочих подобных задач. Давайте предположим, что мы хотим получить задержку в 1 миллисекунду. Поскольку функция sysTickSet может быть вызвана буквально перед тем как таймер вызовет прерывание, у нас может случится, что задержки вообще не будет. Т.е. если мы сделаем так: sysTickSet(1); то задержки в 1 миллисекунду мы практически никогда не получим, она всегда будет разной и меньше 1 миллисекунды.

Во второй части примера на точность задержки дополнительно влияет загрузка контроллера. Точность сложно гарантировать, поскольку нам не известно на сколько загружен контроллер и когда у него будет время “обратить внимание” на состояние переменной. Поэтому эту реализацию можно применять когда не требуется супер точность.

Существуют методы, которые позволяют получить более точную задержку, но в этой статье они рассматриваться не будут.

Вы так же можете использовать таймер SysTick для выполнения периодических операций почти как обычный таймер. При этом периодически выполняемые операции вынести в обработчик прерывания SysTick_Handler(). Разумеется, в этом случае ранее описанных проблемы с точностью нет.

Неизбежно возникает вопрос: какой максимально возможный период между прерываниями можно установить для SysTick? Минимальная возможная частота рассчитывается по формуле: 2^24/SystemCoreClock. Т.е. Когда мы инициализируем таймер функцией SysTick_Config(), параметр, который мы ей передаем не должен быть больше 24 битного числа. Если у нас микроконтроллер работает на частоте 72Мгц, тогда 16777216/72000000 = 0.233 секунды. Если микроконтроллер работает на частоте 1Мгц, тогда 16777216/1000000 = 16.777 секунды.

Скачать приер для System Workbench for STM32: STM32F103/Example_SysTick

Успехов.

Смотри также:

2 комментария: STM32. SysTick

  • Dima говорить:

    Здравствуйте.
    Вот здесь – http://www.avislab.com/blog/stm32-exti_ru/ Вы обещали сделать описание событий (Events), Вы его ещё не делали?
    И ещё вопрос, можно ли общаться с Вами в Телеграме?

    И конечно же спасибо за исчерпывающие статьи!

    • andre говорить:

      Здравствуйте. Спасибо за замечание.
      Видимо, про Events я совсем забыл. Постараюсь заполнить этот пробел.
      В Телеграме меня нет, лучше всего пишите на andre@avislab.com

Залишити відповідь

Ваша e-mail адреса не оприлюднюватиметься. Обов’язкові поля позначені *

 
Translate
Архіви

© 2011-2018 Андрій Корягін, Кременчук - Київ, Україна