Hinweise zu Arduino

Als Ergänzung zu meiner STM32 Anleitung gebe ich hier Tipps zum Umgang mit Arduino.

Die Arduino richtet sich primär an Bastler, die schnelle Ergebnisse wollen. Das Framework vereinheitlicht die Programmierung unterschiedlicher Mikrocontroller-Boards, so weit es geht. Auf diese Weise kann man nicht alle Funktionen der Mikrocontroller nutzen, allerdings hindert Arduino niemanden daran, das Ding teilweise am Framework vorbei zu programmieren. Ein großer Vorteil ist die Verfügbarkeit zahlreicher Bibliotheken.

Wenn du im Internet etwas für STM32duino findest, musst du zwischen dem aktuellen STM32duino Core von ST und dem alten STM32duino Core von Roger Clarks unterscheiden. Sie sind nur teilweise kompatibel.

STM32duino Core von ST

Für diesen STM32duino Core muss dein Mikrocontroller mindestens 32 KiB Flash und 8 KiB RAM haben. Nimm besser ein größeres Modell.

Falls du mit STM32duino programmieren möchtest, kannst du so anfangen:

Damit hast du Zugriff auf das Arduino Framework, das CMSIS von ARM und die LL/HAL Bibliotheken von ST.

Lies die Dokumentation von ST (auch das Wiki) und die Dokumentation von Arduino.

Für den Upload werden folgende Adapter direkt unterstützt: ST-Link, Black Magic Probe und DAPLink. Zusätzlich unterstützt die IDE auch J-Link und Bootloader (seriell und USB), wenn der STM32CubeProgrammer installiert ist.

Debuggen geht aber nur mit ST-Link.

Taktfrequenz

Der Code für die generischen Boards und für Nucleo Boards nutzt standardmäßig den internen HSI Oszillator, keinen Quarz. Boards mit Quarz benutzen den HSE Oszillator.

Alle Boards werden mit der höchstmöglichen Taktfrequenz betrieben, die sich aus ihrer Standard Beschaltung ergibt. Als Beispiel picke ich mal den alten STM32F103 heraus:

An dieser Stelle möchte ich erwähnen, dass die internen Oszillatoren nur in Kombination mit dem "Clock Recovery System" (CRS) für USB taugen. Dabei wird die Taktfrequenz an den Host (PC) angeglichen. Der STM32F103 hat aber kein CRS!

F_CPU ist als Alias für die Variable SystemCoreClock definiert, die mit der tatsächlichen Taktfrequenz der CPU initialisiert wird.

Um die Taktfrequenz zu ändern soll man die Funktion SystemClock_Config() überschreiben. Darin kannst du wahlweise direkte Registerzugriffe oder LL/HAL Bibliotheken benutzen. Beachte dabei die notwendige Prozedur aus dem Referenzhandbuch des STM32, einschließlich dem "voltage scaling" (falls vorhanden) und den "wait states" für den Flash Speicher.

// Change system clock to 32 MHz 
void SystemClock_Config(void) {
   
    ... model specific code

    SystemCoreClock=32000000;
    SysTick_Config(SystemCoreClock/1000);
}
Ein nachträgliches Ändern zur Laufzeit ist zu vermeiden, weil manche Bibliotheken damit nicht zurecht kommen.

Zum Stromsparen bieten sich eher die Befehle __WFI() und __WFE() aus dem Power Management, sowie die STM32LowPower Bibliothek an. Oft ist "schnell rechnen und schlafen" effizienter als "langsam dauerhaft laufen".

Serielle Ports

In der Board-Konfiguration taucht der Begriff "generic serial" auf, damit ist die Variable Serial gemeint. Wenn sie aktiviert ist, dann verweist sie auf den bevorzugten seriellen Port des Boardes. Beim Nucleo64 Board ist Serial=Serial2, weil dieser mit dem ST-Link Adapter verbunden ist.

Für die anderen Ports muss man selber Instanzen von HardwareSerial anlegen. Welche Pins dazu geeignet sind, steht im Datenblatt des Mikrocontrollers. Kopiervorlage:

HardwareSerial Serial1(PA10,PA9);
HardwareSerial Serial2(PA3,PA2);
HardwareSerial Serial3(PB11,PB10);
HardwareSerial Serial4(PC11,PC10);
HardwareSerial Serial5(PD2,PC12);

void setup() {
    Serial1.begin(115200); 
    Serial2.begin(115200); 
    Serial3.begin(115200);
    Serial4.begin(115200);
    Serial5.begin(115200);
}

Virtueller COM Port

Der virtuelle COM Port über USB (auch VCP oder CDC genannt) ist unter dem Namen SerialUSB nutzbar, sofern in der Board-Konfiguration aktiviert. Zusätzlich kann der "generic serial" darauf referenzieren, dann ist Serial=SerialUSB. Die Einstellung der Baudrate kann entfallen, weil sie keine Rolle spielt.

Das folgende Beispiel lässt die LED an PA5 blinken und gibt dabei abwechselnd die Worte "Tick" und "Tack" aus:

void setup() {
    pinMode(PA5, OUTPUT);
}

void loop() {
    digitalWrite(PA5, LOW);
    SerialUSB.println("Tick");
    delay(500);

    digitalWrite(PA5, HIGH);
    SerialUSB.println("Tack");
    delay(500);
}

Die Ausgabe kann man mit dem seriellen Monitor, einem Terminal-Programm oder unter Linux einfach mit dem Befehl cat /dev/ttyACM0 anzeigen. Die Ausgabe findet nur statt, wenn das DTR Signal (im Terminalprogramm) eingeschaltet ist. Es sei denn, man ruft vorher SerialUSB.dtr(false) auf, dann wird das DTR Signal ignoriert.

Bitte beachte meinen Hinweis zu CDC Geräten unter Linux, er erspart dir womöglich eine langwierige Fehlersuche.

Historische Informationen

Das Arduino Framework begann 2005 mit kleinen 8 Bit AVR Mikrocontrollern als Fork von Wiring (die ganze hässliche Story).

Die ersten inoffizellen 32 Bit Boards kamen 2009 von der Firma Leaflabs: Das "Maple" Board und das kleinere "Maple Mini", beide mit STM32F103C8T6. Leaflabs musste dazu einen anderen Compiler und eigene Bibliotheken in die Arduino IDE integrieren. Kurz danach kam das ähnliche Blue Pill Board auf den Markt, das heute noch angeboten wird.

Das erste "offizielle" 32 Bit Board von Arduino war das Arduino Due von 2012. Dieses Board wurde von den Makern weitgehend ignoriert, vielleicht weil es viel zu teuer ist. Erst 2015 nahmen die offiziellen 32 Bit Boards mit dem Arduino Zero langsam Fahrt auf.

Als Leaflabs den Produktsupport für die Maple Boards im Jahr 2016 beendete, übernahm Roger Clarks wesentliche Teile des Codes in sein STM32duino Projekt. Er hielt damit die Unterstützung für die STM32F103 am Leben. Der Compiler vom Arduino Due Board unterstützt auch STM32, so dass Roger diesen Compiler nun mit benutzen konnte. Dan Drown hat den Code von Roger Clarks so verpackt, dass man ihn bequem mit dem Boardmanager der IDE installieren kann.

Im Jahr 2018 übernahm die Firma ST die Rechte am Namen "STM32duino" und schrieb den Code auf Basis des Cube HAL Frameworks um. So konnte ST schnell fast alle STM32 Modelle unterstützen. Die damit erzeugten Programme sind größer und etwas langsamer als mit dem alten Code.

STM32duino Core von Roger Clarks

So installierst du den alten STM32duino Core von Roger Clarks:

Lies die Dokumentation von Roger Clarks und die Dokumentation von Arduino.

Beim STM32duino Core von Roger Clarks ist das "Serial" Objekt ein virtueller COM Port über den USB Anschluss des Mikrocontrollers (PA11,PA12). Für die echten seriellen Schnittstellen (USART) gibt es die Objekte Serial1, Serial2 und Serial3.

Die Pins PA13, PA14, PA15, PB3 und PB4 sind standardmäßig für die ungenutzte JTAG Schnittstelle reserviert. Das kann man so ändern:

void setup() {
    // Disable both SWD and JTAG to free PA13, PA14, PA15, PB3 and PB4
    afio_cfg_debug_ports(AFIO_DEBUG_NONE);
    
    or:      
    
    // Disable JTAG only to free PA15, PB3 and PB4. SWD remains active
    afio_cfg_debug_ports(AFIO_DEBUG_SW_ONLY);
}

Dieser Arduino Core basiert nicht auf dem CMSIS, daher heißen dort die Konstanten für die Register und Bitmasken etwas anders. Werfe dazu ggf. einen Blick in die Dateien packages/stm32duino/hardware/STM32F1/2022.9.26/system/libmaple/stm32f1/include/series/*.h

Für den Upload werden folgende Adapter unterstützt: ST-Link, J-Link, Black Magic Probe, USB-UART (Serieller Bootloader), USB (STM32duino Bootloader).

STM32duino Bootloader

Für einige STM32F103 Boards steht der STM32duino Bootloader zur Verfügung, der das Hochladen von Programmen über den USB Anschluss des Mikrocontrollers ermöglicht. Er belegt die ersten 8 KiB vom Flash Speicher. Für das Blue Pill Board ist die Datei generic_boot20_pc13.bin die richtige.

Der STM32duino Bootloader ist nur eine Sekunde lang nach dem Loslassen des Reset-Knopfes aktiv. Dies zeigt er durch schnelles Blinken der Status-LED an. Innerhalb dieser kurzen Zeit kann man mit der Arduino IDE einen Sketch hochladen. Im Gerätemanager von Windows erscheint der Bootloader als "libusb-win32 devices/Maple DFU". Nach einer Sekunde verschwindet er wieder, danach erscheint der virtuelle serielle COM Port des Sketches. Wegen des schwierigen Timings finde ich den Bootloader unhandlich und benutze ihn nicht gerne.

Damit Windows den USB Bootloader wie gezeigt erkennt, braucht es einen Treiber aus dem Arduino_STM32 Paket. Führe zur Installation die Datei drivers/win/install_driver.bat aus. Linux und Mac OS brauchen keinen Treiber. Zum Hochladen wird das Programm dfu-util verwendet, welches in beiden STM32duino Cores enthalten ist (keine separate Installation nötig).

STM32 Anleitungen