Salut, Habr.
L'avantage unique traditionnel de la plate-forme Arduino a été appelé (et maintenant il est parfois appelé, bien que ce soit déjà faux - et nous expliquerons pourquoi) en abaissant le seuil d'entrée dans le développement de microcontrôleurs au niveau des connaissances de base de C / C ++ et de l'électronique à l'échelle «connectez la LED dans la bonne polarité».
Demandez à n'importe quel partisan Arduino actif - et ils vous expliqueront rapidement ce que vous pouvez, bien sûr, écrire sous STM32 ou nRF52, mais il n'y a aucun avantage réel, mais des nuits blanches vous attendent sur des centaines de pages de fiches techniques et de feuilles de fonctions sans fin avec de longs noms obscurs.
Il est vraiment difficile de surestimer les mérites d'Arduino en abaissant le seuil d'entrée - cette plate-forme est née au milieu des années zéro, et après 2010, elle a gagné en popularité auprès des amateurs. Il n'y avait pas d'alternatives spéciales à l'époque - les processeurs basés sur les cœurs Cortex-M viennent d'apparaître, comparés aux AVR, ils étaient assez compliqués même pour les développeurs professionnels, et les cartes de débogage pour la plupart des fournisseurs coûtent des centaines de dollars ou plus (et en général, le prix à payer dans l'industrie pour le débogage sur un contrôleur à 5 $ à 500 $, je n'ai été très surpris par personne).
Cependant, le gros problème avec Arduino est que son développement au cours des 10 dernières années ressemble le plus à certains modèles AvtoVAZ:
Comme je prévois une longue introduction, maintenant, afin que vous puissiez imaginer la partie pratique, je donnerai le
texte complet du programme, y compris l'initialisation du processeur STM32 et le clignotement de la LED. Le programme est écrit pour l'ARM Mbed OS:
#include "mbed.h"
DigitalOut myled(LED1);
int main() {
while(1) {
myled = 1; // LED is ON
wait(0.2); // 200 ms
myled = 0; // LED is OFF
wait(1.0); // 1 sec
}
}
? ? ? ? , .
, 2010 … . AVR, 8- , — 2017 12 % ( Aspencore), : AVR, PIC STM8. , — , ..
ATMega 12 % — 32- Cortex-M / (STM32F030 16-64 4-8 30-50 ). , - .
64- — , , Cortex-A. , , Cortex-M ? ( , — ), . AVR , STM32F1 STM32L1 , - Infineon NXP…
, — , STMicro : SPL, HAL LL. , , , .
.
, . , — , , , . ,
(, , , loop(), , - — , - , - ).
— , « », :
- HAL — . . , -, (, , - STM32L072, STM32L151 STM32L451 — , ), -, ( , , , STM32, , ). — , RIOT API SAUL, ; , - .
- — , , - . , , .
- — , . , . , , , . , .
- IPC — . , , , , , , , , , - - (, , : , , , , ).
- — API , , . , , , , , , , API .
- — « » .
, — API POSIX.
, . , :
- FreeRTOS — , , . — . ( , )
- Contiki OS — , , , 6LoWPAN. , (, ). Contiki NG — , .
- RIOT OS — , Contiki. ( ATMega) . . C. , , . , , .
- ARM Mbed — ( , Apache 2.0) ARM Holdings. 2.0, 5.x. C++ API. , . , Mbed.
- TI-RTOS — Texas Instruments, , TI - , , . , API .
- , arm-none-eabi-gcc. , RIOT Makefile', Visual Studio, . ARM Mbed (
mbed-cli),
PlatformIO, mbed-cli Keil uVision Makefiles.
— , Arduino. , gdb JTAG/SWD-.
, ? , ?
. . ,
.
, RIOT OS « » :
- MinGW, arm-none-eabi-gcc GNU make ( Windows 10 , Ubuntu)
- RIOT
- cd RIOT/examples/hello-world
- make BOARD=nucleo-l152re
- HEX- Nucleo ( ST-Link )
, main.c, :
#include <stdio.h>
int main(void)
{
puts("Hello World!");
printf("You are running RIOT on a(n) %s board.\n", RIOT_BOARD);
printf("This board features a(n) %s MCU.\n", RIOT_MCU);
return 0;
}
? , ? SPL? , ?
.
,
. — ARM Mbed .
( , , b2b-, Nucleo-L152RE BME280 OPT3001)

1)
mbed.com.
2) «Compiler» - . , . , «Add board» Nucleo, ( L152RE, , Nucleo, ). , Nucleo .

3) New → New Program. Mbed - , Nucleo-L152 . , , 5.9.5, — «Empty program».
— -, mbed, -, - main.cpp. #include, mbed-os.
:
- «Import», «Click here to import from URL», ( , Mbed, )
- «Library»
- «Import»

→ «New file» → main.cpp. :
#include "mbed.h"
DigitalOut led(LED1);
int main()
{
printf("Hello World !\n");
while(1) {
wait(1); // 1 second
led = !led; // Toggle LED
}
}
(LED1 — Nucleo )
4) Ctrl-D ( «Compile»), -, . Nucleo USB- ( : Nucleo mini-USB, ), 540 «Node_L152RE». MBED.HTM, , .
, , BIN- HEX- , Mbed , .
. Nucleo , — LED1.
5) BME280, ?
, «Import Library» (, , , — ). , Library, («Target path»).

, , .
6) , :
#include "mbed.h"
#include "BME280.h"
DigitalOut led(LED1);
BME280 sensor_bme(D14, D15);
int main()
{
while(1) {
wait(1); // 1 second
led = !led; // Toggle LED
printf("%2.2f degC, %04.2f hPa, %2.2f %%\r\n", sensor_bme.getTemperature(), sensor_bme.getPressure(), sensor_bme.getHumidity());
}
}
, , , Nucleo I2C-. , .. SDA SCL ( STM32L1 I2C, ), , , I2C_SDA I2C_SCL . .
7) . — +3,3 , , SDA, SCL. STM32, 3,3-, .

8) «Compile», BIN- Nucleo.
8) ??????
( —
Termite, , Nucleo; COM-. 9600 /)
9) PROFIT!!!

. , , « , », , .
— , . -, , while(1) 1- — , 1 , 1 , .
-, 9600 / — - , 2018 , 115200.
: Serial, , .
Serial pc(SERIAL_TX, SERIAL_RX);
pc.baud(115200);
while(1) , , . Mbed , (
EventQueue), ( call) ( call_every), .
:
#include "mbed.h"
#include "BME280.h"
DigitalOut led(LED1);
BME280 sensor_bme(D14, D15);
EventQueue eventQueue(/* event count */ 50 * EVENTS_EVENT_SIZE);
void printTemperature(void)
{
printf("%2.2f degC, %04.2f hPa, %2.2f %%\r\n", sensor_bme.getTemperature(), sensor_bme.getPressure(), sensor_bme.getHumidity());
led = !led; // Toggle LED
}
int main()
{
eventQueue.call_every(1000, printTemperature); // run every 1000 ms
eventQueue.dispatch_forever();
return 0;
}
, . , ( ), — , - . eventQueue ( — , 50 ), , , , .
?
, while(1) , .
, OPT3001. , …
OPT3001 — ( , ), TSL2561 , Mbed . , ( ), —
https://github.com/ashok-rao/mbed-OPT3001.
Import, «Click here to import from URL», URL , «Library» — «Import».
. .
, . , « OPT3001.cpp, »,
( , OPT3001).
: Import → Click here to import from URL →
github.com/olegart/mbed_opt3001 → Library → Target Path = → Import.
:
#include "mbed.h"
#include "BME280.h"
#include "OPT3001.h"
DigitalOut led(LED1);
BME280 sensor_bme(D14, D15);
OPT3001 sensor_opt(D14, D15);
EventQueue eventQueue(/* event count */ 50 * EVENTS_EVENT_SIZE);
Serial pc(SERIAL_TX, SERIAL_RX);
void printTemperature(void)
{
pc.printf("%2.2f degC, %04.2f hPa, %2.2f %%\r\n", sensor_bme.getTemperature(), sensor_bme.getPressure(), sensor_bme.getHumidity());
pc.printf("%ld lux\r\n", sensor_opt.readSensor());
led = !led; // Toggle LED
}
int main()
{
pc.baud(115200);
eventQueue.call_every(1000, printTemperature); // run every 1000 ms
eventQueue.dispatch_forever();
return 0;
}
Compile, , Nucleo, 115200…

PROFIT!!!
:
, , , — , .
, , , . , , .
Nucleo «IDD», , , ( , — , ).

L152 10 , - LED1, ( 2-3 ). - , , ?..
, . , , , — , , eventQueue.call_every , . STM32L151 , — ,
RTC ( L151CB-A , RTC_SSR), — .
, dispatch_forever(), — , , , , .
, ? , , — ?
LowPowerTicker, RTC, — . LowPowerTicker, sleep() — ( , , , — , , - , , ).
: , - — , ( OPT3001, , 100 ). printf — , . , , .
, while(1), — . , while(1) ?
, EventQueue, .
#include "mbed.h"
#include "BME280.h"
#include "OPT3001.h"
DigitalOut led(LED1);
BME280 sensor_bme(D14, D15);
OPT3001 sensor_opt(D14, D15);
EventQueue eventQueue(/* event count */ 50 * EVENTS_EVENT_SIZE);
Serial pc(SERIAL_TX, SERIAL_RX);
LowPowerTicker lpTicker;
void printTemperature(void)
{
pc.printf("%2.2f degC, %04.2f hPa, %2.2f %%\r\n", sensor_bme.getTemperature(), sensor_bme.getPressure(), sensor_bme.getHumidity());
pc.printf("%ld lux\r\n", sensor_opt.readSensor());
led = !led; // Toggle LED
}
void tickerIRQ (void)
{
eventQueue.call(printTemperature);
}
int main()
{
pc.baud(115200);
lpTicker.attach(tickerIRQ, 1); // every second
while(1)
{
eventQueue.dispatch(0);
sleep();
}
}
? : Low Power Ticker, . , eventQueue.call, ( , .. , — call ). .call , while(1), — dispatch , , sleep(), .
.
→ → → call → → dispatch → → sleep() .
PROFIT???

PROFIT!!!
( , 0,57 — , . Mbed, , STM32L1: Digital In , Analog In , - - . , Nucleo JTAG -)
- . , « RTOS» , , .
— 55,1 9,2 ( , «Build details» ), — , 2- STM32F103CB 128 20 . , , STM32F030F4P6 16 4 — RIOT OS .
, , float printf . —
, . malloc , malloc .
P.S. —
Mbed.
P.P.S. :
Nucleo-L152RE ( Nucleo / Discovery , ,
— , , ),
BME280 (: , , , BMP280, ). OPT3001 — , TI .
, RTOS , — Mbed , , - , RIOT 2018.07 ( ), .
, Arduino « », — , , , - ( , , ).
, , . , , , — , . , « », — , , , , 2018 , , , , - .
, — , . , , . .
, , . - , AVR.
…

?!
, 2018 ! ?