- •Оглавление
- •Предисловие
- •Почему я написал книгу?
- •Для кого эта книга?
- •Как использовать эту книгу?
- •Как организована книга?
- •Об авторе
- •Ошибки и предложения
- •Поддержка книги
- •Как помочь автору
- •Отказ от авторского права
- •Благодарность за участие
- •Перевод
- •Благодарности
- •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
Часы реального времени |
465 |
вывести микроконтроллер из состояния сна в режиме Ожидания (standby sleep state) на программируемой основе.
Наконец, RTC предоставляет возможность выборки нескольких заданных входов для обнаружения несанкционированного доступа (tampering): поскольку периферийное устройство RTC может питаться от батареи2 в нескольких микроконтроллерах STM32, оно также может обнаруживать несанкционированный доступ, даже если устройство выключено. При обнаружении несанкционированного доступа устанавливается определенный регистр, при этом обнуляется содержимое резервной памяти (backup memory).
18.2. Модуль HAL_RTC
Для программирования периферийного устройства RTC HAL объявляет структуру Си RTC_HandleTypeDef, которая определена следующим образом:
typedef struct { |
|
|
|
RTC_TypeDef |
*Instance; |
/* Базовый адрес регистров |
*/ |
RTC_InitTypeDef |
Init; |
/* Требуемые параметры RTC |
*/ |
HAL_LockTypeDef |
Lock; |
/* Блокировка объекта RTC |
*/ |
__IO HAL_RTCStateTypeDef |
State; |
/* Состояние работы RTC |
*/ |
} RTC_HandleTypeDef; |
|
|
|
Единственными важными полями данной структуры являются Instance, которое является указателем на дескриптор периферийного устройства RTC, и поле Init, используемое для конфигурации периферийного устройства. Это поле является экземпляром структуры Си RTC_InitTypeDef, которая определена следующим образом:
typedef struct { |
|
|
uint32_t HourFormat; |
/* Задает часовой формат RTC. |
*/ |
uint32_t AsynchPrediv; |
/* Задает значение асинхронного предделителя RTC. |
*/ |
uint32_t SynchPrediv; |
/* Задает значение синхронного предделителя RTC. |
*/ |
uint32_t OutPut; |
/* Задает, какой сигнал будет направлен на выход RTC. */ |
|
uint32_t OutPutPolarity; |
/* Задает полярность выходного сигнала. |
*/ |
uint32_t OutPutType; |
/* Определяет режим вывода выхода RTC. |
*/ |
} RTC_InitTypeDef; |
|
|
•HourFormat: в этом поле задается часовой формат времени, и оно может прини-
мать значения RTC_HOURFORMAT_12 для задания 12-часового формата AM/PM и RTC_HOURFORMAT_24 для задания 24-часового формата времени.
•AsynchPrediv и SynchPrediv: два предделителя, используются для получения такто-
вой частоты в 1 Гц для питания периферийного устройства RTC от источников тактового сигнала LSI/LSE/HSE-генераторов. Первый – асинхронный предделитель 7-разрядного счетчика, который, в свою очередь, подается на синхронный предделитель другого, 15-разрядного, счетчика. Значения этих двух полей должны быть
2 В следующей главе мы увидим, что микроконтроллеры STM32 с большим количеством выводов предоставляют несколько независимых доменов питания. RTC относится к домену VBAT, то есть к набору всех периферийных устройств, которые получают питание через вывод VBAT. Этот домен специально предназначен для подключения к батарее, и все периферийные устройства, принадлежащие данному домену, продолжают работать, даже когда основное питание и, следовательно, ядро микроконтроллера выключены.
Часы реального времени |
|
466 |
установлены так, чтобы была достигнута частота в 1 Гц в соответствии с уравне- |
||
нием [1], где |
Тактовый сигнал Календаря |
– один из сигналов LSI/LSE/HSE- |
генераторов. На момент написания данной главы последний выпуск CubeMX (4.22) не смог автоматически получить правильные значения для полей AsynchPrediv и SynchPrediv. Вы можете использовать значения, указанные в таблице 1, для большинства используемых частот генераторов.
Тактовый сигнал RTC Тактовый сигнал Календаря = ( )( ) AsynchPrediv +1 SynchPrediv +1
[1]
Таблица 1. Правильные значения для полей AsynchPrediv и SynchPrediv в соответствии с наиболее распространенными источниками тактового сигнала
Тактовый сигнал Календаря
HSE_RTC = 1 МГц
LSE = 32,768 кГц
LSI = 32 кГц
LSI = 37 кГц
AsynchPrediv
124
127
127
127
SynchPrediv
7999
255
249
295
•OutPut: задает сигнал I/O, направляемый на выход RTC. Может принимать значе-
ния RTC_OUTPUT_ALARMA, RTC_OUTPUT_ALARMB, RTC_OUTPUT_WAKEUP и RTC_OUTPUT_DISABLE
для направления выхода к сигналу, связанному с будильниками Alarm A, B, блоку пробуждения Wakeup или для отключения выходного сигнала. Пожалуйста, обратите внимание, что фактический GPIO, связанный с заданным будильником, спроектирован во время разработки микроконтроллера и является фиксированным. В зависимости от типа используемого корпуса может быть доступен только один сигнал с I/O, который может использоваться тремя источниками будильника. Например, все микроконтроллеры STM32 с корпусом LQFP-64 имеют только один I/O будильника с именем AF1, и он подключен к выводу PC13.
•OutPutPolarity: в этом поле задается полярность (активный фронт) выходного сиг-
нала, и оно может принимать значения RTC_OUTPUT_POLARITY_HIGH и RTC_OUTPUT_POLARITY_LOW.
•OutPutType: это поле задает тип выходного сигнала и может принимать значения
RTC_OUTPUT_TYPE_OPENDRAIN и RTC_OUTPUT_TYPE_PUSHPULL.
Как обычно, для конфигурации периферийного устройства RTC мы используем функцию:
HAL_StatusTypeDef HAL_RTC_Init(RTC_HandleTypeDef *hrtc);
которая принимает указатель на экземпляр структуры RTC_HandleTypeDef, рассмотренной ранее.
18.2.1. Установка и получение текущей даты/времени
CubeHAL реализует отдельные процедуры и структуры Си для установки и получения текущей даты и времени. Функции:
HAL_StatusTypeDef HAL_RTC_SetTime(RTC_HandleTypeDef *hrtc,
RTC_TimeTypeDef *sTime, uint32_t Format);
HAL_StatusTypeDef HAL_RTC_GetTime(RTC_HandleTypeDef *hrtc,
Часы реального времени |
467 |
RTC_TimeTypeDef *sTime, uint32_t Format);
используются для установки/получения текущего времени, а функции:
HAL_StatusTypeDef HAL_RTC_SetDate(RTC_HandleTypeDef *hrtc,
RTC_DateTypeDef *sDate, uint32_t Format);
HAL_StatusTypeDef HAL_RTC_GetDate(RTC_HandleTypeDef *hrtc,
RTC_DateTypeDef *sDate, uint32_t Format);
используются для установки/получения текущей даты.
Структура RTC_TimeTypeDef, используемая для установки/получения текущего времени, определена следующим образом:
typedef struct { |
|
|
uint8_t Hours; |
/* Задает часы времени RTC. |
|
|
Этот параметр должен быть числом от 0 до 12, если |
|
|
выбран 12-часовой формат. В противном случае он должен |
|
|
быть числом от 0 до 23 при выбранном 24-часовом |
|
|
формате |
*/ |
uint8_t Minutes; |
/* Задает минуты времени RTC. |
|
|
Этот параметр должен быть числом от 0 до 59 |
*/ |
uint8_t Seconds; |
/* Задает секунды времени RTC. |
|
|
Этот параметр должен быть числом от 0 до 59 |
*/ |
uint8_t TimeFormat; |
/* Задает формат времени RTC. |
*/ |
uint32_t SubSeconds; |
/* Задает содержимое регистра подсекунд RTC RTC_SSR. |
|
|
Не используется при настройке таймера |
*/ |
uint32_t SecondFraction; /* Задает диапазон или масштаб дробления регистра |
|
|
|
подсекунд |
*/ |
uint32_t DayLightSaving; /* Задает работу летнего времени |
*/ |
|
uint32_t StoreOperation; /* Задает значение операции хранения |
*/ |
|
} RTC_TimeTypeDef; |
|
|
Давайте проанализируем роль наиболее важных полей:
•Hours, Minutes, Seconds: эти поля используются для установки текущего времени.
•TimeFormat: используется для установки формата времени (12/24-часовой) и может
принимать значения RTC_HOURFORMAT_12 или RTC_HOURFORMAT_24.
•SubSeconds: когда структура RTC_TimeTypeDef заполняется процедурой HAL_RTC_Get-
Time(), это поле содержит текущее значение подсекунд. Оно игнорируется про-
цедурой HAL_RTC_SetTime(). Данное поле соответствует диапазону единиц времени между [0-1] секундами, с масштабом дробления (гранулярностью), равной
1 с/(SecondFraction+1).
•SecondFraction: задает гранулярность (масштаб дробления) поля SubSeconds и со-
ответствует значению коэффициента синхронного предделителя. Данное поле будет использоваться только функцией HAL_RTC_GetTime().
•DayLightSaving: в данном поле задается учет летнего времени, и оно может при-
нимать значения RTC_DAYLIGHTSAVING_SUB1H, RTC_DAYLIGHTSAVING_ADD1H или RTC_DAYLIGHTSAVING_NONE.
Часы реального времени |
468 |
Структура RTC_DateTypeDef, используемая для установки/получения текущей даты, определена следующим образом:
typedef struct { |
|
|
uint8_t WeekDay; |
/* Задает день недели даты RTC. |
*/ |
uint8_t Month; |
/* Задает месяц даты RTC (в формате BCD). |
*/ |
uint8_t Date; |
/* Задает число месяца даты RTC. |
*/ |
uint8_t Year; |
/* Задает год даты RTC. |
*/ |
} RTC_DateTypeDef; |
|
|
Все четыре функции, относящиеся ко времени/дате, принимают в качестве последнего параметра формат полей времени/даты. Данный параметр может принимать значения
RTC_FORMAT_BIN и RTC_FORMAT_BCD. Если передана константа RTC_FORMAT_BIN, тогда поля вре-
мени/даты выражаются в обычном двоичном формате. Например, время «12:45» выражается как есть. Если вместо этого передается константа RTC_FORMAT_BCD, то значения выражаются в формате BCD. Это означает, что каждое поле времени/даты (занимающее один байт), должно интерпретироваться как два вспомогательных фрагмента, которые соответствуют цифрам десятичного числа. Таким образом, следуя тому же предыдущему примеру, мы получим, что десятичное число «12» выражается как 1810 в двоичном формате, что соответствует 12 в шестнадцатеричном представлении (см. рисунок 2).
Рисунок 2: Как возвращается время, закодированное в формате BCD
18.2.1.1. Правильный способ чтения значений даты/времени
Текущее значение даты/времени не может быть прочитано произвольно: существует четко определенная процедура, которой необходимо следовать. Все потому что по умолчанию мы не имеем прямого доступа к внутренним регистрам RTC даты/времени. RTC является периферийным устройством, которое работает самостоятельно и не тактируется от шины APB. Когда код считывает поля календаря, он получает доступ к теневым регистрам, содержащим копию реального календарного времени и даты и тактируемым от тактового сигнала RTC (RTCCLK). Копирование выполняется каждые два тактовых цикла RTCCLK, синхронизированных с системным тактовым сигналом (SYSCLK). Более того, мы должны вызвать HAL_RTC_GetDate() после HAL_RTC_GetTime(), даже если нас не интересует текущая дата. Все потому что вызов HAL_RTC_GetDate() разблокирует значения в теневых регистрах календаря высшего порядка, чтобы обеспечить согласованность между временем и датой. Чтение текущего времени RTC блокирует значения в теневых регистрах календаря до считывания текущей даты. Это достаточно частая ошибка, совершаемая новичками в платформе STM32: при доступе к соответствующим времени полям с помощью HAL_RTC_GetTime() мы получаем последнее переданное время, если не читаем содержимое соответствующих дате полей соответствующего теневого регистра.
После системного сброса или выхода из режимов пониженного энергопотребления приложение должно дождаться синхронизации между внутренним и теневым регистрами RTC, прежде чем читать теневые регистры календаря. Для выполнения данной операции CubeHAL предоставляет функцию: