Тема программирования микроконтроллеров ранее многократно поднималась в этом блоге, но исключительно в контексте микроконтроллеров 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, 1082 x 759, 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