C und C++ mit dem Pico SDK

Die Sprache, in der Betriebssysteme, Treiber und alle Spiele auf dieser Seite geschrieben sind. Das Buch beginnt bei null – erst mit einer kleinen Buchbibliothek, damit schnell etwas auf dem Bildschirm passiert, dann direkt an die Hardware.

Was du lernst

  • VS Code mit der offiziellen Raspberry-Pi-Pico-Erweiterung einrichten
  • Konsole, Variablen, Schleifen, Entscheidungen, Funktionen, Arrays und Strukturen
  • Zeichnen, Tasten, LEDs, Töne, flimmerfreie Grafik, Sprites und Beschleunigungssensor
  • ein komplettes Spiel, dann Zeiger, Speicher und Programme aus mehreren Dateien
  • die Hardware direkt: GPIO, PWM, ADC, I²C, SPI und DMA fürs Display, Interrupts, Timer, zweiter Kern, Flash
  • zum Schluss: Programmieren mit KI

Du brauchst keine Vorkenntnisse, auch kein Python. Jedes Kapitel hat dieselbe Form: Worum geht’s, Erklärung mit kurzen Programmen, ein Abschnitt zum Ausprobieren, Übungsaufgaben in drei Stufen (⭐ bis ⭐⭐⭐) und „Das Wichtigste in Kürze“. Die Lösungen stehen im Anhang.

So sieht ein Programm aus

Das ist das Programm, das schon in der Vorlage steht. Es löscht den Bildschirm, schreibt „Hallo!“ in großer Schrift und zeigt das Bild an:

#include "pbc.h"

int main(void) {
    pbc_init();
    pbc_clear(PBC_BLACK);
    pbc_text24("Hallo!", 80, 120, PBC_WHITE);
    pbc_show();
    while (true) {
        sleep_ms(1000);
    }
}
Bildschirm des PBC+: weißer Text „Hallo!“ auf Schwarz
  • #include "pbc.h" holt die Buchbibliothek ins Programm – und mit ihr alles, was die Beispiele aus dem SDK brauchen.
  • pbc_init() steht immer als Erstes in main. Es richtet Display, Tasten, LEDs, Ton, Sensor und die Konsole ein.
  • Gezeichnet wird zuerst in einen Bildpuffer. Erst pbc_show() bringt das Bild aufs Display.
  • main darf nie enden. Ohne die Endlosschleife hält der Prozessor an, und der PBC+ reagiert auf nichts mehr – auch nicht auf Run in VS Code.

Das Buch arbeitet in C. Wer danach in C++ weitermachen will, braucht nichts Neues: Das Pico SDK und die Werkzeugkette sind dieselben. Die Vorlage ist schon für C und C++ eingerichtet, und pbc.h lässt sich auch aus C++ benutzen.

Einrichten Schritt für Schritt

Beim ersten Mal dauert das etwa eine halbe Stunde, weil viel heruntergeladen wird. Danach ist ein neues Programm mit zwei Klicks auf dem Gerät. Alles läuft unter Windows, macOS und Linux.

1. VS Code und die Pico-Erweiterung

  1. VS Code von code.visualstudio.com herunterladen und installieren. Die Voreinstellungen passen.
  2. In VS Code links auf Erweiterungen klicken (vier Quadrate) oder Strg + Umschalt + X drücken (Mac: Cmd + Umschalt + X).
  3. Nach Raspberry Pi Pico suchen, die Erweiterung mit dem Herausgeber Raspberry Pi wählen und Installieren klicken.
  4. Außerdem den Serial Monitor von Microsoft installieren, falls er nicht schon dabei ist. Damit siehst du später die Ausgaben von printf.

Die Erweiterung besorgt den Compiler, das Pico SDK und das Werkzeug zum Aufspielen selbst. Unter Windows ist damit alles da. Unter macOS braucht sie die Kommandozeilen-Werkzeuge von Apple (xcode-select --install), unter Linux (außer Raspberry Pi OS) Python ab 3.10, Git ab 2.28 und Tar. Unter Linux braucht Run außerdem eine udev-Regel für den USB-Zugriff. Die Einzelheiten stehen in Anhang E des Buchs.

2. Die Vorlage importieren

  1. pbc-vorlage.zip herunterladen und entpacken – am besten in einen Pfad ohne Leerzeichen und Umlaute, etwa C:\PicoBoy\pbc-projekt oder ~/PicoBoy/pbc-projekt.
  2. In VS Code links auf das Symbol der Pico-Erweiterung klicken, dann auf Import Project.
  3. Als Location den Ordner pbc-projekt wählen, als SDK-Version 2.2.0. Den Rest lassen, wie er ist, und Import klicken.

Beim ersten Import lädt die Erweiterung das SDK, den Compiler und weitere Werkzeuge – zusammen mehrere hundert Megabyte. Das dauert einige Minuten. Danach siehst du im Explorer die Dateien der Vorlage:

Datei oder OrdnerWas steht darin?
main.cdein Programm – in den Teilen I bis III änderst du nur diese Datei
pbc/die Buchbibliothek: Befehle für Bildschirm, Tasten, LEDs, Ton und Sensor
CMakeLists.txtdie Bauanleitung: welche Dateien zum Programm gehören und wie es heißt
pico_sdk_import.cmakesucht das Pico SDK; nicht ändern
bild2c.htmlwandelt Bilder in C-Code um (Kapitel 15); öffnet sich im Browser
build/entsteht beim ersten Bauen; hier landet die .uf2-Datei

3. Bauen mit Compile

Unten in der blauen Statusleiste auf Compile klicken. Das Terminal zeigt, was passiert: Erst plant CMake anhand der CMakeLists.txt den Bau, dann übersetzt der Compiler jede .c-Datei, zuletzt fügt der Linker alles zu einem Programm zusammen. Das erste Bauen dauert etwa eine Minute, weil auch die Bibliothek und Teile des SDK übersetzt werden. Danach geht es in wenigen Sekunden. Das Ergebnis ist build/mein_programm.uf2.

4. Das erste Mal aufspielen: BOOT und RES

Rückseite des PBC+ mit Beschriftung: USB-C, zwei AAA-Batterien, RP2350, BOOT und RES über dem Schiebeschalter BAT/USB

BOOT und RES sitzen auf der Rückseite, direkt über dem Schiebeschalter BAT/USB. Der Schalter wählt die Stromquelle: BAT für die zwei AAA-Batterien, USB für das Kabel. Steht er auf USB und kein Kabel steckt, ist der PBC+ aus.

  1. Den PBC+ mit dem USB-Kabel an den Computer anschließen.
  2. BOOT gedrückt halten, kurz RES tippen, BOOT loslassen. Ein neues Laufwerk erscheint.
  3. Die Datei build/mein_programm.uf2 auf dieses Laufwerk ziehen. In VS Code findest du sie mit Rechtsklick → Reveal in File Explorer (Mac: Reveal in Finder).
  4. Das Laufwerk verschwindet von selbst, der PBC+ startet neu und zeigt „Hallo!“.

5. Ab jetzt: Run

Ab dem zweiten Mal reicht Run in der Statusleiste. VS Code baut, falls nötig, und spielt das Programm über das Kabel auf. Das klappt, weil jedes Programm aus der Vorlage über USB auf diesen Befehl hört und sich selbst in den Bootmodus schaltet. Läuft gerade MicroPython oder ein fremdes Spiel, geht es nur über BOOT und RES.

So arbeitest du ab jetzt: main.c ändern → speichern (Strg + S) → Run. Lass die Vorlage pbc-projekt als Sicherung unverändert und arbeite in einer Kopie, die du ebenfalls mit Import Project öffnest.

Kaputt machen kannst du nichts. Der Bootmodus steckt fest im Chip und lässt sich durch kein Programm überschreiben. MicroPython oder ein Spiel kommen genauso zurück wie dein Programm: als .uf2-Datei. Hast du auf dem PBC+ Python-Programme oder Dateien, die du behalten willst? Dann sichere sie vorher – im PBC+ Studio unter Dateien → Flash-Backup erstellen (.uf2)….

Wenn es nicht klappt

Was passiert?Was hilft?
Import Project meldet einen Fehler beim Herunterladen.Internetverbindung prüfen, VS Code neu starten, Import wiederholen. Schon Geladenes wird nicht noch einmal geladen.
Beim Bauen erscheint No such file or directory mit einem Pfad.Liegt der Ordner in einem Pfad mit Leerzeichen oder Umlauten? Verschieben und VS Code neu öffnen.
Das Terminal zeigt error: und eine Zeilennummer.Ein Fehler im Programm – siehe unten „Fehlermeldungen lesen“.
Run findet kein Gerät.Läuft noch MicroPython oder ein anderes Programm? Dann einmal über BOOT und RES aufspielen. Auch ein reines Ladekabel ohne Datenleitungen kann schuld sein.
Nach dem Aufspielen bleibt der Bildschirm schwarz.Fehlt pbc_show()? Sonst BOOT halten, RES tippen und das Vorlagenprogramm neu aufspielen.
Das Laufwerk erscheint nicht.BOOT wirklich festhalten, während du RES tippst. Anderes Kabel oder anderen USB-Anschluss probieren.

Die Buchbibliothek pbc

Damit es ab Kapitel 3 um C geht und nicht um Register, liegt der Vorlage eine kleine Bibliothek bei. Sie versteckt Display, Tasten, Ton, LEDs und Sensor hinter einfachen Befehlen. Grundlage sind die Treiber der MicroPython-Firmware des PBC+. Wer das Python-Buch kennt, findet die Befehle unter denselben Namen wieder: aus pbc.fill_rect(…) wird pbc_fill_rect(…), aus pbc.RED wird PBC_RED.

BefehlWas er tut
pbc_init()richtet alles ein; steht als Erstes in main
pbc_show()bringt den Bildpuffer aufs Display (knapp 29 ms)
pbc_clear(farbe)füllt das ganze Bild mit einer Farbe
pbc_pixel, pbc_line, pbc_hline, pbc_vlinePunkt und Linien
pbc_rect, pbc_fill_rectRechteck als Umriss oder gefüllt
pbc_circle, pbc_fill_circle, pbc_ellipse, pbc_fill_ellipseKreise und Ellipsen um einen Mittelpunkt
pbc_rgb(r, g, b)mischt eine Farbe aus Rot, Grün, Blau (je 0–255) im Format RGB565; dazu elf fertige Farben wie PBC_RED
pbc_text, pbc_text12/18/24Text: feste 8 × 8-Schrift oder drei Proportionalschriften; Rückgabe ist das x hinter dem Text
pbc_text18_width(text)Breite eines Texts in Pixeln, etwa zum Zentrieren (für jede Schrift eine)
pbc_draw_image(&bild, x, y)zeichnet ein Bild, das bild2c.html in C-Code umgewandelt hat; Teile davon können durchsichtig sein
pbc_pressed_a() … pbc_pressed_center()true, solange die Taste gedrückt ist
pbc_was_pressed_a() …true genau einmal pro Druck, auch wenn das Programm gerade beschäftigt war
pbc_wait_for_button()wartet, bis eine Taste gedrückt und losgelassen wurde
pbc_led_red(true), pbc_led_yellow, pbc_led_greendie drei Status-LEDs an oder aus; pbc_leds_off() schaltet alle aus
pbc_rgb_led(r, g, b)Farbe der RGB-LED; pbc_rgb_led_off() schaltet sie aus
pbc_tone(frequenz, ms)spielt einen Ton und wartet nicht; ms = 0 heißt: bis pbc_tone_off()
pbc_accel_x(), pbc_accel_x_g() …Beschleunigungssensor in m/s² oder in g; flach auf dem Tisch ist z = 1 g
pbc_battery_voltage()Spannung in Volt; pbc_is_on_usb() sagt, ob das Kabel die Quelle ist
pbc_backlight(wert)Helligkeit des Displays, 0 bis 255
pbc_millis()Millisekunden seit dem Start
pbc_random(min, max)Zufallszahl, beide Grenzen eingeschlossen
pbc_input, pbc_input_int, pbc_input_floatliest eine Zeile, eine ganze Zahl oder eine Kommazahl aus der Konsole
sleep_ms(ms), printf, snprintfaus dem Pico SDK und Standard-C; kommen über pbc.h mit

Das Display hat 240 × 280 Pixel, (0, 0) ist oben links. Die Ecken sind rund: Was näher als etwa 20 Pixel an einer Ecke liegt, ist abgeschnitten.

Schema: Dein Programm zeichnet mit pbc_clear, pbc_fill_circle, pbc_text18 in den Bildpuffer im RAM (240 × 280 Zahlen, je 2 Byte, 134 400 Bytes). pbc_show() schickt ihn über SPI ans Display.

Der Bildpuffer ist der Grund, warum nichts flackert: Das Programm malt das ganze Bild im Speicher fertig, und pbc_show() schickt es in einem Stück ans Display. Die Bibliothek ist dabei kein Geheimnis. Sie besteht aus zwei C-Dateien: pbc_zeichnen.c rechnet ohne Hardware, pbc_geraet.c spricht mit der Hardware. Kapitel 20 schaut hinein, Teil IV baut die Hardware-Hälfte Stück für Stück selbst nach.

Beispiele aus dem Buch

Diese Programme stehen genau so im Buch. Die Bilder daneben sind keine Fotos, sondern das, was das Programm beim Prüflauf auf dem PC gezeichnet hat – mit demselben Zeichen-Teil der Bibliothek wie auf dem Gerät.

Ein Haus mit Sonne (Kapitel 6)

Zeichnen mit Rechtecken, Linien und Kreisen, eigene Farben mit pbc_rgb und ein Text, der mit pbc_text18_width zentriert wird.

// Ein Haus mit Sonne
#include "pbc.h"

int main(void) {
    pbc_init();
    uint16_t himmel = pbc_rgb(130, 200, 250);
    uint16_t wiese = pbc_rgb(40, 150, 40);
    uint16_t wand = pbc_rgb(230, 200, 150);
    uint16_t holz = pbc_rgb(140, 70, 20);

    // Himmel, Sonne, Wiese
    pbc_clear(himmel);
    pbc_fill_circle(185, 60, 25, PBC_YELLOW);
    pbc_fill_rect(0, 215, PBC_WIDTH, 65, wiese);

    // Haus mit Dach
    pbc_fill_rect(50, 140, 110, 90, wand);
    pbc_line(40, 140, 105, 85, PBC_RED);
    pbc_line(105, 85, 170, 140, PBC_RED);
    pbc_hline(40, 140, 131, PBC_RED);

    // Tuer und Fenster
    pbc_fill_rect(92, 180, 26, 50, holz);
    pbc_fill_rect(62, 155, 22, 22, PBC_WHITE);
    pbc_rect(62, 155, 22, 22, holz);
    pbc_fill_rect(126, 155, 22, 22, PBC_WHITE);
    pbc_rect(126, 155, 22, 22, holz);

    // Beschriftung, waagrecht zentriert
    int x = (PBC_WIDTH - pbc_text18_width("Mein Haus")) / 2;
    pbc_text18("Mein Haus", x, 238, PBC_WHITE);

    pbc_show();
    while (true) {
        sleep_ms(1000);
    }
}
Bildschirm des PBC+: Haus mit rotem Dach, Tür und zwei Fenstern auf grüner Wiese, gelbe Sonne am hellblauen Himmel, darunter „Mein Haus“

Ein Ladebalken (Kapitel 7)

Eine for-Schleife zählt von 0 bis 100. In jedem Durchgang wird das Bild neu gezeichnet, gezeigt und kurz gewartet – so entsteht eine Animation. snprintf macht aus der Zahl einen Text.

// Ein Ladebalken von 0 bis 100 Prozent
#include "pbc.h"

int main(void) {
    pbc_init();
    char text[10];
    int x;
    for (int prozent = 0; prozent <= 100; prozent++) {
        pbc_clear(PBC_BLACK);
        x = (PBC_WIDTH - pbc_text18_width("Laden ...")) / 2;
        pbc_text18("Laden ...", x, 90, PBC_WHITE);

        pbc_rect(20, 130, 200, 24, PBC_WHITE);
        pbc_fill_rect(22, 132, prozent * 196 / 100, 20, PBC_GREEN);

        snprintf(text, sizeof text, "%d %%", prozent);
        x = (PBC_WIDTH - pbc_text18_width(text)) / 2;
        pbc_text18(text, x, 170, PBC_WHITE);
        pbc_show();
        sleep_ms(30);
    }

    x = (PBC_WIDTH - pbc_text24_width("Fertig!")) / 2;
    pbc_text24("Fertig!", x, 210, PBC_GREEN);
    pbc_show();
    while (true) {
        sleep_ms(1000);
    }
}
Bildschirm des PBC+: „Laden ...“, darunter ein halb gefüllter grüner Balken und die Prozentzahl

Ein springender Ball (Kapitel 14)

Ein struct hält Position und Geschwindigkeit. Jedes Bild wird die Schwerkraft dazugerechnet; am Boden prallt der Ball ab und verliert Schwung. bildtakt() sorgt für eine feste Bildrate von 25 Bildern pro Sekunde, Taste A gibt neuen Schwung.

// Ein springender Ball: Schwerkraft, Abprallen am Boden, A gibt Schwung
#include "pbc.h"

#define BILD_MS 40
#define RADIUS 15
#define BODEN 240
#define SCHWERKRAFT 0.6f        // so viel waechst vy in jedem Bild
#define DAEMPFUNG 0.8f          // Anteil des Tempos, der beim Aufprall bleibt

typedef struct {
    float x, y;
    float vx, vy;
} kugel;

void bildtakt(void) {
    static uint32_t naechstes = 0;
    uint32_t jetzt = pbc_millis();
    naechstes = naechstes + BILD_MS;
    int rest = (int)(naechstes - jetzt);
    if (rest > 0) {
        sleep_ms(rest);
    } else {
        naechstes = jetzt;
    }
}

int main(void) {
    pbc_init();
    kugel ball = { 60.0f, 60.0f, 2.0f, 0.0f };

    while (true) {
        if (pbc_was_pressed_a()) {
            ball.vy = -14.0f;                   // kraeftig nach oben
        }
        ball.vy = ball.vy + SCHWERKRAFT;
        ball.x = ball.x + ball.vx;
        ball.y = ball.y + ball.vy;

        if (ball.y + RADIUS > BODEN) {          // Aufprall am Boden
            ball.y = BODEN - RADIUS;
            if (ball.vy > 3.0f) {
                pbc_tone(200, 30);
            }
            ball.vy = -ball.vy * DAEMPFUNG;
            if (ball.vy > -1.0f) {
                ball.vy = 0.0f;                 // zu schwach: liegen bleiben
            }
        }
        if (ball.x - RADIUS < 20 || ball.x + RADIUS > 220) {
            ball.vx = -ball.vx;                 // an den Seiten umkehren
            ball.x = ball.x + ball.vx;
        }

        pbc_clear(pbc_rgb(20, 30, 60));
        pbc_fill_rect(0, BODEN, PBC_WIDTH, 40, pbc_rgb(60, 140, 60));
        pbc_fill_ellipse((int)ball.x, BODEN, RADIUS, 4, pbc_rgb(30, 80, 30));
        pbc_fill_circle((int)ball.x, (int)ball.y, RADIUS, PBC_ORANGE);
        pbc_fill_circle((int)ball.x - 5, (int)ball.y - 5, 4, PBC_WHITE);
        pbc_text12("A: Schwung geben", 64, 252, PBC_WHITE);
        pbc_show();
        bildtakt();
    }
}
Bildschirm des PBC+: orangefarbener Ball im Flug über einer grünen Wiese mit Schatten, unten „A: Schwung geben“

Die Wasserwaage (Kapitel 17)

Der Beschleunigungssensor liefert, wie stark der PBC+ gekippt ist. Die Werte werden geglättet, damit die Blase nicht zittert. Liegt das Gerät waagrecht, wird die Blase grün und die grüne LED geht an.

// Die Wasserwaage: Die Blase wandert zur hoeheren Seite
#include "pbc.h"

#define MX 120                  // Mitte der Waage
#define MY 135
#define GROSS 90                // Radius des grossen Kreises
#define BLASE 14                // Radius der Blase
#define PIXEL_PRO_G 300         // 0,1 g Neigung = 30 Pixel
#define ANTEIL 0.2f             // Glaetten
#define WAAGRECHT 0.02f         // so wenig Neigung gilt als waagrecht

int main(void) {
    pbc_init();
    float gx = 0.0f, gy = 0.0f;             // geglaettete Messwerte
    char text[32];

    while (true) {
        gx = gx + (pbc_accel_x_g() - gx) * ANTEIL;
        gy = gy + (pbc_accel_y_g() - gy) * ANTEIL;

        // Die Blase steigt nach oben: zur Seite, deren Achse nach oben
        // zeigt. Dort ist der Messwert positiv.
        float dx = gx * PIXEL_PRO_G;
        float dy = gy * PIXEL_PRO_G;
        int frei = GROSS - BLASE;            // so weit darf sie wandern
        while (dx * dx + dy * dy > frei * frei) {
            dx = dx * 0.95f;                 // in Richtung Mitte holen
            dy = dy * 0.95f;
        }

        bool waagrecht = gx > -WAAGRECHT && gx < WAAGRECHT &&
                         gy > -WAAGRECHT && gy < WAAGRECHT;
        pbc_led_green(waagrecht);

        pbc_clear(PBC_BLACK);
        pbc_fill_circle(MX, MY, GROSS, pbc_rgb(150, 190, 40));
        pbc_circle(MX, MY, GROSS, PBC_WHITE);
        pbc_hline(MX - GROSS, MY, 2 * GROSS, pbc_rgb(90, 120, 20));
        pbc_vline(MX, MY - GROSS, 2 * GROSS, pbc_rgb(90, 120, 20));
        pbc_circle(MX, MY, BLASE + 3, PBC_BLACK);    // Zielkreis
        if (waagrecht) {
            pbc_fill_circle(MX + (int)dx, MY + (int)dy, BLASE, PBC_GREEN);
        } else {
            pbc_fill_circle(MX + (int)dx, MY + (int)dy, BLASE, PBC_WHITE);
        }
        snprintf(text, sizeof text, "x %5.2f g   y %5.2f g", gx, gy);
        pbc_text12(text, 50, 240, PBC_WHITE);
        pbc_show();
        sleep_ms(30);
    }
}
Bildschirm des PBC+: grüne Libelle mit Fadenkreuz und Zielkreis, die weiße Blase liegt rechts unten, darunter „x 0.12 g y 0.08 g“

Die vier Teile des Buchs

27 Kapitel und fünf Anhänge. Bis Teil III arbeitest du nur mit der Buchbibliothek. Teil IV nimmt sie auseinander.

Teil I – Los geht’s (Kapitel 1–4)

Was ein Mikrocontroller ist und was mit einem C-Programm passiert, bis es als .uf2-Datei auf dem Gerät läuft. Werkzeuge einrichten, das erste Programm, Fehlermeldungen des Compilers lesen und die Konsole mit printf über USB.

Teil II – Grundlagen von C (Kapitel 5–13)

Variablen und Datentypen (auch uint8_t und der Überlauf), Zeichnen und Farben, Schleifen und Zeit, Entscheidungen, Tasten und Joystick, LEDs und Töne, Funktionen, Arrays und Texte, Strukturen. Zum Ausprobieren entstehen kleine Projekte wie Würfel, Zahlenraten, Reaktionstest oder eine Ampel mit Signalton.

Teil III – Spiele bauen (Kapitel 14–18)

Flimmerfrei animieren mit fester Bildrate, Bilder und Sprites, Kollisionen, der Beschleunigungssensor und zum Schluss ein ganzes Spiel mit Titelbild, Spiel und Spielende.

Teil IV – Hinter die Kulissen (Kapitel 19–27)

Jetzt sprichst du selbst mit der Hardware, mit den Funktionen des Pico SDK. Am Ende ist die Buchbibliothek kein Geheimnis mehr – du könntest sie selbst geschrieben haben.

  • Zeiger und Speicher: Adressen, Zeiger als Parameter, Arrays und Zeiger. Was im RAM (512 KB) und was im Flash (16 MB) liegt – und warum der Stack nur 4 KB hat.
  • Mehrere Dateien: .h und .c, die CMakeLists.txt erweitern, eine eigene Bibliothek – und ein Blick in pbc.
  • GPIO, PWM und ADC: LEDs über ihre Pins schalten, Tasten lesen und entprellen, LEDs und Display dimmen, Töne selbst erzeugen, die Batteriespannung messen.
  • I²C: ein Scan nach allen Geräten am Bus, dann die Kennung und die Rohwerte des Beschleunigungssensors lesen und selbst in g umrechnen.
  • SPI und DMA: wie der Display-Controller ST7789 Befehle und Pixel bekommt, ein Fenster setzen und füllen, und wie der DMA das Bild verschickt, während die CPU weiterrechnet.
  • Interrupts, Timer, zweiter Kern: ein Timer, der regelmäßig etwas tut, Tasten per Interrupt, Musik auf Kern 1 – und wie zwei Abläufe sich Daten teilen, ohne sich zu stören.
  • Flash: löschen in Sektoren, schreiben in Seiten, einen Highscore speichern, der das Ausschalten übersteht.
  • Dein eigenes Projekt und Programmieren mit KI zum Abschluss.

So sieht der erste Schritt hinter die Kulissen aus: die rote LED, diesmal ohne pbc_led_red, direkt über ihren Pin GP14.

#include "pbc.h"
#include "hardware/gpio.h"

#define PIN_LED_ROT 14

int main(void) {
    pbc_init();
    // pbc_init hat den Pin schon eingerichtet. Ohne pbc ginge es so:
    gpio_init(PIN_LED_ROT);                // Pin als einfacher Ein-/Ausgang
    gpio_set_dir(PIN_LED_ROT, GPIO_OUT);   // Richtung: Ausgang

    while (true) {
        gpio_put(PIN_LED_ROT, 1);          // HIGH: 3,3 V, die LED leuchtet
        sleep_ms(500);
        gpio_put(PIN_LED_ROT, 0);          // LOW: 0 V, die LED ist aus
        sleep_ms(500);
    }
}
Schema: Bildpuffer im RAM (240 × 280 Pixel, je 16 Bit) → DMA holt die Pixel → SPI0 (SCK GP18, MOSI GP19, Takt 37,5 MHz) → Display-Controller ST7789 mit eigenem Speicher für 240 × 320 Pixel; dazu CS GP10, DC GP8, RST GP9

Kapitel 23 zeigt, was bei pbc_show() wirklich passiert: Der DMA liest den Bildpuffer und füttert den SPI-Bus, der die Pixel an den Display-Controller schickt. Danach kennst du jede Zeile des Display-Teils der Bibliothek.

Die Anhänge: A listet alle Befehle von pbc, B erklärt Fehlermeldungen des Compilers, C enthält die Lösungen, D ist die Hardware-Referenz mit Pinbelegung und Speicheraufteilung, E beschreibt die Installation im Detail und das Bauen ohne VS Code.

Stolpersteine, vor denen das Buch warnt

Fehlermeldungen lesen

Fehler sieht man in C beim Bauen. Der Compiler nennt Datei, Zeile und Spalte. Hier fehlt in Zeile 5 das Semikolon hinter pbc_clear(PBC_BLACK):

main.c: In function 'main':
main.c:5:25: error: expected ';' before 'pbc_text24'
    5 |     pbc_clear(PBC_BLACK)
      |                         ^
      |                         ;
    6 |     pbc_text24("Hallo!", 80, 120, PBC_WHITE);
      |     ~~~~~~~~~~

Zur Laufzeit gibt es dagegen keine Fehlermeldung. Ein falsches Programm macht still das Falsche oder bleibt hängen. Die Vorlage baut mit -Wall -Wextra, damit der Compiler möglichst viel schon vorher anmerkt. Anhang B erklärt die häufigsten Meldungen.

Typische Fallen

  • Kein Bild? Ohne pbc_show() bleibt alles im Bildpuffer.
  • = statt == in einer Bedingung ist gültiges C – und fast immer ein Fehler.
  • Über das Ende eines Arrays hinaus prüft C nicht. Dann ändert sich vielleicht eine ganz andere Variable, oder das Programm bleibt stehen – solche Fehler sind schwer zu finden.
  • Umlaute gibt es auf dem Display nicht; die Schriften haben nur ASCII. Ein Umlaut erscheint als ?.
  • pbc_tone wartet nicht. Das Programm läuft sofort weiter. Für Töne nacheinander musst du selbst warten, sonst hörst du nur den letzten.
  • Der Stack hat nur 4 KB. Große Arrays gehören nicht als lokale Variable in eine Funktion, sondern werden static, global oder const. Läuft der Stack über, hält ein Wächter das Programm an.
  • Die Pins des Pico 2 passen nicht. Die Board-Datei übernimmt die Grundeinstellungen des Raspberry Pi Pico 2, aber dessen Standard-Pins sind hier belegt: UART an GP0/GP1 sind zwei Joystick-Richtungen, I²C an GP4/GP5 träfe Joystick hoch, und an GP25 ist keine LED. Immer die Pins aus der Hardware-Referenz nehmen.
  • Im Flash den letzten Sektor frei lassen. Viele .uf2-Dateien schreiben dort einen Zusatzblock. Das Buch speichert im vorletzten Sektor.

Wie die Programme geprüft wurden

Jedes Programm im Buch wurde mit dem echten Pico SDK 2.2.0 für den RP2350 gebaut, mit denselben Warnungen wie in der Vorlage. Programme im Buch erzeugen keine Warnung, außer sie zeigen absichtlich eine.

Dazu gibt es eine PC-Fassung der Buchbibliothek. Mit ihr laufen die Programme aus Teil I bis III auf dem Rechner: Tastendrücke kommen aus einem Skript, das Display wird als Bild gespeichert, printf als Text. Alle Bildschirmbilder, Konsolenausgaben und Compilermeldungen im Buch stammen aus diesen Läufen, nichts ist abgetippt.

Was nur das Gerät zeigen kann – Ton, LEDs, Sensor, genaues Timing und die Programme aus Teil IV – wurde am PBC+ von Hand geprüft.

Downloads und Quellcode

  • pbc-vorlage.zip – die Projektvorlage mit der Buchbibliothek pbc, fertig zum Öffnen in VS Code
  • Hardware & Pins – Pinbelegung und Bauteile auf einen Blick
  • pbc-plus – alle Spiele und Emulatoren als Pico-SDK-Projekte, jedes mit Bauanleitung
Titelseite des Handbuchs „Programmieren in C“

KI-generiert

Programmieren in C

439 Seiten · PDF · 10 MB · für Einsteiger ohne Vorkenntnisse

27 Kapitel von der ersten Zeile bis zu DMA und zweitem Prozessorkern, mit Übungen und Lösungen.

Das Handbuch ist KI-generiert. Alle vier Handbücher wurden mit künstlicher Intelligenz (KI) generiert – Texte und Beispielprogramme. Das steht auch vorne in jedem Buch. Die Programme wurden getestet, auch auf dem echten Gerät. Fehler sind trotzdem möglich. Wenn dir einer auffällt: Bescheid sagen.

Die anderen Wege

1

Blöcke

Ideal für Anfänger. Ab 10 Jahren · PBC+ Studio im Browser

2

Python

Der Einstieg in die text­basierte Programmierung. Ab 14 Jahren · PBC+ Studio im Browser

3

Arduino

Der Einstieg in die Hardware­programmierung. Für Einsteiger ohne Vorkenntnisse, aber anspruchsvoller · Arduino IDE 2