Робота з кнопкою і світлодіодом. Приклад організації коду по різних файлах.
Зовнішні переривання
Використання SWO виводу програматора. Вивід даних у консоль (консоль програматора, не UART). Статистика роботи прошивки SWV. Графіки даних.
Приклади роботи з послідовним портом
Відправлення даних і отримання символів з консолі. 1 - вмикає світлодіод, 0 - вимикає.
Використання переривань і Callback функції для приймання даних
Використання DMA для приймання даних
Low Power UART & Low Power Timer - використовуються коли треба зменшити споживання мікроконтролера і працювати з низькою тактовою частотою. У цьому прикладі частота ядра 500КГц. Частота тактування деякої периферії знижена до 31250 Гц
MP3 модуль з керуванням по порту UART. Приклад бібліотеки, яка вміє проговорювати числа.
Приклад роботи з протоколом CRSF, з яким працюють ELRS або TBS приймачі
Приклад роботи з GPS модулем GY-GPS6MV2. Парсинг GPS даних.
Налаштування таймера для періодичних викликів. Приклад використання Callback функції.
Вимірювання часу між двома подіями (натисканнями на кнопку)
Генерація PWM
Генерація PWM для RGB світлодіода
Генерація PWM для сервомашинки
Генерація звуку і програвання мелодії
Захоплення сигналу, обчислення частоти сигналу
Робота з інкрементним енкодером
Захоплення сигналу PWM, обчислення частоти сигналу та його шпаруватості
Захоплення сигналу від пульта телевізора. Працює тільки з поодинокими натисненнями на кнопки пульта. При натисканні і утриманні не спрацьовує.
Захоплення сигналу DShot 150/300/600 від польотного контролера. Використовується DMA.
Використання таймера SysTick. На той випадок, коли не вистачить звичайних таймерів.
Low Power Timer & Low Power UART - використовуються коли треба зменшити споживання мікроконтролера і працювати з низькою тактовою частотою. У цьому прикладі частота ядра 500Кгц. Частота тактування деякої периферії знижена до 31250 Гц
Використання DWT таймера для мікросекундних затримок
Приклад роботи з ультразвуковим відстанеміром
Приклад роботи з цифровими світлодіодами
Сканує підключені до шини I2C пристрої і виводить їх адреси
LCD16x2 з I2C модулем. Використовуємо бібліотеку i2c_lcd
Монохромний OLED дисплей
Монохромний LCD дисплей
Датчик тиску, температури
Датчик тиску, температури
Приклад роботи з SD карткою пам'яті по шині SPI
Графічний кольоровий дисплей
Графічний монохромний LCD дисплей. Приклад програмної реалізації SPI
Приклад роботи з шиною CAN
Приклади роботи з АЦП
Як не бажано робити
Послідовне опитування декількох каналів ADC. Звернути увагу, що увімкнуто Discontinuous.
Використання ADC з DMA
Використання ADC з DMA у циклічному безконечному режимі. Зверніть увагу на дільник. Якщо частота занадто висока може зависати головний цикл. У цьому випадку треба збільшити дільник, або час вибірки.
Використання Injected каналів. Використовуються канали виміру температури та напруги Vbat. Vbat 1/3 тому множимо на 3. Запуск перетворень від таймера. Зверніть увагу на External Trigger Source.
Використання Injected каналів, початок перетворень по тригеру від таймера. Звернути увагу, що час вибірки не може бути будь-яким.
Note: In case of usage of internal measurement channels (VrefInt, Vbat, ...),
sampling time constraints must be respected (sampling time can be adjusted
in function of ADC clock frequency and sampling time setting).
Refer to device datasheet for timings values. */
/* Note: VrefInt, TempSensor and Vbat internal channels are not available on */
/* all ADC instances (refer to Reference Manual).
Аналоговий Watchdog. Звернути увагу:
- для WDG треба, щоб ADC працював з включеним Continuous Conversion Mode
- HAL_ADC_LevelOutOfWindowCallback викликається тільки при виходу з вікна. При поверненні Callback не спрацьовує.
- не завжди аналоговий WDG буде працювати. Якщо додати ще один канал у регулярні перетворення, переривання не виникають.
Аналоговий компаратор
Цифро аналоговий перетворювач
Просте використання, встановлення постійної напруги
Проста генерація сигналу синусоїдальної форми
Генерація гладенького синуса з використанням DMA і розрахунком на льоту. У проєкт додано дисплей і 4 кнопки для зміни частоти та амплітуди
Операційний підсилювач. Поєднання виходу підсилювача зі входом АЦП
Це продовження прикладу FMAC. У цьому прикладі демонструються можливості мікроконтролера поєднувати різні периферії Операційний підсилювач з програмованим коефіцієнтом підсилення -> ADC -> фільтр FMAC -> DAC. Тактується ADC, DAC одним таймером
Використання CORDIC для обчислення тригонометричних функцій. Порівняв швидкість роботи функцій "sin":
- sin з math.h
- sinf з math.h
- arm_sin_f32 з arm_math.h
- CORDIC
Формат q31 та функції перетворення
Обчислення CRC (Cyclic Redundancy Check) за допомогою вбудованого модуля мікроконтролера
Цифрова фільтрація даних. У прикладі дані з АЦП потрапляють у FMAC. Порівняння вхідних і вихідних даних на графіках SWV. Online розрахунок коефіцієнтів фільтра: https://fiiir.com/ Для перетворення коефіцієнтів у формат для FMAC використовуйте файл /FMAC/Info/index.html
Дивись також приклад OPAMP_ADC_FMAC_DAC
Програмна реалізація фільтра з використанням бібліотеки arm_math.h На відміну від FMAC можемо організувати фільтрацію декількох каналів. У прикладі АЦП починає перетворення декількох каналів по тригеру від таймера. Дані з використанням DMA поміщаються у відповідний буфер. По завершенню перетворень викликається функція фільтрації. Порівняння вхідних і вихідних даних на графіках SWV. Online розрахунок коефіцієнтів фільтра: https://fiiir.com/
Використання модуля RNG для генерації випадкового числа
Віртуальний порт через USB
Емуляція мишки та клавіатури
Повторення раніше створеного Bootloader https://blog.avislab.com/stm32-bootloader/
DFU Bootloader.
Для прошивки використовується dfu-util:
dfu-util -s 0x08008000 -D ./Debug/USB_DFU_TestApp.bin
Або WEBDFU - dfu-util via web: https://devanlai.github.io/webdfu/dfu-util/
Пам'ятка по опису па USBD_DFU_MEDIA_Interface:
Parameter Description:
The description of the flash (used by PC tool DFuSe) Each Alternate setting string descriptor must follow this memory mapping so that the PC Host Software can decode the right mapping for the selected device:
● @: To detect that this is a special mapping descriptor (to avoid decoding standard descriptor)
● /: for separator between zones
● Maximum 8 digits per address starting by “0x”
● /: for separator between zones
● Maximum of 2 digits for the number of sectors
● *: For separator between number of sectors and sector size
● Maximum 3 digits for sector size between 0 and 999
● 1 digit for the sector size multiplier. Valid entries are: B (byte), K (Kilo), M (Mega)
● 1 digit for the sector type as follows:
– a (0x41): Readable
– b (0x42): Erasable
– c (0x43): Readable and Erasabled (0x44): Writeable
– e (0x45): Readable and Writeable
– f (0x46): Erasable and Writeable
– g (0x47): Readable, Erasable and Writeable
Note: If the target memory is not contiguous, the user can add the new sectors to be decoded just after a slash"/" as shown in the following example: "
@Flash /0xF000/1*4Ka/0xE000/1*4Kg/0x8000/2*24Kg"
@Internal Flash /0x08008800/03*016Ka,01*016Kg,01*064Kg,07*128Kg,04*016Kg,01*064Kg,07*128Kg
@Internal Flash /0x08000000/01*034Ka,05*016Kg
@Internal Flash /0x08000000/01*032Ka,47*002Kg,01*002Ka
1 block 32K - Readable (bootloader here)
47 blocks 2K = Readable, Erasable and Writeable (main firmware here)
1 block 2K - Readable (App Settings here)
Totall Flash size: 1*32+ 47*2 + 1*2= 128
Програма для DFU Bootloader
Зверніть увагу:
- у файлі STM32G431CBUX_FLASH.ld скоригувати "Memories definition". Встановити адрес 0x08008000 та максимальний розмір 94K. (128-32-2) 32K для bootloader, 2K - остання сторінка для зберігання налаштувань
...
/* Memories definition */
MEMORY
{
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 32K
FLASH (rx) : ORIGIN = 0x8008000, LENGTH = 94K
}
...
- у файлі Core/Src/system_stm32g4xx.c розкоментувати #define USER_VECT_TAB_ADDRESS та вказати FLASH_BASE
...
#define USER_VECT_TAB_ADDRESS
#define FLASH_BASE 0x08008000
...
Годинник реального часу. Зверніть увагу - якщо у CubeMX увімкнути ініціалізацію календаря, тоді при старті контролера час і дата буде скидатися до встановленого. Підключаємо батарейку 3V для того, щоб RTC працював без основного живлення мікроконтролера, а результат - при страті контролера час і дата скидається до встановленого у CubeMX. Тому ініціалізацію календаря НЕ вмикаємо.
Використання "Будильника".
Backup registers. RTC має бути увімкнуто. Тактування можна і від внутрішнього RC- генератора. Календар вмикати не потрібно.
Приклад зберігання та читання даних з Flash пам'яті
Watchdogs використовуються, щоб у разі зависання програми мікроконтролера його (мікроконтролер) можна було перезавантажити.
Незалежний Watchdog - тактується від окремого, вбудованого у мікроконтролера, генератора низької частоти. Зверніть увагу, що у цьому мікроконтролері IWDG має ознаку window. hiwdg.Init.Window = 4095; - якщо Window не використовуємо. HAL_Delay(600); Відразу до першого HAL_IWDG_Refresh(&hiwdg); - це важливо у разі використання Window. Якщо скинути IWDG відразу - це перезавантаження.
Window Watchdog тактується частотою, якою тактується мікроконтролер. Вірніше сказати, частота тактування WWDG дорівнює частоті HCLK, поділена на постійний дільник 4096. Таким чином робота WWDG синхронізована з роботою мікроконтролера.
Моніторінг напруги живлення мікроконтроллера. Налаштування переривання при зниженні напруги і при поверненні до норми. Зазор від встановленної напруги +- 100мВ. Зверніть увагу, що все що наконфігуячили у CubeMX в проекті не з'являється, треба самостійно налаштовувати.
Режими зниженого енергоспоживання Sleep, Stop, Standby
Сплячий режим Sleep. У сплячому режимі тактування ядра зупинено, периферія, в тому числі і ядро, працюють, виходи мікроконтролера зберігають свій стан.
Сплячий режим Sleep. Контроллер прокидається тільки для обробки переривань і відразу впадає у Sleep.
Режим зупинки - це режим глибокої сплячки ядра. В цьому режимі зупиняються всі генератори тактової частоти, а також відключаються PLL, HSI і HSE RC. У режимі зупинки всі виводи мікроконтролера зберігають свій стан. Зверніть увагу, що переривання пробуджують мікроконтроллер, але обробник переривання не виконуєтьс. Обробка переривань спрацьовує лише у режимі, коли мікроконтроллер працьє у нормальному режимі.
Режим Standby найекономічніший. Мікроконтролер у цьому стані вимикає майже все - PLL, HSI, HSE, регулятор живлення. Вся інформація у пам`яті та регістрах втрачається. Виводи переводяться у високоімпедансний стан, тобто відключаються. Стан контролера майже такий, як і без живлення. Майже, бо перед переходом у режим Standby можна сконфігурувати деякі речі, які будуть працювати і можуть вивести його з режиму Standby. Наприклад RTC_Alarm. Дивись наступний приклад.
Щоб вивести зі сплячик требе А0 замкнути на землю і відпустити. Саме зростаючий фронт перезавантажує мікроконтроллер. Повідинка, як і при Reset.
Режим Standby. Періодичне прокидання по RTC_Alarm.