Урок 16. Таймеры STM32 в режиме счетчиков. Генерация циклических прерываний от таймеров.

Уроки STM32

В уроке познакомимся с таймерами микроконтроллера, научимся конфигурировать их в режиме счетчика и организовывать циклические прерывания.

Предыдущий урок     Список уроков     Следующий урок

В предыдущем уроке я рассказывал о выполнении задач параллельными процессами. Для реализации такого способа необходимо формировать циклические прерывания с заданным периодом. Опять же в предыдущем уроке было сказано, что логичнее и проще это делать с помощью аппаратных таймеров.

 

В этом уроке мы будем рассматривать таймеры в качестве именно такого функционального применения. Т.е. будем использовать их для генерации циклических прерываний.

 

Таймеры STM32.

У нашего микроконтроллера STM32F103C8T6 есть 4 таймера:

  • TIM1 – расширенный таймер, ориентированный на управление электродвигателем.
  • TIM2 … TIM4 – таймеры общего назначения.

Все таймеры имеют одинаковую архитектуру. Расширенный таймер отличается наличием дополнительных аппаратных узлов для формирования противофазных сигналов ШИМ. В результате его можно конфигурировать на работу в режиме 6-канального ШИМ и управлять им тремя полумостовыми усилителями мощности.

Но сейчас нас это не интересует. Для нашей задачи - формирования циклических прерываний, все таймеры имеют одинаковую архитектуру.

Таймеры STM32 - многофункциональные устройства. С помощью каждого из них можно реализовать:

  • Счетчик импульсов, а значит и времени с автоматической перезагрузкой.
  • Захват входного сигнала (4 канала).
    • Обнаружение фронта входного сигнала, запоминание времени, генерация события.
    • Измерение временных параметров входного ШИМ-сигнала: периода и длительности импульсов.
    • Интерфейс энкодера. Измерение параметров импульсов энкодера.
  • Сравнение кодов таймера (4 канала).
    • Генерация события по совпадению кода таймера с заданным значением.
    • Формирование ШИМ-сигнала.
    • Формирование одиночных импульсов, режим одновибратора.

У таймеров большой выбор источников тактирования, есть предделители, обеспечивается цифровая фильтрация входных сигналов, возможна синхронизация между собой и много еще чего.

Но сейчас нас интересует исключительно режим счетчика с перезагрузкой. Именно в этом режиме удобнее всего формировать циклические прерывания.

Функциональная схема таймера достаточно сложная. Я выделил только необходимую нам часть.

Функциональная схема TIM1

Собственно отсчет импульсов или времени происходит на 16-ти разрядном счетчике CNT. Когда код счетчика достигает значения регистра перезагрузки, счетчик сбрасывается в 0. Таким образом, счетчик считает по циклу от 0 до значения регистра перезагрузки.

Частота сигнала тактирования таймера может быть уменьшена с помощью 16-ти разрядного предделителя PSC.

Перезагрузка счетчика формирует событие (прерывание). Частота его появления также может быть уменьшена счетчиком повторов (8 разрядов). Коэффициент деления задается в регистре повторов.

Код счетчика используется другими узлами таймера, например, для формирования ШИМ. Но об этом в других уроках.

В качестве источника тактирования могут быть выбраны:

  • Внутренние синхросигналы шин APB1 иAPB2, про которые мы говорили в уроке 5 (система тактирования микроконтроллера).
    • Для таймера TIM1 используется синхросигнал шины APB2;
    • Для таймеровTIM2- TIM4 используется синхросигнал шины APB1.
  • Внешнее тактирование, режим 1. Используется выходной сигнал другого таймера или внешний сигнал входов захвата.
  • Внешнее тактирование, режим 2.  Используется вывод микроконтроллера ETR.
  • Особый режим синхронизации – интерфейс подключения энкодера.

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

 

Режимы счета таймера.

При использовании таймера в качестве счетчика импульсов можно выбрать один из режимов:

  • прямой счет;
  • обратный счет;
  • двунаправленный.

При прямом счете содержимое счетчика с каждым импульсом тактирования увеличивается на 1. Когда оно достигает значения регистра перезагрузки, то счетчик сбрасывается. Таким образом,таймер считает по циклу от 0 до значения перезагрузки. В момент перезагрузки формируется прерывание.

В режиме обратного (реверсивного) счета с каждым входным импульсом содержимое счетчика уменьшается на 1. При достижении 0 в счетчик загружается значение регистра перезагрузки и реверсивный счет продолжается. Таймер считает по циклу от значения перезагрузки до 0. В момент перезагрузки формируется прерывание.

Двунаправленный режим означает, что счетчик считает в прямом направлении от 0 до значения перезагрузки, а затем переходит в реверсивный режим и счет ведется до 0. При изменении направления счета и сбросе генерируется прерывание.

 

Установка конфигурации таймера с помощью STM32CubeMX.

Давайте научимся конфигурировать таймеры через STM32CubeMX. Заодно в строгой форме перечислим регистры, задающие режимы таймера и  выясним, что конкретно в них загружать.

Создадим проект Lesson16_1. Настроим конфигурацию системы тактирования. Обратим внимание на то, что частота тактирования таймеров на шинах APB1 и APB2 задана 72 мГц.

STM32CubeMX

Настроим выводы:

  • PC13 – активный выход;
  • PB13 – активный выход;
  • PB12 – вход с подтягивающим резистором.

Установка выводов в STM32CubeMX

Теперь будем конфигурировать таймер 1. В нашем микроконтроллере он самый многофункциональный.

Открываем вкладку Timers ->TIM1.

Выбираем в качестве источника тактирования внутреннее тактирование: Clock Source -> Internal Clock.

Выбор источника тактирования

Ниже появилось поле Parameter Settings.

Установка параметров

Давайте подробно разберем, что в нем.

Prescaler (PSC).

Это регистр предделителя. Предделитель делит частоту тактирования таймера, поступающую на основной счетчик. По сути, он, вместе с входной частотой,  определяет разрешающую способность таймера.

Счетчик предделителя считает входные импульсы от 0 до значения этого регистра. При равенстве кода счетчика и регистра счетчик сбрасывается и начинает считать заново. В момент сброса формируется импульс тактирования основного счетчика таймера. Таким образом, значение регистра предделителя определяет коэффициент деления частоты входного сигнала.

Счетчик и регистр предделителя 16-ти разрядные. Т.е. максимальный коэффициент деления 65536.

Надо помнить, что реальный коэффициент деления на 1 больше, чем значение регистра предделителя. Например:

Значение регистра предделителя Коэффициент деления
0 1
999 1000
65535 (максимальное значение) 65536

Регистр предделителя имеет буферный регистр. Поэтому его значение можно устанавливать в любой момент. Реальное изменение коэффициента деления произойдет при перезагрузке буферного регистра в момент перезагрузки основного счетчика таймера.

Counter mode.

Режим счетчика, определяет в какую сторону считать.

counter mode

  • Up – прямой счет.
  • Down – реверсивный счет.
  • Center Aligned mode 1 – двунаправленный счет, прерывание генерируется в момент, когда счетчик считает в обратную сторону и доходит до 0.
  • Center Aligned mode 2 – двунаправленный счет, прерывание генерируется, когда счетчик считает в прямом направлении и достигает значения перезагрузки.
  • Center Aligned mode 3 – двунаправленный счет, прерывание генерируется, в обоих случаях - при достижении 0 и значения перезагрузки.

Counter Period (Auto Reload Register).

Регистр перезагрузки. Его значение задает период работы таймера. Конечно, на время периода влияет еще режим счета.

Счетчик 16-ти разрядный. Значит, для однонаправленного счета период может длиться от 1 до 65536 длительностей импульсов предделителя. Реальная длительность периода на 1 больше значения регистра перезагрузки. Все как для регистра предделителя.

Internal Clock Division (CKD).

Делитель входной частоты для внутренних нужд таймера.

Internal Clock Division (CKD)

Частота используется при фильтрации внешних сигналов, формировании “мертвого времени” ШИМ и т.п. Сейчас это нам не интересно.

Repetition Counter (RCR).

Регистр счетчика повторов. Присутствует не во всех таймерах. Счетчик повторов считает импульсы событий на выходе таймера и при достижении значения регистра повторов сбрасывается и формирует реальное событие. Т.е. он делит частоту генерации событий (прерываний) таймера.

Счетчик 8-ми разрядный. Коэффициент деления на 1 больше значения регистра повторов и может быть в диапазоне 1 - 256. Регистр буферизирован, можно изменять его значения в любой момент.

Auto-reload preload.

Регистр перезагрузки буферизирован. Разработчики микроконтроллера предоставляют программисту выбор - при записи значения перезагрузки передавать его в регистр моментально или дождаться крайнего состояния счетчика.

Управляет режимом перезагрузки специальный бит, а в STM32CubeMX выбор делается в выпадающем меню.

Auto-reload preload

Вкладка NVIC Settings позволяет выбрать нужный тип прерывания, связанного с таймером.

Выбор прерывания

 

Пример конфигурации таймера и реализации программы.

Сделаем практическую задачу. Установим конфигурацию таймера 1, обеспечивающую циклические прерывания с периодом 0,5 секунд. В обработчике прерывания будем инвертировать состояние светодиода. В результате получим мигающий светодиод, но с использованием таймера и прерывания.

Частота тактирования у нас 72 мГц. Превратим ее с помощью предделителя в круглое значение.

Например, если задать 720 – 1 = 719, то частота после предделителя будет 72 000 000 / 720 = 100 000 Гц, или период 10 мкс.

Если в регистр перезагрузки задать значение 50 000, то получим требуемый период 0,5 секунд.

Конфигурация проекта

Во вкладке NVIC Settings выберем прерывание по перезагрузке счетчика.

Выбор прерывания

Создаем проект и открываем его в Atollic TrueStudio.

В папке Src проекта создан файл stm32f1xx_it.c. Он существовал и во всех предыдущих проектах. Просто мы на него до времени не обращали внимания.

Это файл обработчиков прерываний. Хороший стиль размещать функции обработки прерываний в нем.

В самом конце файла появилась функция:

void TIM1_UP_IRQHandler(void) {

    /* USER CODE BEGIN TIM1_UP_IRQn 0 */
    /* USER CODE END TIM1_UP_IRQn 0 */

    HAL_TIM_IRQHandler(&htim1);

    /* USER CODE BEGIN TIM1_UP_IRQn 1 */
    /* USER CODE END TIM1_UP_IRQn 1 */
}

Это и есть обработчик прерывания таймера 1. Код, который мы поместим в функцию, будет вызываться с периодом 0,5 секунд.

Вызовем в обработчике прерывания функции инверсии состояния для обоих светодиодов.

void TIM1_UP_IRQHandler(void) {

    /* USER CODE BEGIN TIM1_UP_IRQn 0 */

    HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);
    HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_13);

Мы установили конфигурацию таймера, но не запустили его. Сделаем это HAL-функцией в файле main.c.

/* Initialize all configured peripherals */

MX_GPIO_Init();
MX_TIM1_Init();

/* USER CODE BEGIN 2 */

HAL_TIM_Base_Start_IT(&htim1); // запуск таймера

Функция запускает таймер в режиме генерации прерываний.

Все. Компилируем, загружаем, проверяем. Оба светодиода мигают раз в секунду.

Полностью проект можно загрузить по ссылке:

  Зарегистрируйтесь и оплатите. Всего 25 руб. в месяц за доступ ко всем ресурсам сайта!  

Основной цикл у нас пустой. Программа просто крутится в нем.

while (1) {

    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
}

По отношению к нему светодиоды мигают в фоновом режиме, сами по себе. Если мы будем выполнять в цикле какие-либо действия, это никак не скажется на равномерном мигании светодиодов. Единственное условие – надолго не запрещать прерывания.

 

В следующем уроке будем разрабатывать программу, обрабатывающую сигнал кнопки параллельным процессом. Научимся связывать переменные разных файлов одной программы. Разберемся в специфике использования функций обработки прерываний.

Предыдущий урок     Список уроков     Следующий урок

0

Автор публикации

не в сети 7 дней

Эдуард

56
Комментарии: 1319Публикации: 148Регистрация: 13-12-2015

2 комментария на «Урок 16. Таймеры STM32 в режиме счетчиков. Генерация циклических прерываний от таймеров.»

  1. Большое Вам спасибо за ваш труд.
    У меня уточнение, для получения периода 0,5 секунды на мой взгляд в регистр перезагрузки необходимо задать значение 49999 (50000 — 1). Прав ли я?

    0

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *