- •Оглавление
- •Предисловие
- •Почему я написал книгу?
- •Для кого эта книга?
- •Как использовать эту книгу?
- •Как организована книга?
- •Об авторе
- •Ошибки и предложения
- •Поддержка книги
- •Как помочь автору
- •Отказ от авторского права
- •Благодарность за участие
- •Перевод
- •Благодарности
- •I Введение
- •1. Введение в ассортимент микроконтроллеров STM32
- •1.1. Введение в процессоры на базе ARM
- •1.1.1. Cortex и процессоры на базе Cortex-M
- •1.1.1.10. Внедренные функции Cortex-M в ассортименте STM32
- •1.2. Введение в микроконтроллеры STM32
- •1.2.1. Преимущества ассортимента STM32….
- •1.2.2. ….И его недостатки
- •1.3. Краткий обзор подсемейств STM32
- •1.3.1. Серия F0
- •1.3.2. Серия F1
- •1.3.3. Серия F2
- •1.3.4. Серия F3
- •1.3.5. Серия F4
- •1.3.6. Серия F7
- •1.3.7. Серия H7
- •1.3.8. Серия L0
- •1.3.9. Серия L1
- •1.3.10. Серия L4
- •1.3.11. Серия L4+
- •1.3.12. Серия STM32WB
- •1.3.13. Как правильно выбрать для себя микроконтроллер?
- •1.4. Отладочная плата Nucleo
- •2. Установка инструментария
- •2.1. Почему выбирают Eclipse/GCC в качестве инструментария для STM32
- •2.1.1. Два слова о Eclipse…
- •2.2. Windows – Установка инструментария
- •2.2.1. Windows – Установка Eclipse
- •2.2.2. Windows – Установка плагинов Eclipse
- •2.2.3. Windows – Установка GCC ARM Embedded
- •2.2.4. Windows – Установка инструментов сборки
- •2.2.5. Windows – Установка OpenOCD
- •2.2.6. Windows – Установка инструментов ST и драйверов
- •2.3. Linux – Установка инструментария
- •2.3.2. Linux – Установка Java
- •2.3.3. Linux – Установка Eclipse
- •2.3.4. Linux – Установка плагинов Eclipse
- •2.3.5. Linux – Установка GCC ARM Embedded
- •2.3.6. Linux – Установка драйверов Nucleo
- •2.3.7. Linux – Установка OpenOCD
- •2.3.8. Linux – Установка инструментов ST
- •2.4. Mac – Установка инструментария
- •2.4.1. Mac – Установка Eclipse
- •2.4.2. Mac – Установка плагинов Eclipse
- •2.4.3. Mac – Установка GCC ARM Embedded
- •2.4.4. Mac – Установка драйверов Nucleo
- •2.4.5. Mac – Установка OpenOCD
- •2.4.6. Mac – Установка инструментов ST
- •3. Hello, Nucleo!
- •3.1. Прикоснитесь к Eclipse IDE
- •3.2. Создание проекта
- •3.3. Подключение Nucleo к ПК
- •3.5. Изучение сгенерированного кода
- •4. Инструмент STM32CubeMX
- •4.1. Введение в инструмент CubeMX
- •4.1.1. Представление Pinout
- •4.1.2. Представление Clock Configuration
- •4.1.3. Представление Configuration
- •4.1.4. Представление Power Consumption Calculator
- •4.2. Генерация проекта
- •4.2.1. Генерация проекта Си при помощи CubeMX
- •4.2.2. Создание проекта Eclipse
- •4.2.3. Ручное импортирование сгенерированных файлов в проект Eclipse
- •4.3. Изучение сгенерированного кода приложения
- •4.3.1. Добавим что-нибудь полезное в микропрограмму
- •4.4. Загрузка исходного кода примеров книги
- •5. Введение в отладку
- •5.1. Начало работы с OpenOCD
- •5.1.1. Запуск OpenOCD
- •5.1.2. Подключение к OpenOCD Telnet Console
- •5.1.3. Настройка Eclipse
- •5.1.4. Отладка в Eclipse
- •5.2. Полухостинг ARM
- •5.2.1. Включение полухостинга в новом проекте
- •5.2.2. Включение полуохостинга в существующем проекте
- •5.2.3. Недостатки полухостинга
- •5.2.4. Как работает полухостинг
- •II Погружение в HAL
- •6. Управление GPIO
- •6.2. Конфигурация GPIO
- •6.2.1. Режимы работы GPIO
- •6.2.2. Режим альтернативной функции GPIO
- •6.2.3. Понятие скорости GPIO
- •6.3. Управление GPIO
- •6.4. Деинициализация GPIO
- •7. Обработка прерываний
- •7.1. Контроллер NVIC
- •7.1.1. Таблица векторов в STM32
- •7.2. Разрешение прерываний
- •7.2.1. Линии запроса внешних прерываний и контроллер NVIC
- •7.2.2. Разрешение прерываний в CubeMX
- •7.3. Жизненный цикл прерываний
- •7.4. Уровни приоритета прерываний
- •7.4.1. Cortex-M0/0+
- •7.4.2. Cortex-M3/4/7
- •7.4.3. Установка уровня прерываний в CubeMX
- •7.5. Реентерабельность прерываний
- •8. Универсальные асинхронные последовательные средства связи
- •8.1. Введение в UART и USART
- •8.2. Инициализация UART
- •8.3. UART-связь в режиме опроса
- •8.3.1. Установка консоли последовательного порта в Windows
- •8.3.2. Установка консоли последовательного порта в Linux и MacOS X
- •8.4. UART-связь в режиме прерываний
- •8.5. Обработка ошибок
- •8.6. Перенаправление ввода-вывода
- •9. Управление DMA
- •9.1. Введение в DMA
- •9.1.1. Необходимость DMA и роль внутренних шин
- •9.1.2. Контроллер DMA
- •9.2. Модуль HAL_DMA
- •9.2.1. DMA_HandleTypeDef в HAL для F0/F1/F3/L0/L1/L4
- •9.2.2. DMA_HandleTypeDef в HAL для F2/F4/F7
- •9.2.3. DMA_HandleTypeDef в HAL для L0/L4
- •9.2.4. Как выполнять передачи в режиме опроса
- •9.2.5. Как выполнять передачи в режиме прерываний
- •9.2.8. Разнообразные функции модулей HAL_DMA и HAL_DMA_Ex
- •9.3. Использование CubeMX для конфигурации запросов к DMA
- •10. Схема тактирования
- •10.1. Распределение тактового сигнала
- •10.1.1. Обзор схемы тактирования STM32
- •10.1.1.1. Многочастотный внутренний RC-генератор в семействах STM32L
- •10.1.3.1. Подача тактового сигнала от высокочастотного генератора
- •10.1.3.2. Подача тактового сигнала от 32кГц генератора
- •10.2. Обзор модуля HAL_RCC
- •10.2.1. Вычисление тактовой частоты во время выполнения
- •10.2.2. Разрешение Выхода синхронизации
- •10.2.3. Разрешение Системы защиты тактирования
- •10.3. Калибровка HSI-генератора
- •11. Таймеры
- •11.1. Введение в таймеры
- •11.1.1. Категории таймеров в микроконтроллере STM32
- •11.1.2. Доступность таймеров в ассортименте STM32
- •11.2. Базовые таймеры
- •11.2.1. Использование таймеров в режиме прерываний
- •11.2.2. Использование таймеров в режиме опроса
- •11.2.3. Использование таймеров в режиме DMA
- •11.2.4. Остановка таймера
- •11.3. Таймеры общего назначения
- •11.3.1.1. Режим внешнего тактирования 2
- •11.3.1.2. Режим внешнего тактирования 1
- •11.3.2. Режимы синхронизации ведущего/ведомого таймеров
- •11.3.2.1. Разрешение прерываний, относящихся к триггерной цепи
- •11.3.2.2. Использование CubeMX для конфигурации синхронизации ведущего/ведомого устройств
- •11.3.3. Программная генерация связанных с таймером событий
- •11.3.4. Режимы отсчета
- •11.3.5. Режим захвата входного сигнала
- •11.3.5.1. Использование CubeMX для конфигурации режима захвата входного сигнала
- •11.3.6. Режим сравнения выходного сигнала
- •11.3.6.1. Использование CubeMX для конфигурации режима сравнения выходного сигнала
- •11.3.7. Генерация широтно-импульсного сигнала
- •11.3.7.1. Генерация синусоидального сигнала при помощи ШИМ
- •11.3.7.2. Использование CubeMX для конфигурации режима ШИМ
- •11.3.8. Одноимпульсный режим
- •11.3.8.1. Использование CubeMX для конфигурации одноимпульсного режима
- •11.3.9. Режим энкодера
- •11.3.9.1. Использование CubeMX для конфигурации режима энкодера
- •11.3.10.1. Режим датчика Холла
- •11.3.10.2. Комбинированный режим трехфазной ШИМ и другие функции управления двигателем
- •11.3.10.3. Вход сброса таймера и блокировка регистров таймера
- •11.3.10.4. Предварительная загрузка регистра автоперезагрузки
- •11.3.11. Отладка и таймеры
- •11.4. Системный таймер SysTick
- •12. Аналого-цифровое преобразование
- •12.1. Введение в АЦП последовательного приближения
- •12.2. Модуль HAL_ADC
- •12.2.1. Режимы преобразования
- •12.2.1.1. Режим однократного преобразования одного канала
- •12.2.1.2. Режим сканирования с однократным преобразованием
- •12.2.1.3. Режим непрерывного преобразования одного канала
- •12.2.1.4. Режим сканирования с непрерывным преобразованием
- •12.2.1.5. Режим преобразования инжектированных каналов
- •12.2.1.6. Парный режим
- •12.2.2. Выбор канала
- •12.2.3. Разрядность АЦП и скорость преобразования
- •12.2.4. Аналого-цифровые преобразования в режиме опроса
- •12.2.6. Аналого-цифровые преобразования в режиме DMA
- •12.2.6.1. Многократное преобразование одного канала в режиме DMA
- •12.2.6.3. Непрерывные преобразования в режиме DMA
- •12.2.7. Обработка ошибок
- •12.2.8. Преобразования, управляемые таймером
- •12.2.9. Преобразования, управляемые внешними событиями
- •12.2.10. Калибровка АЦП
- •12.3. Использование CubeMX для конфигурации АЦП
- •13.1. Введение в периферийное устройство ЦАП
- •13.2. Модуль HAL_DAC
- •13.2.1. Управление ЦАП вручную
- •13.2.2. Управление ЦАП в режиме DMA с использованием таймера
- •13.2.3. Генерация треугольного сигнала
- •13.2.4. Генерация шумового сигнала
- •14.1. Введение в спецификацию I²C
- •14.1.1. Протокол I²C
- •14.1.1.1. START- и STOP-условия
- •14.1.1.2. Формат байта
- •14.1.1.3. Кадр адреса
- •14.1.1.4. Биты «Подтверждено» (ACK) и «Не подтверждено» (NACK)
- •14.1.1.5. Кадры данных
- •14.1.1.6. Комбинированные транзакции
- •14.1.1.7. Удержание синхросигнала
- •14.1.2. Наличие периферийных устройств I²C в микроконтроллерах STM32
- •14.2. Модуль HAL_I2C
- •14.2.1.1. Операции I/O MEM
- •14.2.1.2. Комбинированные транзакции
- •14.3. Использование CubeMX для конфигурации периферийного устройства I²C
- •15.1. Введение в спецификацию SPI
- •15.1.1. Полярность и фаза тактового сигнала
- •15.1.2. Управление сигналом Slave Select
- •15.1.3. Режим TI периферийного устройства SPI
- •15.1.4. Наличие периферийных устройств SPI в микроконтроллерах STM32
- •15.2. Модуль HAL_SPI
- •15.2.1. Обмен сообщениями с использованием периферийного устройства SPI
- •15.2.2. Максимальная частота передачи, достижимая при использовании CubeHAL
- •15.3. Использование CubeMX для конфигурации периферийного устройства SPI
- •16. Циклический контроль избыточности
- •16.1. Введение в расчет CRC
- •16.1.1. Расчет CRC в микроконтроллерах STM32F1/F2/F4/L1
- •16.2. Модуль HAL_CRC
- •17. Независимый и оконный сторожевые таймеры
- •17.1. Независимый сторожевой таймер
- •17.1.1. Использование CubeHAL для программирования таймера IWDG
- •17.2. Системный оконный сторожевой таймер
- •17.2.1. Использование CubeHAL для программирования таймера WWDG
- •17.3. Отслеживание системного сброса, вызванного сторожевым таймером
- •17.4. Заморозка сторожевых таймеров во время сеанса отладки
- •17.5. Выбор сторожевого таймера, подходящего для вашего приложения
- •18. Часы реального времени
- •18.1. Введение в периферийное устройство RTC
- •18.2. Модуль HAL_RTC
- •18.2.1. Установка и получение текущей даты/времени
- •18.2.1.1. Правильный способ чтения значений даты/времени
- •18.2.2. Конфигурирование будильников
- •18.2.3. Блок периодического пробуждения
- •18.2.5. Калибровка RTC
- •18.2.5.1. Грубая калибровка RTC
- •18.2.5.2. Тонкая калибровка RTC
- •18.2.5.3. Обнаружение опорного тактового сигнала
- •18.3. Использование резервной SRAM
- •III Дополнительные темы
- •19. Управление питанием
- •19.1. Управление питанием в микроконтроллерах на базе Cortex-M
- •19.2. Как микроконтроллеры Cortex-M управляют рабочим и спящим режимами
- •19.2.1. Переход в/выход из спящих режимов
- •19.2.1.1. «Спящий режим по выходу»
- •19.3. Управление питанием в микроконтроллерах STM32F
- •19.3.1. Источники питания
- •19.3.2. Режимы питания
- •19.3.2.1. Рабочий режим
- •19.3.2.2. Спящий режим
- •19.3.2.3. Режим останова
- •19.3.2.4. Режим ожидания
- •19.3.2.5. Пример работы в режимах пониженного энергопотребления
- •19.4. Управление питанием в микроконтроллерах STM32L
- •19.4.1. Источники питания
- •19.4.2. Режимы питания
- •19.4.2.1. Рабочие режимы
- •19.4.2.2. Спящие режимы
- •19.4.2.2.1. Режим пакетного сбора данных
- •19.4.2.3. Режимы останова
- •19.4.2.4. Режимы ожидания
- •19.4.2.5. Режим выключенного состояния
- •19.4.3. Переходы между режимами питания
- •19.4.4. Периферийные устройства с пониженным энергопотреблением
- •19.4.4.1. LPUART
- •19.4.4.2. LPTIM
- •19.5. Инспекторы источников питания
- •19.6. Отладка в режимах пониженного энергопотребления
- •19.7. Использование калькулятора энергопотребления CubeMX
- •20. Организация памяти
- •20.1. Модель организации памяти в STM32
- •20.1.1. Основы процессов компиляции и компоновки
- •20.2.1. Исследование бинарного ELF-файла
- •20.2.2. Инициализация секций .data и .bss
- •20.2.2.1. Пара слов о секции COMMON
- •20.2.3. Секция .rodata
- •20.2.4. Области Стека и Кучи
- •20.2.5. Проверка размера Кучи и Стека на этапе компиляции
- •20.2.6. Различия с файлами скриптов инструментария
- •20.3. Как использовать CCM-память
- •20.3.1. Перемещение таблицы векторов в CCM-память
- •20.4.1. Программирование MPU с использованием CubeHAL
- •21. Управление Flash-памятью
- •21.1. Введение во Flash-память STM32
- •21.2. Модуль HAL_FLASH
- •21.2.1. Разблокировка Flash-памяти
- •21.2.2. Стирание Flash-памяти
- •21.2.3. Программирование Flash-памяти
- •21.3. Байты конфигурации
- •21.3.1. Защита от чтения Flash-памяти
- •21.4. Дополнительные памяти OTP и EEPROM
- •21.5. Задержка чтения Flash-памяти и ускоритель ART™ Accelerator
- •21.5.1. Роль TCM-памятей в микроконтроллерах STM32F7
- •22. Процесс начальной загрузки
- •22.1.1. Программное физическое перераспределение памяти
- •22.1.2. Перемещение таблицы векторов
- •22.1.3. Запуск микропрограммы из SRAM с помощью инструментария GNU MCU Eclipse
- •22.2. Встроенный загрузчик
- •22.2.1. Запуск загрузчика из встроенного программного обеспечения
- •22.2.2. Последовательность начальной загрузки в инструментарии GNU MCU Eclipse
- •22.3. Разработка пользовательского загрузчика
- •22.3.2. Как использовать инструмент flasher.py
- •23. Запуск FreeRTOS
- •23.1. Введение в концепции, лежащие в основе ОСРВ
- •23.2.1. Структура файлов с исходным кодом FreeRTOS
- •23.2.1.2. Как импортировать FreeRTOS с использованием CubeMX и CubeMXImporter
- •23.3. Управление потоками
- •23.3.1. Состояния потоков
- •23.3.2. Приоритеты потоков и алгоритмы планирования
- •23.3.3. Добровольное освобождение от управления
- •23.3.4. Холостой поток idle
- •23.4. Выделение памяти и управление ею
- •23.4.1. Модель динамического выделения памяти
- •23.4.1.1. heap_1.c
- •23.4.1.2. heap_2.c
- •23.4.1.3. heap_3.c
- •23.4.1.4. heap_4.c
- •23.4.1.5. heap_5.c
- •23.4.2. Модель статического выделения памяти
- •23.4.3. Пулы памяти
- •23.4.4. Обнаружение переполнения стека
- •23.5. Примитивы синхронизации
- •23.5.1. Очереди сообщений
- •23.5.2. Cемафоры
- •23.5.3. Сигналы потоков
- •23.6. Управление ресурсами и взаимное исключение
- •23.6.1. Мьютексы
- •23.6.2. Критические секции
- •23.6.3. Обработка прерываний совместно с ОСРВ
- •23.7. Программные таймеры
- •23.7.1. Как FreeRTOS управляет таймерами
- •23.8. Пример из практики: Управление энергосбережением с ОСРВ
- •23.8.1. Перехват холостого потока idle
- •23.8.2. Бестиковый режим во FreeRTOS
- •23.9. Возможности отладки
- •23.9.1. Макрос configASSERT()
- •23.9.2. Статистика среды выполнения и информация о состоянии потоков
- •23.10. Альтернативы FreeRTOS
- •23.10.1. ChibiOS
- •23.10.2. ОС Contiki
- •23.10.3. OpenRTOS
- •24. Продвинутые методы отладки
- •24.1. Введение в исключения отказов Cortex-M
- •24.1.1.1. Как инструментарий GNU MCU Eclipse обрабатывает исключения отказов
- •24.1.1.2. Как интерпретировать содержимое регистра LR при переходе в исключение
- •24.1.2. Исключения отказов и их анализ
- •24.2.1. Представление Expressions
- •24.2.1.1. Мониторы памяти
- •24.2.2. Точки наблюдения
- •24.2.3. Режим Instruction Stepping Mode
- •24.2.4. Keil Packs и представление Peripheral Registers
- •24.2.5. Представление Core Registers
- •24.3. Средства отладки от CubeHAL
- •24.4. Внешние отладчики
- •24.4.1. Использование SEGGER J-Link для отладчика ST-LINK
- •24.4.2. Использование интерфейса ITM и трассировка SWV
- •24.5. STM Studio
- •24.6. Одновременная отладка двух плат Nucleo
- •25. Файловая система FAT
- •25.1. Введение в библиотеку FatFs
- •25.1.1. Использование CubeMX для включения в ваши проекты библиотеки FatFs
- •25.1.2. Наиболее важные структуры и функции FatFs
- •25.1.2.1. Монтирование файловой системы
- •25.1.2.2. Открытие файлов
- •25.1.2.3. Чтение и запись файла
- •25.1.2.4. Создание и открытие каталога
- •25.1.3. Как сконфигурировать библиотеку FatFs
- •26. Разработка IoT-приложений
- •26.2. Ethernet контроллер W5500
- •26.2.1. Как использовать шилд W5500 и модуль ioLibrary_Driver
- •26.2.1.1. Конфигурирование интерфейса SPI
- •26.2.1.2. Настройка буферов сокетов и сетевого интерфейса
- •26.2.2. API-интерфейсы сокетов
- •26.2.2.1. Управление сокетами в режиме TCP
- •26.2.2.2. Управление сокетами в режиме UDP
- •26.2.3. Перенаправление ввода-вывода на сокет TCP/IP
- •26.2.4. Настройка HTTP-сервера
- •26.2.4.1. Веб-осциллограф
- •27. Начало работы над новым проектом
- •27.1. Проектирование оборудования
- •27.1.1. Послойная разводка печатной платы
- •27.1.2. Корпус микроконтроллера
- •27.1.3. Развязка выводов питания
- •27.1.4. Тактирование
- •27.1.5. Фильтрация вывода сброса RESET
- •27.1.6. Отладочный порт
- •27.1.7. Режим начальной загрузки
- •27.1.8. Обратите внимание на совместимость с выводами…
- •27.1.9. …и на выбор подходящей периферии
- •27.1.10. Роль CubeMX на этапе проектирования платы
- •27.1.11. Стратегии разводки платы
- •27.2. Разработка программного обеспечения
- •27.2.1. Генерация бинарного образа для производства
- •Приложение
- •Принудительный сброс микроконтроллера из микропрограммы
- •B. Руководство по поиску и устранению неисправностей
- •Проблемы с установкой GNU MCU Eclipse
- •Проблемы, связанные с Eclipse
- •Eclipse не может найти компилятор
- •Eclipse постоянно прерывается при выполнении каждой инструкции во время сеанса отладки
- •Пошаговая отладка очень медленная
- •Микропрограмма работает только в режиме отладки
- •Проблемы, связанные с STM32
- •Микроконтроллер не загружается корректно
- •Невозможно загрузить микропрограмму или отладить микроконтроллер
- •C. Схема выводов Nucleo
- •Nucleo-F446RE
- •Разъемы, совместимые с Arduino
- •Morpho-разъемы
- •Nucleo-F411RE
- •Разъемы, совместимые с Arduino
- •Morpho-разъемы
- •Nucleo-F410RB
- •Разъемы, совместимые с Arduino
- •Morpho-разъемы
- •Nucleo-F401RE
- •Разъемы, совместимые с Arduino
- •Morpho-разъемы
- •Nucleo-F334R8
- •Разъемы, совместимые с Arduino
- •Morpho-разъемы
- •Nucleo-F303RE
- •Разъемы, совместимые с Arduino
- •Morpho-разъемы
- •Nucleo-F302R8
- •Разъемы, совместимые с Arduino
- •Morpho-разъемы
- •Nucleo-F103RB
- •Разъемы, совместимые с Arduino
- •Morpho-разъемы
- •Nucleo-F091RC
- •Разъемы, совместимые с Arduino
- •Morpho-разъемы
- •Nucleo-F072RB
- •Разъемы, совместимые с Arduino
- •Morpho-разъемы
- •Nucleo-F070RB
- •Разъемы, совместимые с Arduino
- •Morpho-разъемы
- •Nucleo-F030R8
- •Разъемы, совместимые с Arduino
- •Morpho-разъемы
- •Nucleo-L476RG
- •Разъемы, совместимые с Arduino
- •Morpho-разъемы
- •Nucleo-L152RE
- •Разъемы, совместимые с Arduino
- •Morpho-разъемы
- •Nucleo-L073R8
- •Разъемы, совместимые с Arduino
- •Morpho-разъемы
- •Nucleo-L053R8
- •Разъемы, совместимые с Arduino
- •Morpho-разъемы
- •D. Корпусы STM32
- •LFBGA
- •LQFP
- •TFBGA
- •TSSOP
- •UFQFPN
- •UFBGA
- •VFQFP
- •WLCSP
- •E. Изменения книги
- •Выпуск 0.1 – Октябрь 2015
- •Выпуск 0.2 – 28 октября 2015
- •Выпуск 0.2.1 – 31 октября 2015
- •Выпуск 0.2.2 – 1 ноября 2015
- •Выпуск 0.3 – 12 ноября 2015
- •Выпуск 0.4 – 4 декабря 2015
- •Выпуск 0.5 – 19 декабря 2015
- •Выпуск 0.6 – 18 января 2016
- •Выпуск 0.6.1 – 20 января 2016
- •Выпуск 0.6.2 – 30 января 2016
- •Выпуск 0.7 – 8 февраля 2016
- •Выпуск 0.8 – 18 февраля 2016
- •Выпуск 0.8.1 – 23 февраля 2016
- •Выпуск 0.9 – 27 марта 2016
- •Выпуск 0.9.1 – 28 марта 2016
- •Выпуск 0.10 – 26 апреля 2016
- •Выпуск 0.11 – 27 мая 2016
- •Выпуск 0.11.1 – 3 июня 2016
- •Выпуск 0.11.2 – 24 июня 2016
- •Выпуск 0.12 – 4 июля 2016
- •Выпуск 0.13 – 18 июля 2016
- •Выпуск 0.14 – 12 августа 2016
- •Выпуск 0.15 – 13 сентября 2016
- •Выпуск 0.16 – 3 октября 2016
- •Выпуск 0.17 – 24 октября 2016
- •Выпуск 0.18 – 15 ноября 2016
- •Выпуск 0.19 – 29 ноября 2016
- •Выпуск 0.20 – 28 декабря 2016
- •Выпуск 0.21 – 29 января 2017
- •Выпуск 0.22 – 2 мая 2017
- •Выпуск 0.23 – 20 июля 2017
- •Выпуск 0.24 – 11 декабря 2017
- •Выпуск 0.25 – 3 января 2018
- •Выпуск 0.26 – 7 мая 2018
Таймеры |
331 |
11.3.6. Режим сравнения выходного сигнала
До сих пор мы использовали несколько методов для управления формой выходного сигнала: один с использованием прерываний и один – с DMA. Оба они используют генерацию события UEV для переключения GPIO, сконфигурированного в качестве выходного вывода. Сравнение выходного сигнала (Output compare) – это режим, предоставляемый тай-
мерами общего назначения и расширенного управления, который позволяет управлять со-
стоянием выходных каналов, когда регистр сравнения каналов (TIMx_CCRx) совпадает с регистром счетчика таймера (TIMx_CNT).
Для программистов доступно шесть28 режимов сравнения выходного сигнала:
•Времязадание в режиме сравнения выходного сигнала (Output compare timing)29: сов-
падение регистра сравнения выходного сигнала (CCRx) и счетчика (CNT) не влияет на выходной сигнал. Данный режим используется для генерации временного отсчета.
•Активный выходной сигнал сравнения (Output compare active): в момент совпадения выходной сигнал канала устанавливается на активный уровень. Выходной сигнал канала становится высоким в момент совпадения счетчика (CNT) и регистра захвата/сравнения (CCRx).
•Неактивный выходной сигнал сравнения (Output compare inactive): в момент совпа-
дения выходной сигнал канала устанавливается на неактивный уровень. Выходной сигнал канала становится низким в момент совпадения счетчика (CNT) и регистра захвата/сравнения (CCRx).
•Инвертирование выходного сигнала сравнения (Output compare toggle): выходной сиг-
нал канала инвертируется в момент совпадения счетчика (CNT) и регистра захвата/сравнения (CCRx).
•Установка активным/неактивным выходного сигнала сравнения (Output compare forced active/inactive): выходной сигнал канала принудительно устанавливается высоким (активный режим) или низким (неактивный режим) независимо от значения счетчика.
Каждый канал таймера конфигурируется в режиме сравнения выходного сигнала с использованием функции HAL_TIM_OC_ConfigChannel() и экземпляра структуры Си TIM_OC_InitTypeDef, которая определена следующим образом:
typedef struct { |
|
|
uint32_t OCMode; |
/* Задает режим TIM. |
*/ |
uint32_t Pulse; |
/* Задает значение импульса для загрузки в |
|
|
регистр сравнения/захвата. |
*/ |
uint32_t OCPolarity; |
/* Задает полярность выходного сигнала. |
*/ |
uint32_t OCNPolarity; |
/* Задает полярность комплементарного выхода. |
*/ |
uint32_t OCFastMode; |
/* Задает состояние быстрого режима (Fast mode). |
*/ |
uint32_t OCIdleState; /* Задает состояние вывода сравнения выходного |
|
|
|
сигнала TIM во время состояния простоя (Idle state) |
*/ |
uint32_t OCNIdleState; |
/* Задает состояние комплементарного вывода сравнения |
|
|
выходного сигнала TIM во время состояния простоя. |
*/ |
} TIM_OC_InitTypeDef; |
|
|
28Режимов сравнения выходного сигнала на самом деле восемь, но два из них связаны с выходным ШИМсигналом, и они будут проанализированы в следующем параграфе.
29Этот режим в CubeMX называется Frozen mode.
Таймеры |
332 |
•OCMode: задает режим сравнения выходного сигнала и может принимать значение
из таблицы 19.
•Pulse: содержимое данного поля будет храниться в регистре CCRx, и оно опреде-
ляет, когда активировать выход.
•OCPolarity: задает полярность выходного канала, когда регистры CCRx совпадают с регистрами CNT. Может принимать значение из таблицы 20.
•OCNPolarity: задает полярность комплементарного выхода. Данный режим досту-
пен только в таймерах расширенного управления TIM1 и TIM8, которые позволяют генерировать на дополнительных выделенных каналах комплементарные сигналы (то есть, когда CH1 – ВЫСОКИЙ, CH1N – НИЗКИЙ, и наоборот). Эта функция специально разработана для приложений управления двигателем, и она не описана в данной книге. Может принимать значение из таблицы 21.
•OCFastMode: задает состояние быстрого режима (fast mode state). Данный параметр
действует только в режимах ШИМ 1 и ШИМ 2 и может принимать значения
TIM_OCFAST_DISABLE и TIM_OCFAST_ENABLE.
•OCIdleState: задает состояние вывода канала сравнения выходного сигнала во
время режима простоя (idle state) таймера. Может принимать значения TIM_OCIDLESTATE_SET и TIM_OCIDLESTATE_RESET. Данный параметр доступен только в тайме-
рах расширенного управления TIM1 и TIM8.
•OCNIdleState: задает состояние вывода комплементарного канала сравнения вы-
ходного сигнала во время режима простоя (idle state) таймера. Может принимать
значения TIM_OCNIDLESTATE_SET и TIM_OCNIDLESTATE_RESET. Данный параметр досту-
пен только в таймерах расширенного управления TIM1 и TIM8.
Таблица 19: Доступные режимы сравнения выходного сигнала
Режим сравнения |
выходного |
сигнала |
Описание |
TIM_OCMODE_TIMING |
Сравнение между регистром сравнения выходного сиг- |
|
нала (CCRx) и счетчиком (CNT) не влияет на выходной |
|
сигнал (он же режим Frozen mode). |
TIM_OCMODE_ACTIVE
При совпадении устанавливает выходной сигнал канала на активный уровень.
TIM_OCMODE_INACTIVE
TIM_OCMODE_TOGGLE
При совпадении устанавливает выходной сигнал канала на неактивный уровень.
Выходной сигнал канала инвертируется в момент совпадения счетчика (CNT) и регистра захвата/сравнения
(CCRx).
TIM_OCMODE_PWM1
TIM_OCMODE_PWM2 TIM_OCMODE_FORCED_ACTIVE
TIM_OCMODE_FORCED_INACTIVE
Режим ШИМ 1 – см. в следующем параграфе. Режим ШИМ 2 – см. в следующем параграфе.
Выходной сигнал канала устанавливается в высокий уровень независимо от значения счетчика.
Выходной сигнал канала устанавливается в низкий уровень независимо от значения счетчика.
Таймеры |
333 |
Таблица 20: Доступные режимы полярности сравнения выходного сигнала |
|
Режим полярности сравнения |
|
выходного сигнала |
Описание |
TIM_OCPOLARITY_HIGH |
При совпадении регистров CCRx и CNT выходной сигнал |
|
канала устанавливается высоким |
TIM_OCPOLARITY_LOW
При совпадении регистров CCRx и CNT выходной сигнал канала устанавливается низким
Таблица 21: Доступные режимы полярности комплементарного вывода сравнения выходного сигнала
Режим полярности комплементарного |
|
вывода сравнения выходного сигнала |
Описание |
TIM_OCNPOLARITY_HIGH |
При совпадении регистров CCRx и CNT выход- |
|
ной сигнал комплементарного канала устанавли- |
|
вается высоким |
TIM_OCNPOLARITY_LOW
При совпадении регистров CCRx и CNT выходной сигнал комплементарного канала устанавливается низким
Когда регистры CCRx совпадают со счетчиком CNT таймера и канал сконфигурирован для работы в режиме сравнения выходного сигнала, генерируется специальное прерывание (если оно разрешено). Это позволяет управлять независимо частотой переключения каждого канала и, в конечном итоге, выполнять фазовый сдвиг между каналами. Частота канала может быть вычислена по следующей формуле:
CHx _Update = |
TIMx _ CLK |
|
CCRx |
||
|
[5]
где:
TIMx _ CLK – рабочая частота таймера, а CCRx – значение импульса Pulse структуры TIM_OnePulse_InitTypeDef, используемой для конфигурации канала. Это означает, что мы можем вычислить значение Pulse, учитывая частоту канала, следующим образом:
Pulse = |
TIMx _ CLK |
|
CHx _Update |
||
|
[6]
Важно подчеркнуть, что частота таймера должна быть установлена таким образом, чтобы значение Pulse, рассчитанное с помощью [6], было меньше значения Period таймера (значение CCRx не может быть выше значения TIM->ARR, которое соответствует значению Period таймера).
В следующем примере показано, как генерировать два выходных сигнала прямоугольной формы, один из которых работает на частоте 50 кГц, а другой – на частоте 100 кГц. Пример использует каналы 1 и 2 (привязаны к OC1 и OC2) таймера TIM3 и предназначен для работы на Nucleo-F030R8.
Таймеры |
334 |
Имя файла: src/main-ex7.c
17volatile uint16_t CH1_FREQ = 0;
18volatile uint16_t CH2_FREQ = 0;
20int main(void) {
21 |
HAL_Init(); |
22 |
|
23Nucleo_BSP_Init();
24MX_TIM3_Init();
26HAL_TIM_OC_Start_IT(&htim3, TIM_CHANNEL_1);
27HAL_TIM_OC_Start_IT(&htim3, TIM_CHANNEL_2);
29while (1);
30}
31
32/* Функция инициализации TIM3 */
33void MX_TIM3_Init(void) {
34TIM_OC_InitTypeDef sConfigOC;
36htim3.Instance = TIM3;
37htim3.Init.Prescaler = 2;
38htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
39htim3.Init.Period = 65535;
40htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
41 |
HAL_TIM_OC_Init(&htim3); |
42 |
|
43CH1_FREQ = computePulse(&htim3, 50000);
44CH2_FREQ = computePulse(&htim3, 100000);
46sConfigOC.OCMode = TIM_OCMODE_TOGGLE;
47sConfigOC.Pulse = CH1_FREQ;
48sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
49sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
50HAL_TIM_OC_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_1);
52sConfigOC.Pulse = CH2_FREQ;
53HAL_TIM_OC_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_2);
54}
Строки [46:53] конфигурируют каналы 1 и 2 для работы в качестве каналов сравнения выходного сигнала. Оба конфигурируются в режиме переключения toggle mode (то есть они инвертируют состояние GPIO каждый раз, когда регистр CCRx совпадает с регистром CNT таймера). TIM3 сконфигурирован для работы на частоте 16 МГц, и, следовательно, функция computePulse(), которая использует уравнение [6], вернет значения 320 и 160, чтобы иметь частоты переключения каналов, равные 50 кГц и 100 кГц соответственно. Однако приведенного выше кода все еще недостаточно для управления GPIO на данной частоте. Здесь мы конфигурируем каналы так, чтобы они переключали свой выход каждый раз, когда регистр таймера CNT равен 320 для канала 1 и 160 для канала 2. Но это означает, что частота переключения равна:
Таймеры |
|
335 |
|
16000000 |
= 244 Гц |
|
65535 +1 |
|
|
|
и мы имеем только смещение 10 мкс между двумя каналами, как показано на рисунке 21. Значение 65535 соответствует значению Period таймера, то есть максимальному значению, достигаемому регистром CNT таймера.
Рисунок 21: Смещение переключения между каналами 1 и 2
Чтобы достичь желаемой частоты переключения30, нам нужно переключать выход каждые 320 и 160 тиков регистра CNT таймера TIM3. Для этого мы можем определить следующую процедуру обратного вызова:
Имя файла: src/main-ex7.c
61void HAL_TIM_OC_DelayElapsedCallback(TIM_HandleTypeDef *htim) {
62uint16_t pulse;
63
64/* Переключение TIM2_CH1 с частотой = 50 кГц */
65if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1)
66{
67pulse = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1);
68/* Установка значения регистра захвата/сравнения */
69__HAL_TIM_SET_COMPARE(htim, TIM_CHANNEL_1, (pulse + CH1_FREQ));
70}
71
72/* Переключение TIM2_CH2 с частотой = 100 кГц */
73if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2)
74{
75pulse = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_2);
76/* Установка значения регистра захвата/сравнения */
77__HAL_TIM_SET_COMPARE(htim, TIM_CHANNEL_2, (pulse + CH2_FREQ));
78}
79}
HAL_TIM_OC_DelayElapsedCallback() автоматически вызывается HAL каждый раз, когда регистр канала CCRx совпадает со счетчиком таймера. Таким образом, мы можем увеличить Pulse (то есть регистр CCRx) значением 320 для канала 1 и значением 160 для канала 2. Это приведет к тому, что соответствующий канал будет переключаться на желаемой частоте, как показано на рисунке 22.
30 Обратите внимание, что на качество выходного сигнала влияет параметр GPIO скорость нарастания, как описано в Главе 6.