← На главную

Пишем под микроконтроллеры STM32 в Arduino IDE

Тема программирования микроконтроллеров ранее многократно поднималась в этом блоге, но исключительно в контексте микроконтроллеров AVR и, соответственно, Arduino. Сегодня же речь пойдет о микроконтроллере STM32F103C8T6 на базе ядра ARM 32 Cortex-M3. Вы наверняка слышали об архитектуре ARM – она используется в большинстве современных телефонов и планшетов, а также Raspberry Pi, полетных контроллерах для квадрокоптеров, и много где еще.

Список покупок

Для повторения шагов из сей заметки вам понадобится следующие железки:

К моменту, когда вы будете читать эти строки, ссылки могут устареть. Однако необходимые товары легко находятся по запросам «STM32F103C8T6 Development Board» и «ST-Link v2 Programmer» как на AliExpress, так и на eBay. Плата также известна под названием «STM32 Blue Pill».

Важно! Заметьте, что USB-разъем на этих платах часто не слишком надежно припаян и может быстро оторваться. Первым делом после покупки рекомендуется его подпаять.

О плате Blue Pill

Ниже приведены некоторые характеристики платы и используемой в ней микроконтроллера:

  • Микроконтроллер 32-х битный;
  • Рабочая частота 72 МГц;
  • 64 Кб flash-памяти;
  • 20 Кб оперативной памяти;
  • Мне удалось насчитать 32 GPIO;
  • 12-и битный АЦП, 10 аналоговых пинов;
  • 16-и битный ШИМ, 15 ШИМ-пинов;
  • 3 UART канала, 2 I2C шины, 2 SPI шины;
  • Возможность отладки по SWD;
  • Плата питается от 3.3 В;

Расположение пинов (кликабельно – GIF, 1082x759, 143 Кб):

Расположение пинов на плате Blue Pill

Для сравнения, Arduino Nano стоит столько же и имеет похожий форм-фактор, но работает на 8-и битном микроконтроллере, имеет частоту 16 МГц, меньше пинов, лишь 32 КБ flash-памяти, 2 Кб оперативной памяти, 10-битный АЦП, 8-и битный ШИМ, по одному каналу UART, I2C и SPI, а про отладку он и вовсе слыхом не слыхивал. То есть, за те же деньги мы получаем куда более мощную железку.

Настройка Arduino IDE

Интересная особенность платы заключается в том, что под нее можно писать из Arduino IDE, используя знакомый набор процедур и классов, а также многие библиотеки, изначально написанные под Arduino. Это делает плату весьма привлекательной для начинающих.

Для программирования под данную плату нам понадобится кросс-компилятор для ARM, отладчик, стандартная библиотека C и клиент к программатору. В Arch Linux соответствующие пакеты ставятся так:

sudo pacman -S arm-none-eabi-gcc arm-none-eabi-gdb \ arm-none-eabi-newlib stlink

Далее учим Arduino IDE работать с нашей платой:

cd ~/opt/arduino/hardware git clone https://github.com/rogerclarkmelbourne/Arduino_STM32.git

Мне дополнительно пришлось поправить Arduino_STM32/STM32F1/platform.txt:

# compiler.path={runtime.tools.arm-none-eabi-gcc.path}/bin/ compiler.path=/usr/bin/

… ибо сыпались ошибки про то, что Arduino IDE не может найти исполняемый файл arm-none-eabi-g++.

После этого если открыть Arduino IDE, то в меню Tools → Board вы обнаружите большой выбор плат на базе микроконтроллеров STM32. Выбираем Generic STM32F103C. В Tools → Upload Method выбираем STLink. Четыре пина на плате с подписями 3.3V, IO, CLK и GND подключаем к пинам 3.3V, SWDIO, SWCLK и GND программатора соответственно. Проверяем джамперы на плате. Оба джампера (так называемые boot0 и boot1) должны стоять в положении 0.

Fun fact! Чтобы постоянно не возиться с проводами при подключении программатора, выясняя, провод какого цвета к какому пину платы нужно подключить в этот раз, можно взять кусок макетки и спаять адаптер на базе разъема IDC-10. Адаптер подключается к плате через четыре угловых гнезда с шагом 2.54 мм, а затем адаптер подключается к программатору через соответствующий шлейф. Больше никакой путаницы!

Пробуем скомпилировать и залить такой скетч:

void setup() { pinMode(PC13, OUTPUT); } void loop() { digitalWrite(PC13, HIGH); delay(100); digitalWrite(PC13, LOW); delay(100); }

Fun fact! В плате Blue Pill светодиод стоит между ногой PC13 и VCC (схема [PDF]), а не между ногой и землей, как можно было бы ожидать. Поэтому, подавая HIGH на PC13, мы гасим светодиод, а подавая LOW – зажигаем.

Если при прошивке возникает ошибка:

st-flash 1.3.1 INFO src/common.c: Loading device parameters.... WARN src/common.c: unknown chip id! 0xe0042000

… проверьте, не перепутали ли вы пины CLK и IO, а также попробуйте зажать кнопку Reset на плате.

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

Поздравляю, среда разработки настроена!

Более сложный пример

Ниже приведен код посложнее, демонстрирующий использование ШИМ, аналоговых пинов, а также отладочный вывод по UART:

const int LED1 = PB8; const int LED2 = PB9; const int PTNT = PA0; const int BTN = PB7; int selected_led = LED1; bool btn_was_high = false; void setup() { pinMode(LED1, PWM); pinMode(LED2, PWM); pwmWrite(LED1, 0); pwmWrite(LED2, 0); pinMode(BTN, INPUT); pinMode(PTNT, INPUT_ANALOG); Serial.begin(115200); } void loop() { delay(100); if(digitalRead(BTN) == HIGH) { btn_was_high = true; } else if(btn_was_high) { btn_was_high = false; if(selected_led == LED1) { selected_led = LED2; pwmWrite(LED1, 0); } else { selected_led = LED1; pwmWrite(LED2, 0); } } int ptnt = analogRead(PTNT); int ptnt_mapped = map(ptnt, 0, 4095, 0, 65535); Serial.println(String("ptnt = ") + ptnt + ", ptnt_mapped = " + ptnt_mapped); pwmWrite(selected_led, ptnt_mapped); }

Соответствующая цепь, собранная на макетной плате:

Моя первая цепь с микроконтроллером STM32

При нажатии на кнопку один светодиод гаснет, а второй загорается. Яркость свечения светодиода регулируется потенциометром. Как видите, код очень мало отличается от обычного кода для Arduino. Отличаются только названия пинов, а также диапазоны значений, с которыми работают процедуры analogRead и pwmWrite.

Еще больше примеров можно найти в File → Examples → A_STM32_Examples.

Сторонние библиотеки

Многие библиотеки уже портированы под STM32 – Wire, Servo, LiquidCrystal, и другие. А что, если попытаться использовать стороннюю библиотеку с GitHub? Для эксперимента я решил попытаться воспользоваться библиотекой LiquidCrystal_I2C, уже знакомой нам по заметке Об использовании экранчиков 1602 с I2C-адаптером.

Добавляем библиотеку в Arduino IDE:

cd ~/Arduino/libraries git clone \ https://github.com/fdebrabander/Arduino-LiquidCrystal-I2C-library.git\ ./LiquidCrystal_I2C

Заливаем прошивку:

#include <LiquidCrystal_I2C.h> LiquidCrystal_I2C lcd(0x3F, PB6, PB7); void setup() { lcd.begin(); lcd.setCursor(0, 0); lcd.print("Current time:"); } void loop() { delay(100); lcd.setCursor(0, 1); unsigned long tstamp = millis(); int h = tstamp / 1000 / 60 / 60; int m = (tstamp / 1000 / 60) % 60; int s = (tstamp / 1000) % 60; String line = String(h) + "h " + String(m) + "m " + String(s) + "s"; int len = line.length(); while(len < 16) { line += " "; len++; } lcd.print(line); }

Любуемся результатом:

Использование библиотеки LiquidCrystal_I2C на STM32

Стоит помнить, что экранчику нужно 5 В, а плата питается от 3.3 В. Поэтому, чтобы все заработало, плату нужно запитать от USB, а экранчик подключить к пину 5V. Экранчик оказался совместим с 3.3-вольтовой логикой, но в более общем случае может потребоваться преобразователь логических уровней.

Само собой разумеется, не всякая библиотека, написанная под Arduino, так просто возьмет и заработает под STM32. Но, по всей видимости, для многих библиотек это действительно так.

Заключение

Итак, что же мы выяснили? Плата стоит как Arduino Nano, имеет похожий форм-фактор, но является при этом куда более мощной. Писать под нее можно точно так же, как под Arduino. При этом нам доступны если и не все те же библиотеки, что под Arduino, то по крайней мере очень многие из них.

А программируете ли вы под STM32 и если да, то что для этого используете?

Дополнение: Готовим «взрослую» среду разработки под STM32 в Linux