AVR vs STM32: як перейти і чому варто. Частина 4
Я починав з AVRок, а потім з’явилось Arduino зі своїми шильдами, датчиками, сенсорами. Це супер захопливо і дуже зручно, макетки, проводульки і майже нуль пайки. За 12 років знайомства перепробував купу усього, і є проєкти, які без упину працюють більше 10 років. Оскільки ця тема цікава, то зустрічав костильні кастомні рішення навіть на конвеєрах і ЧПУ.
Пам’ятаю, як в 2016 році створював радіоклуб і познайомився з чоловіком, який зібрав ЧПУ, на якому різбив ікони. Це було щось неймовірне. А ще один член нашого клубу робив дрони для контрабандістів, за допомогою яких через кордон до Європи переправляли цигарки. Робили радіоключі для відкривання авто і майстер-ключі для домофонів. Приблуди для зміни міри наливання бензину на колонках АЗС. Звісно, не все прямо на ардуїнках, але точно на AVR. Цікавий проєкт, цікаві часи.
Тож подивився я років надцять тому на STM32 і подумав, навіщо воно мені? Arduino працює, бібліотек купа, все просто. Але були проєкти, де тре було ну дуже економне енергоспоживання. У моєму випадку це датчик рівня газу, який встановлений у вибухово небезпечній зоні. Мав відповідати певним правилам, зокрема до нього не можна було тягнути проводульки, і він повинен був бути реалізованим у вибухозахищеному корпусі. В ідеалі така собі коробочка з батарейкою, яка передає дані на сервер раз чи два на добу по GSM. На практиці батарейку міняли раз на три роки.
Купив я плати розробника з stm32 на борту, декілька книжок, погуглив. Попробував китайську IDE для stm. Зробив кілька учбових проектів. Заробив гемарой Намучився і закинув. Забігаючи наперед скажу, що Ардуїно і avr для моїх проектів вистачало з головою, і вистачає до цих пір, і в нас взаємна любов. Та одного дня перебуваючи в глубокій духовній практиці, було виявлено незакритий гештальт, який значно фонив і мав негативний вплив на моє духовне прозріння.
Тому і вирішено було написати bare-metal код для STM32. І в цьому опусі поділюсь першими враженнями.
Ще раз зазначу, що це проміжна стаття серії, для тих хто знає AVR/Arduino і хоче зрозуміти STM32. Трохи вищого рівня ніж «ось бібліотека підключи і працює» — а що реально відбувається всередині і чому STM32 влаштований саме так. Погнали.
Перше здивування: де PORTB?
На AVR все просто:
// AVR ATmega328P — мигаємо PB5 (це D13 на Arduino Uno)
#include <avr/io.h>
int main(void) {
DDRB |= (1 << PB5); // пін як вихід
while (1) {
PORTB ^= (1 << PB5); // toggle
_delay_ms(500);
}
}
Три рядки. DDRB, PORTB — просто змінні. Йопта невже чорна Магія?
На STM32:
// STM32F103 — мигаємо PC13 (вбудований LED на Blue Pill)
#include <stdint.h>
#define RCC_APB2ENR (*(volatile uint32_t *)0x40021018)
#define GPIOC_CRH (*(volatile uint32_t *)0x40011004)
#define GPIOC_ODR (*(volatile uint32_t *)0x4001100C)
int main(void) {
RCC_APB2ENR |= (1 << 4); // тактування GPIOC
GPIOC_CRH &= ~(0xF << 20); // очищаємо PC13
GPIOC_CRH |= (0x2 << 20); // output push-pull 2MHz
while (1) {
GPIOC_ODR ^= (1 << 13);
for (volatile int i = 0; i < 500000; i++);
}
}
Більше коду. Магічні адреси. Незрозумілий RCC. Навіщо це все?
Чому на AVR простіше
ATmega328P (самий популярний на моїй пам’яті)— маленький мікроконтролер. 32 КБ Flash, 2 КБ SRAM, 23 GPIO. Периферії мало — UART один (є рішення як зробити три), SPI один, I2C один.
Регістри периферії на AVR — це буквально змінні в пам’яті даних. Компілятор знає де вони знаходяться і дає їм імена:
// AVR — DDRB це просто адреса 0x24 в пам'яті // але avr/io.h ховає це від тебе DDRB = 0xFF; // виглядає як звичайна змінна
Плюс в тому, що на AVR немає тактування периферії. Вмикаєш живлення і все вже працює. Не треба думати про RCC.
AVR простіший бо мабуть скромніше. Менше периферії → менше регістрів → менше налаштувань.
Чому на STM32 складніше але краще
STM32F103 (моя перша платка і мабуть теж дуже популярна, у мене є коробка плат десятирічної витримки в ідеальних умовах, так до слова) це зовсім інший рівень. 64 КБ Flash, 20 КБ SRAM, 37 GPIO, 3 UART, 2 SPI, 2 I2C, 7 таймерів, ADC, USB, CAN.
На правах реклами: ви можете придбати в мене одну з плат дуже задорого (100 долларів США). Отримавши при цьому плату десятирічної витримки, яка пройшла езотеричний обряд очищення та заряджання кремнієвими духами. Одна її присутність у вашій лабораторії чи майстерні гарантує Благість, Удачу, Присутність Кремнієвого духу, оберіг від КЗ, втоми та поганого настрою, а найголовніше вона захистить вас від зайвих 100 баксів, які ви точно мали витрати на пиво, блуд чи цигарки 😀😀😀
1. Карта адрес (Memory Map)
На AVR регістри периферії живуть в окремому I/O просторі. На STM32 — все в одному
0×08000000 Flash (твій код)
0×20000000 SRAM (твої змінні)
0×40000000 Периферія APB1 (таймери, I2C, UART2/3)
0×40010000 Периферія APB2 (GPIO, SPI1, UART1, ADC)
0xE0000000 Системна периферія (NVIC, SysTick)
Це означає що будь-який модуль — DMA, відладчик, Linux через UART може читати і писати в будь-який регістр периферії напряму.
2. Тактування (RCC)
На AVR периферія завжди тактується. На STM32 — за замовчуванням вимкнена. Економія енергії.
// STM32: спочатку вмикаємо тактування
RCC_APB2ENR |= (1 << 4); // GPIOC on
// тільки після цього регістри GPIOC реагують на запис
Забув тицьнути в RCC і периферія мовчить. І ніхто не підкаже чому. Думаю це найпопулярніша помилка новачків на STM32.
3. Більше можливостей GPIO
AVR: пін або вхід або вихід. STM32: вісім режимів — input floating, pull-up, pull-down, output push-pull 2/10/50MHz, open-drain, alternate function, analog.
// input floating: 0×4
// input pull-up: 0×8
// output push-pull 2MHz: 0×2
// AF push-pull 50MHz: 0xB ← для UART TX, SPI
// AF open-drain 50MHz: 0xF ← для I2C
Порівняння: UART
AVR ATmega328P
void uart_init(uint32_t baud) {
uint16_t ubrr = F_CPU / 16 / baud - 1;
UBRR0H = (ubrr >> 8);
UBRR0L = ubrr;
UCSR0B = (1 << TXEN0) | (1 << RXEN0);
UCSR0C = (1 << UCSZ01) | (1 << UCSZ00); // 8-bit
}
STM32F103
void uart_init(uint32_t baud) {
RCC_APB2ENR |= (1 << 14); // USART1 clock
// PA9 TX → AF push-pull 50MHz
GPIOA_CRH &= ~(0xF << 4);
GPIOA_CRH |= (0xB << 4);
USART1_BRR = 8000000UL / baud; // простіше ніж на AVR!
USART1_CR1 = (1<<13)|(1<<3)|(1<<2); // UE+TE+RE
}
BRR на STM32 простіший — просто ділимо частоту на baud. На AVR формула складніша і залежить від режиму.
Порівняння: переривання
AVR — переривання через макрос
ISR(INT0_vect) { // макрос приховує все
// твій код
}
int main(void) {
EICRA |= (1 << ISC01); // falling edge
EIMSK |= (1 << INT0); // увімкнути INT0
sei(); // глобальні переривання
}
STM32 — переривання через таблицю векторів
void EXTI1_IRQHandler(void) { // точне ім'я з RM0008
if (EXTI_PR & (1 << 1)) {
// твій код
EXTI_PR = (1 << 1); // скидаємо прапорець
}
}
int main(void) {
AFIO_EXTICR1 &= ~(0xF << 4); // Port A для EXTI1
EXTI_FTSR |= (1 << 1); // falling edge
EXTI_IMR |= (1 << 1); // unmask
NVIC_ISER0 |= (1 << 7); // IRQ7 = EXTI1
}
На STM32 видно весь ланцюжок: GPIO → AFIO → EXTI → NVIC → ISR. Ця архітектура однакова на будь-якому Cortex-M — STM32, nRF52, LPC, SAMD. Вивчив один і розумієш всі.
Де AVR виграє
Та без перебільшення думаю є речі де AVR зручніший:
1. Простота старту. П’ять рядків і LED мигає.
2. Менше документації. Datasheet ATmega328P — 450 сторінок. RM0008 — 1136 сторінок.
3. Передбачуваність тактування. AVR завжди запускається без налаштувань.
4. Програматори дешевші. USBasp — $2. ST-Link v2 — $3-5.
Де STM32 виграє
1. Продуктивність. 16MHz
2. Периферія. Три UART, два SPI, два I2C, USB, CAN — на одному чіпі.
3. Ціна. Blue Pill — $2-3. ATmega328P окремо — $2-4 тільки за чіп.
4. Переносимість знань. Вивчив Cortex-M3 — розумієш Cortex-M4, Cortex-A (Raspberry Pi, Android). Вивчив AVR — знаєш тільки AVR.
5. Промислове застосування. ARM домінує в embedded. Вакансій набагато більше.
Покроковий план переходу
Крок 1 — Середовище (1 день): встановити arm-none-eabi-gcc, купити Blue Pill + ST-Link v2.
Крок 2 — Перший LED (1 день): написати мигання без бібліотек. Зрозуміти RCC, CRH, ODR.
Крок 3 — UART (1 день): вивести текст в термінал. Зрозуміти BRR, CR1, Alternate Function.
Крок 4 — Переривання
Крок 5 — Периферія
Крок 6 — Власний HAL (1 тиждень): загорнути все в зручний API. Тепер розумієш що роблять ST HAL і CubeMX.
Крок 7 (необов’язково, можна пропустити)— Зрозуміти, що то геморно складно і повернутись на Arduino.
Крок 8 — продовжити читати цю серію статей, або розпочати свою.
Порівняльна таблиця
| Параметр | AVR ATmega328P | STM32F103C8T6 |
| Ядро | AVR | ARM Cortex-M3 |
| Частота | 16 MHz | до 72 MHz |
| Flash | 32 KB | 64 KB |
| SRAM | 2 KB | 20 KB |
| GPIO | 23 | 37 |
| UART | 1 | 3 |
| SPI | 1 | 2 |
| I2C | 1 | 2 |
| Таймери | 3 | 7 |
| ADC | ||
| USB | немає | є (FS) |
| CAN | немає | є |
| Ціна плати | Arduino Uno ~$5-25 | Blue Pill ~$2-3 |
| Документація | 450 стор | 1136 стор |
| Складність старту | низька | середня |
| Переносимість | тільки AVR | весь ARM світ |
Головна відмінність — рівень абстракції
Arduino — це digitalWrite(13, HIGH). Зручно. Але що під капотом — невідомо.
AVR bare-metal — це PORTB |= (1 << PB5). Вже краще. Але I/O простір прихований.
STM32 bare-metal — це *(volatile uint32_t *)0×4001100C |= (1 << 13). Бачиш все. Адреса, розмір, volatile — нічого не приховано.
І це не недолік STM32. Це перевага для розуміння.
Якщо знаєш AVR — знаєш Arduino. Якщо знаєш STM32 bare-metal — знаєш як працює будь-який мікроконтролер на ARM. А ARM — це 90% embedded ринку.
Код на GitHub: github.com/pipicosim800-maker/stm32F103
Серія «STM32 з нуля без HAL» на DOU.ua
17 коментарів
Додати коментар Підписатись на коментаріВідписатись від коментарівДесь з 2007 по 2008 року фірма ST безкоштовно розсилала ( по підписці) свою плату STM32F100B-Discovery. Я отримав цю плату разом посилання на ресурси для програмування,
найбільш повним виявився Keil. Він містив приклади ініціалізації і запуску практично всіх узлів мікроконтролера і чудовий дебаггер. Зараз , по моєму, найкращим пакетом для роботи є VS Code, до якого можна під’єднати як Keil, IAR, так і практично все інше.
Я embedded-панк1970-х у США та Великій Британії, заснована на панк-рок музиці, ідеології анархії, особистій свободі та протесті проти соціальних норм. Панки вирізняються епатажним стилем (ірокези, шкіряні куртки, шпильки) та принципом DIY («Зроби сам»).
За вікіпедією Панк — це молодіжна субкультура, що виникла в середині
Звичайно, набагато простіше переказати з розумним видом своїми словами фірмовий мануал на чіп, так і стаття набігає і якісь скілли добавляються, заодно і по новому велосипед можна
винайти. На рахунок вірусів, то потрібно скачувати з Keil.com, а не російських торрентів
Чому Кeil (free 32KB) а не ІAR(free 32KB or 30 days)?
Це при тому, що є рідний Куб, і при бажанні можна прикрутити VScode
звиздіти, а не мішки тягати та обливати помиями інших
Лабай статтю, з радістю обкладем пісюнами: а що «так понубськи, ти чьо школоло а не чоткий пацан», «чому ріжеш гланди через задній прохід а не як нормальні люде», «даташіт і дурний прочитає і з розумним виглядом блінк зробе»
Такого типу коментарі — показник вашого IQ і відсутності модерації на DOU
алаверди
Просто відзеркалення вашого внутрішнього стану. За що боролись на то і напоролись. Показник IQ відносний і те, що ви до нього апелюєте означає лише одне, ви не знаєте навіщо його створили і що насправді він визначає
Судячи з вашого коментаря ви не читали ні цю серію статей ні мануал. Як людина, яка багато часу присвятила самопізнанню і вивченю психології, я розумію що ваші коментарі направлені на обезцінення моєї праці. Чому? Ну ви краще знаєте відповідь. Якщо не знаєте, то я відповім, — ви просто заздрите бо теж хотіли б написате про це і навіть спробували та Ваш єдиний топік-переказ мануала нікого не зацікавив. Я запросив би вас на інтенсиви Архітектура тіні де працюю з такими як ви та він вже тиждень як стартував ;)
І що цікаво під вашим топіком хтось написав, що у кожного embedded розробника я б дещо перефразував «embedded панка» є своя саморобочка 😀
Для ARM Cortex M0, M0+ можливо найти безкоштовний Keil (не старіше за v$.74, вищі версії урізані) з прикладами, Знаючи С не становииме проблеми розібратися в роботі ARM
з бешкоштовними вірусами і бекдорами та іншим спайваре
Прям з язика зняв
А хіба не цікаво пройти шлях і розібратись з самих основ. Побути дослідником — розібрати і спробувати скласти чи створити щось своє?
Є книга по stm32 зараз не пам’ятаю назви (в мен десь була в pdf) там інженер робить, щось схоже як я тільки бере файли з st hal. Теж наглядно і досить цікаво. Тож це поширений спосіб навчання
Взагалі не дуже розумію, нащо користувати той самий кеіл, коли є купа безкоштовних середовищ, і у кожного вендора своє. Куб, середовища на базі екліпса, середовиша на базі візуалки, середовища на баз теї, вскод.
Відкопати стюардесу
Закопати знову і продовжити страждати як справжній мужик
Складно щось додати чи спростувати 😀😀😀😀