VBCores Документация
СайтGitHub
  • VBCores
  • Hardware
    • VBCore VB32G4
    • VB STM32 программатор
    • BLDC драйвер 30A
    • DC драйвер 15A
    • Stepper драйвер 10A
    • CAN-FD - Raspberry PI
      • Настройка CAN на RPI
      • Часто возникаемые ошибки при работе с CAN/CAN FD
      • Работа с CAN FD через Python
    • Power board 30A
    • SBus-HID
    • DC-DC преобразователь
    • Ethernet - CAN-FD
    • USB-HUB
    • IMU BNO055
    • IMU BHI360
    • Т-Энкодер
  • Настройка ПО
    • Arduino IDE
      • Подготовка модуля VBCore
      • Установка среды программирования на Windows
      • Установка среды программирования на Ubuntu
        • Возможные ошибки в Ubuntu при работе с Arduino
      • Выбор платы в Arduino IDE
      • Установка базовой библиотеки
      • Структура ПО для Arduino
      • Примеры
        • Работа с CAN и CAN FD на Arduino
        • Работа с I2C
        • I2C detect
        • Датчик BNO055 / I2C
        • Датчик AS5047P / SPI
        • Датчик AS5600 / I2C
        • Работа с бесколлекторными двигателями
          • Simple FOC. Управление скоростью. Нахождение количества пар полюсов.
          • Simple FOC. Управление моментом
          • Чтение данных с датчика тока
        • Работа с коллекторным двигателем
          • Вращение DC мотором
          • Чтение угла по энкодеру. Управление DC мотором по углу
          • Чтение скорости вращения мотора по энкодеру
        • Работа с шаговым двигателем
          • Вращение шагового двигателя.
          • Контроль двигателя по интерфейсу SPI
    • STM32 CUBE IDE
      • Типовые настройки
      • Подсказки начинающим
        • Cube IDE для начинающих
        • Clock configuration
        • Таймеры - прерывания
        • Таймеры - ШИМ
        • Отладка программ
        • Коммуникации - FDCAN
        • Управление DC-мотором
        • Backup программы
  • Cyphal CAN
    • Cyphal CAN
    • PyCyphal
    • Yakut
    • Cyphal Arduino
      • Отправка и получение сообщений по cyphal
  • Работа с ROS
    • Установка Ubuntu, ROS и Arduino
    • ROS_LIB
    • Примеры
      • Publisher. Hello World!
      • Publisher with Subscriber
      • Rotation by DC motor
  • Работа с научным ПО
    • TCP Server
    • LabView
    • Matlab
  • Инструкции
    • Стенд управления двигателями
    • Переделка датчика мотор-колеса
    • Стенд мотор-колеса
    • iPower Motor
    • AS5047p OEM
  • Практические занятия
    • Коллекторный двигатель
      • Устройство коллекторного двигателя
  • RPI Display
Powered by GitBook
On this page
  • Таймеры
  • Настройка внутреннего тактирования
  • Настройка частоты таймера
  • Код прерывания и управление периодом
  1. Настройка ПО
  2. STM32 CUBE IDE
  3. Подсказки начинающим

Таймеры - прерывания

Базовая работа с таймерами, использование прерываний

PreviousClock configurationNextТаймеры - ШИМ

Last updated 1 year ago

Часто, нам надо выполнять какие-то действия с фиксированной частотой или, наоборот, немедленно реагировать на внешние события. Обе этих задачи решаются прерываниями.

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

Таймеры

Настройка внутреннего тактирования

Откроем Clock Configuration. Первое изменение, которое надо сделать, это переключить с HSI на HSE (слева) и Input frequency усттановить 12. Далее, HCLK установить в 160 МГц. Это даст всей переферии (справа), включая таймеры, базовую частоту в 160 МГц. Можно указать и другое значение, в зависимости от задачи, но здесь мы будем работать с этим.

Настройка частоты таймера

Настроим третий таймер (TIM3).

Clock Source - Internal Clock. Это "включает" таймер в базовом варианте. Prescaler - "делитель" для частоты таймера. Поделив частоту таймера на 16000, мы получаем таймер с частотой 10 КГц. Counter Period - значение, по достижению которого счетчик таймера сбрасывается.

Также в NVIC Settings поставим галочку на TIM3 global interrupt. Теперь, по достижению значения counter period, таймер не только сбрасывается, но и вызывается прерывание (код для которого будет сгенерирован в stm32g4xx_it.c). Учитывая, что частота таймера 10 КГц, а период 10000, мы получили прерывание, вызывающееся 1 раз в секунду.

Обратите внимание, что из всех числовых параметров в редакторе вычитается единица (16000-1, 10000-1). Это связано с тем, что на самом деле prescaler при значении 0, конечно, делит входящую частоту не на 0, а на 1, соответственно его реальное значение на единицу больше. А counter ведет отсчет от 0.

Код прерывания и управление периодом

Заведем в Inc/main.h переменную extern double x;, отвечающую за "время" - ось X для нашего синуса. Этот хедер включается и в main.c, и в stm32g4xx_it.c, что позволит нам использовать эту переменную в обеих файлах.

Вообще говоря, использовать глобальные переменные как разделяемое (shared) состояние в разных файлах - антипаттерн и крайне подверженная багам конструкция (как со стороны программиста, так и со стороны компилятора - например "initialization order fiasco"). Но в этом туториале для наглядности мы воспользуемся одной глобальной переменной.

Инициализируем x в main.c:

/* USER CODE BEGIN PV */
double x = 0;
/* USER CODE END PV */

Запустим прерывания внутри блока USER CODE в main, после всех инициализаций но до бесконечного цикла:

HAL_TIM_Base_Start_IT(&htim3);

И в главном цикле будем увеличивать его значение со временем в диапазоне от 0 до 2:

/* USER CODE BEGIN WHILE */
while (1) {
    HAL_Delay(1);
    if (x < 2) x += 0.003;
    else x = 0.0;
/* USER CODE END WHILE */

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

  1. Переключать состояние диода. HAL_GPIO_TogglePin(LED1_GPIO_Port, LED1_Pin);

  2. Менять значение counter period таймера по синусоиде, чтобы частота переключений плавно менялась. __HAL_TIM_SET_AUTORELOAD(&htim3, (sin(3.14*x)+1.2)*500);. Мы пользуемся третьим таймером, x меняется от 0 до 2, значение синуса нам надо немного "поднять" над 0, поэтому +1.2, и *500, так как получившееся до этого значение лежит только в пределе [0.2, 2.2]

Приведем код функции прерывания целиком:

void TIM3_IRQHandler(void)
{
  /* USER CODE BEGIN TIM3_IRQn 0 */
  HAL_GPIO_TogglePin(LED1_GPIO_Port, LED1_Pin);
  __HAL_TIM_SET_AUTORELOAD(&htim3, (sin(3.14*x)+1.2)*500);
  /* USER CODE END TIM3_IRQn 0 */
  HAL_TIM_IRQHandler(&htim3);
  /* USER CODE BEGIN TIM3_IRQn 1 */

  /* USER CODE END TIM3_IRQn 1 */
}

Все! Залив этот код на контроллер, мы получим мерцающий по синусоиде светодиод.