Пишем под микроконтроллеры STM32 в Arduino IDE
31 июля 2017
Тема программирования микроконтроллеров ранее многократно поднималась в этом блоге, но исключительно в контексте микроконтроллеров AVR и, соответственно, Arduino. Сегодня же речь пойдет о микроконтроллере STM32F103C8T6 на базе ядра ARM 32 Cortex-M3. Вы наверняка слышали об архитектуре ARM — она используется в большинстве современных телефонов и планшетов, а также Raspberry Pi, полетных контроллерах для квадрокоптеров, и много где еще.
Список покупок
Для повторения шагов из сей заметки вам понадобится следующие железки:
- Вот такая плата на базе STM32F103C8T6 (~2.5$ с доставкой);
- Программатор ST-Link v2 для STM8 и STM32 (~2$ с доставкой);
К моменту, когда вы будете читать эти строки, ссылки могут устареть. Однако необходимые товары легко находятся по запросам «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 Кб):
Для сравнения, Arduino Nano стоит столько же и имеет похожий форм-фактор, но работает на 8-и битном микроконтроллере, имеет частоту 16 МГц, меньше пинов, лишь 32 КБ flash-памяти, 2 Кб оперативной памяти, 10-битный АЦП, 8-и битный ШИМ, по одному каналу UART, I2C и SPI, а про отладку он и вовсе слыхом не слыхивал. То есть, за те же деньги мы получаем куда более мощную железку.
Настройка Arduino IDE
Интересная особенность платы заключается в том, что под нее можно писать из Arduino IDE, используя знакомый набор процедур и классов, а также многие библиотеки, изначально написанные под Arduino. Это делает плату весьма привлекательной для начинающих.
Для программирования под данную плату нам понадобится кросс-компилятор для ARM, отладчик, стандартная библиотека C и клиент к программатору. В Arch Linux соответствующие пакеты ставятся так:
arm-none-eabi-newlib stlink
Далее учим Arduino IDE работать с нашей платой:
git clone https://github.com/rogerclarkmelbourne/Arduino_STM32.git
Мне дополнительно пришлось поправить Arduino_STM32/STM32F1/platform.txt:
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 мм, а затем адаптер подключается к программатору через соответствующий шлейф. Больше никакой путаницы!
Пробуем скомпилировать и залить такой скетч:
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 — зажигаем.
Если при прошивке возникает ошибка:
INFO src/common.c: Loading device parameters....
WARN src/common.c: unknown chip id! 0xe0042000
… проверьте, не перепутали ли вы пины CLK и IO, а также попробуйте зажать кнопку Reset на плате.
Если все сделано правильно, светодиод на плате будет мигать, а частота мигания будет меняться при внесении соответствующих изменений в код.
Поздравляю, среда разработки настроена!
Более сложный пример
Ниже приведен код посложнее, демонстрирующий использование ШИМ, аналоговых пинов, а также отладочный вывод по UART:
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);
}
Соответствующая цепь, собранная на макетной плате:
При нажатии на кнопку один светодиод гаснет, а второй загорается. Яркость свечения светодиода регулируется потенциометром. Как видите, код очень мало отличается от обычного кода для Arduino. Отличаются только названия пинов, а также диапазоны значений, с которыми работают процедуры analogRead и pwmWrite.
Еще больше примеров можно найти в File → Examples → A_STM32_Examples.
Сторонние библиотеки
Многие библиотеки уже портированы под STM32 — Wire, Servo, LiquidCrystal, и другие. А что, если попытаться использовать стороннюю библиотеку с GitHub? Для эксперимента я решил попытаться воспользоваться библиотекой LiquidCrystal_I2C, уже знакомой нам по заметке Об использовании экранчиков 1602 с I2C-адаптером.
Добавляем библиотеку в Arduino IDE:
git clone \
https://github.com/fdebrabander/Arduino-LiquidCrystal-I2C-library.git\
./LiquidCrystal_I2C
Заливаем прошивку:
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);
}
Любуемся результатом:
Стоит помнить, что экранчику нужно 5 В, а плата питается от 3.3 В. Поэтому, чтобы все заработало, плату нужно запитать от USB, а экранчик подключить к пину 5V. Экранчик оказался совместим с 3.3-вольтовой логикой, но в более общем случае может потребоваться преобразователь логических уровней.
Само собой разумеется, не всякая библиотека, написанная под Arduino, так просто возьмет и заработает под STM32. Но, по всей видимости, для многих библиотек это действительно так.
Заключение
Итак, что же мы выяснили? Плата стоит как Arduino Nano, имеет похожий форм-фактор, но является при этом куда более мощной. Писать под нее можно точно так же, как под Arduino. При этом нам доступны если и не все те же библиотеки, что под Arduino, то по крайней мере очень многие из них.
А программируете ли вы под STM32 и если да, то что для этого используете?
Дополнение: Готовим «взрослую» среду разработки под STM32 в Linux
Метки: STM32, Электроника.
Вы можете прислать свой комментарий мне на почту, или воспользоваться комментариями в Telegram-группе.