Skip to content

LCD- en OLED-fontgenerator (bitmap naar C-array)

Zet tekst en afbeeldingen om naar C-arrays voor SSD1306, SH1106, ST7920 en Adafruit GFX. Scherpe pixelfonts van 12×12 en 16×16, alle vier scanmodi van PCtoLCD2002 en een decoder voor onbekende arrays.

Geen tracking Draait in je browser Gratis
Alles draait in je browser – tekst en afbeeldingen verlaten dit apparaat nooit.

Past bij het pagina-geheugen van SSD1306 / SSD1309 / SH1106 / ST7565 en MicroPython framebuf.MONO_VLSB – schrijf de bytes rechtstreeks naar het display.

Preview

Klik op een pixel om hem om te zetten.
    5 glyph(s) · 80 bytes
    Referentie: het teken 中 (16 × 16) in elke scanrichting

    Pixel aan = 1, glyph uit GNU Unifont. Vergelijk deze bytes met je eigen array om te zien met welke instellingen die gemaakt is.

    Scanrichting Bitvolgorde Bytes (hex)
    Rij voor rij (horizontale bytes) MSB eerst — eerste pixel in bit 7 01 00 01 00 01 00 01 00 3F F8 21 08 21 08 21 08 21 08 21 08 3F F8 21 08 01 00 01 00 01 00 01 00
    Rij voor rij (horizontale bytes) LSB eerst — eerste pixel in bit 0 80 00 80 00 80 00 80 00 FC 1F 84 10 84 10 84 10 84 10 84 10 FC 1F 84 10 80 00 80 00 80 00 80 00
    Kolom voor kolom (verticale bytes) MSB eerst — eerste pixel in bit 7 00 00 00 00 0F F0 08 20 08 20 08 20 08 20 FF FF 08 20 08 20 08 20 08 20 0F F0 00 00 00 00 00 00
    Kolom voor kolom (verticale bytes) LSB eerst — eerste pixel in bit 0 00 00 00 00 F0 0F 10 04 10 04 10 04 10 04 FF FF 10 04 10 04 10 04 10 04 F0 0F 00 00 00 00 00 00
    Kolommen per pagina (verticale bytes, SSD1306-paginavolgorde) MSB eerst — eerste pixel in bit 7 00 00 0F 08 08 08 08 FF 08 08 08 08 0F 00 00 00 00 00 F0 20 20 20 20 FF 20 20 20 20 F0 00 00 00
    Kolommen per pagina (verticale bytes, SSD1306-paginavolgorde) LSB eerst — eerste pixel in bit 0 00 00 F0 10 10 10 10 FF 10 10 10 10 F0 00 00 00 00 00 0F 04 04 04 04 FF 04 04 04 04 0F 00 00 00
    Rijen per strook (horizontale bytes, stroken van 8 pixels) MSB eerst — eerste pixel in bit 7 01 01 01 01 3F 21 21 21 21 21 3F 21 01 01 01 01 00 00 00 00 F8 08 08 08 08 08 F8 08 00 00 00 00
    Rijen per strook (horizontale bytes, stroken van 8 pixels) LSB eerst — eerste pixel in bit 0 80 80 80 80 FC 84 84 84 84 84 FC 84 80 80 80 80 00 00 00 00 1F 10 10 10 10 10 1F 10 00 00 00 00

    Pixelfonts: GNU Unifont (16 px) en Fusion Pixel Font (12 px), beide onder de SIL Open Font License 1.1. Licentieteksten

    Alle acht combinaties van scanrichting en bitvolgorde worden byte voor byte vergeleken met een onafhankelijke referentie-implementatie, en de voorinstellingen met de datasheets van SSD1306, SH1106 en ST7565 en de broncode van Adafruit GFX, U8g2, LVGL en MicroPython. — Go Tools Engineering Team · Oct 3, 2026

    Gebouwd en geverifieerd door het engineeringteam van Go Tools.

    Snelle antwoorden

    Welke instellingen heeft een SSD1306-OLED nodig?

    Kolommen per pagina · LSB eerst Kolommen per pagina, LSB eerst, pixel aan = 1 – als je de bytes rechtstreeks in het displaygeheugen schrijft.

    Welke instellingen heeft Adafruit GFX drawBitmap() nodig?

    Rij voor rij · MSB eerst Rij voor rij, MSB eerst, pixel aan = 1, elke rij aangevuld tot hele bytes.

    Hoeveel bytes is een teken van 16 × 16?

    32 bytes 32 bytes in elke scanrichting. 12 × 12 is 24 bytes, een ASCII-teken van 8 × 16 is 16.

    Wat betekenen 顺向 en 逆向 in PCtoLCD2002?

    逆向 = LSB eerst 顺向 = MSB eerst (eerste pixel in bit 7); 逆向 = LSB eerst (eerste pixel in bit 0).

    Wat is een fontbitmap (取模)?

    De meeste grafische OLED- en LCD-controllers – waaronder de SSD1306, SH1106 en ST7565 – hebben geen ingebouwd font. Om een teken te tonen kopieert de firmware een klein raster van pixels (aan/uit) naar het displaygeheugen: één bit per pixel, acht pixels per byte. Een glyph omzetten naar die bytes heet in Chinese embedded-tutorials 取模 – het werk dat het Windows-programma PCtoLCD2002 al jaren doet.

    De bytes alleen zijn niet genoeg. Hetzelfde teken van 16 × 16 kun je op vier manieren inpakken (rij voor rij, kolom voor kolom, kolommen per pagina, rijen per strook) en elke manier kan de eerste pixel in bit 7 of in bit 0 zetten. Acht bytereeksen beschrijven hetzelfde glyph, en een display tekent er maar één correct. Daarom verschijnt een font dat je uit een tutorial kopieert zo vaak gespiegeld, in tweeën gesplitst of gedraaid.

    // 中 (16x16), pages of columns, LSB first, lit = 1 — SSD1306 page order
    const unsigned char zhong[32] = {
      0x00,0x00,0xF0,0x10,0x10,0x10,0x10,0xFF,0x10,0x10,0x10,0x10,0xF0,0x00,0x00,0x00,
      0x00,0x00,0x0F,0x04,0x04,0x04,0x04,0xFF,0x04,0x04,0x04,0x04,0x0F,0x00,0x00,0x00
    };
    // First 16 bytes = page 0 (rows 0-7), one byte per column, bit 0 = top row

    Wat deze generator doet

    Pixelzuiver Chinees in 12 × 12 en 16 × 16

    Browserfonts zijn anti-aliased contouren; met een drempelwaarde op 12 px in een Song-lettertype verdwijnen de horizontale streken van 中 gewoon. Daarom levert deze tool echte bitmapfonts: het 16 × 16-font dekt alle 6.763 GB2312-tekens, het 12 × 12-font mist 143 zeldzame tekens, die met een systeemfont worden getekend en gemarkeerd.

    Alle vier scanmodi van PCtoLCD2002, beide bitvolgordes

    Rij voor rij, kolom voor kolom, kolommen per pagina en rijen per strook, telkens MSB eerst of LSB eerst, pixel aan = 1 of 0. De optienamen volgen PCtoLCD2002 en hun betekenis is gecontroleerd aan de hand van de SSD1306-datasheet en gangbare OLED-voorbeeldprojecten, zodat je dezelfde instellingen kunt kiezen als een bestaand project.

    Voorinstellingen die zeggen waar ze bij passen

    Kies SSD1306, Adafruit GFX of XBM en de opties worden voor je ingesteld. Pas je een optie met de hand aan, dan vertelt de tool welke displays en libraries die bytevolgorde lezen – of dat er geen enkele is.

    Een bestaande array decoderen

    Plak een fontarray van onbekende herkomst en alle acht lezingen van scanrichting en bitvolgorde worden naast elkaar getekend. De leesbare verraadt de instellingen; één klik neemt ze over.

    Afbeelding naar bitmap met echte dithering

    Logo's, iconen en foto's worden geschaald naar je displaygrootte en omgezet met een drempelwaarde, Floyd–Steinberg- of Atkinson-dithering. Transparante delen tellen als achtergrond, en de drempelwaarde werkt in elke modus.

    Uitvoer die zo in je project past

    2D-arrays in C51-stijl met /*"中",0*/ als commentaar, Arduino PROGMEM met offsets, MicroPython-bytearray-dictionaries, A51-DB-regels of kale hex. De gegenereerde C compileert zonder waarschuwingen met -Wall -Wextra -pedantic.

    Uitgewerkte voorbeelden

    中 voor een SSD1306-OLED (16 × 16, kolommen per pagina, LSB eerst)

    中
    00 00 F0 10 10 10 10 FF 10 10 10 10 F0 00 00 00 00 00 0F 04 04 04 04 FF 04 04 04 04 0F 00 00 00

    32 bytes: 16 kolommen van pagina 0 (rijen 0–7), daarna 16 kolommen van pagina 1 (rijen 8–15). In de 0xFF op kolom 7 staat elke bit aan: de verticale streek loopt door alle acht rijen van beide pagina's.

    Hetzelfde 中 voor Adafruit GFX drawBitmap (rij voor rij, MSB eerst)

    中
    01 00 01 00 01 00 01 00 3F F8 21 08 21 08 21 08 21 08 21 08 3F F8 21 08 01 00 01 00 01 00 01 00

    Twee bytes per rij, 16 rijen. 0x01 0x00 is alleen de middelste streek: de meest linkse pixel is bit 7 van de eerste byte, dus de pixel in kolom 7 komt in bit 0 terecht. Stuur je deze bytes met een page-write naar een SSD1306, dan krijg je pixelbrij – hetzelfde glyph, anders ingepakt.

    Halfbrede A in een font van 16 pixels (8 × 16)

    A
    00 00 00 00 18 24 24 42 42 7E 42 42 42 42 00 00

    ASCII-tekens zijn half zo breed: 8 × 16 is 16 bytes, één byte per rij bij rij-voor-rij-scannen. Vink “Halfbrede tekens (A–Z, 0–9) de volle celbreedte geven” aan als je driver voor elk glyph 16 × 16 verwacht.

    Waarom 12 × 12 24 bytes is en geen 18

    中 (12 × 12, rij voor rij, MSB eerst)
    00 00 04 00 04 00 FF E0 84 20 84 20 84 20 FF E0 04 00 04 00 04 00 04 00

    Elke rij van 12 pixels heeft twee bytes nodig; de laatste vier bits van de tweede byte zijn opvulling. 12 rijen × 2 bytes = 24. Elke displaylibrary adresseert rijen als (width + 7) / 8 bytes, dus strakker ingepakte bits zouden ze allemaal in de war brengen.

    Zo genereer je fontdata voor een LCD of OLED

    1. 1

      Typ tekst of sleep een afbeelding

      Tekst gebruikt een echt pixelfont: 12 × 12 (Fusion Pixel) of 16 × 16 (GNU Unifont), met ASCII op halve breedte. Voor logo's en iconen schakel je over naar het tabblad Afbeelding en stel je de doelgrootte in, bijvoorbeeld 128 × 64.

    2. 2

      Kies het doeldisplay of de library

      SSD1306 / SH1106 / ST7565 willen verticale bytes in paginavolgorde met de bovenste pixel in bit 0. Adafruit GFX, TFT_eSPI, U8g2 drawBitmap en LVGL willen horizontale bytes met de linkerpixel in bit 7. XBM / U8g2 drawXBM is hetzelfde, maar met de linkerpixel in bit 0.

    3. 3

      Controleer de preview en corrigeer pixels waar nodig

      De preview toont precies de bitmap die wordt geëncodeerd. Klik op een pixel om hem om te zetten, of schuif het glyph op zijn plek met de verschuifvelden.

    4. 4

      Kopiëren of downloaden

      Kies C (C51-stijl van PCtoLCD2002), Arduino PROGMEM, MicroPython bytearray, A51-assembly of kale hex. De eerste regel van de uitvoer legt scanrichting, bitvolgorde en glyphgrootte vast, zodat de array zichzelf documenteert.

    Onleesbare tekens: symptoom → verkeerde instelling

    Elke groep van 8 pixels is links-rechts gespiegeld

    Horizontale bytes met de verkeerde bitvolgorde. Adafruit GFX drawBitmap() wil MSB eerst; XBM en U8g2 drawXBM() willen LSB eerst.

    ✗ Fout
    U8g2 drawXBM() krijgt bytes met MSB eerst
    ✓ Correct
    drawXBM() → XBM-voorinstelling (rij voor rij, LSB eerst)

    Elke 8 rijen staan op hun kop

    Verticale bytes met de verkeerde bitvolgorde. Controllers van het type SSD1306 zetten D0 in de bovenste rij en hebben dus LSB eerst nodig.

    ✗ Fout
    Kolommen per pagina, MSB eerst → SSD1306
    ✓ Correct
    Kolommen per pagina, LSB eerst → SSD1306

    Boven- en onderhelft door elkaar

    Kolom voor kolom en kolommen per pagina verwisseld. Ze geven alleen dezelfde bytes bij glyphs tot 8 pixels hoog; bij 16 pixels verschilt de bytevolgorde.

    ✗ Fout
    Kolom voor kolom → page-writes naar SSD1306
    ✓ Correct
    Kolommen per pagina → page-writes naar SSD1306

    Glyph gespiegeld langs de diagonaal, of geïnverteerd

    Een spiegeling langs de diagonaal betekent dat horizontale bytes als verticale zijn gelezen (of andersom). Donkere tekst op een lichte achtergrond betekent dat pixel aan = 0 is gekozen waar het display pixel aan = 1 verwacht.

    ✗ Fout
    Rij-voor-rij-bytes naar een SSD1306-pagina gestuurd
    ✓ Correct
    Plak de array in het decodertabblad en kies de leesbare preview

    Wanneer je dit nodig hebt

    Chinese tekst op een 0,96" SSD1306-OLED
    Een temperatuurwaarde, een menu of een statusregel in het Chinees op een STM32- of 51-bord. Gebruik het font van 16 × 16 met de SSD1306-voorinstelling en plak de array in de oled_font.h die je voorbeeldproject al heeft.
    Opstartlogo op een Arduino- of ESP32-display
    Sleep een PNG-logo hierheen, stel 128 × 64 in, kies de voorinstelling Adafruit GFX en roep display.drawBitmap(0, 0, logo, 128, 64, WHITE) aan.
    Iconen en eenheden voor een LVGL- of U8g2-interface
    Batterij-, wifi- en °C-symbolen als 1-bit-afbeeldingen. Gebruik de voorinstelling Adafruit GFX / LVGL voor horizontale bytes met MSB eerst, of de XBM-voorinstelling voor U8g2 drawXBM().
    Werken op een Mac of Linux-machine
    PCtoLCD2002 en de klassieke 字模提取-tools zijn Windows-programma's. Deze tool draait in elke moderne browser en hoeft niet geïnstalleerd te worden.
    Een geërfd project ontrafelen
    Je voorganger liet een Hzk[][32]-array achter, zonder aantekeningen. Plak hem in de decoder om uit te vinden hoe hij gegenereerd is, voordat je nieuwe tekens in hetzelfde formaat toevoegt.

    Zo werken de vier scanrichtingen

    Rij voor rij (horizontale bytes)
    Rijen worden van boven naar beneden gelezen; binnen een rij bevat elke byte acht naast elkaar liggende pixels, van links naar rechts. Een rij van 16 pixels is twee bytes. Dit is de indeling van Adafruit GFX drawBitmap(), U8g2 drawBitmap(), XBM-bestanden, ST7920-GDRAM en 1-bit-afbeeldingen in LVGL.
    Kolommen per pagina (verticale bytes) – de SSD1306-volgorde
    Het glyph wordt opgedeeld in pagina's van acht rijen hoog. Per pagina worden de kolommen van links naar rechts gelezen en bevat elke byte de acht pixels van die kolom. Dat komt overeen met het GDDRAM van de SSD1306, SH1106 en ST7565, waar volgens de datasheet databit D0 in de bovenste rij wordt geschreven – de bijbehorende bitvolgorde is dus LSB eerst.
    Kolom voor kolom, en rijen per strook
    Kolom voor kolom leest elke kolom van boven naar beneden over alle pagina's voordat het naar rechts gaat; dat komt overeen met de verticale adresseringsmodus van de SSD1306. Rijen per strook neemt een strook van 8 pixels breed met al zijn rijen, daarna de volgende strook; geen gangbare library gebruikt dit, oudere PCtoLCD2002-projecten wel. Elk van de twee ziet er alleen hetzelfde uit als zijn tegenhanger wanneer het glyph hooguit 8 pixels hoog (of breed) is, en daarom valt de verwisseling bij tests met 8 × 8 niet op.
    Bitvolgorde en de waarde van een pixel die aan staat
    MSB eerst zet de eerst gelezen pixel (meest links of meest boven) in bit 7; LSB eerst zet hem in bit 0. PCtoLCD2002 noemt dit 顺向 (MSB eerst) en 逆向 (LSB eerst). Pixel aan = 1 (阴码) is wat OLED's, TFT drawBitmap() en LVGL A1 verwachten; pixel aan = 0 (阳码) alleen voor drivers die 0 als “aan” definiëren.
    Opvulling als de grootte geen veelvoud van 8 is
    Elke rij (horizontale bytes) of elke pagina (verticale bytes) wordt los aangevuld tot hele bytes, en opvulbits zijn 0. Bij kolommen per pagina en een glyph van 12 pixels bevat de tweede pagina 4 opvulrijen; een driver die hele pagina's schrijft, wist die 4 rijen onder het glyph. De tool waarschuwt wanneer dat speelt.

    Aanbevolen aanpak

    Kies de voorinstelling op basis van de tekenfunctie, niet van het scherm
    Een SSD1306 die via Adafruit_SSD1306 wordt aangestuurd, loopt via drawBitmap() en heeft dus horizontale bytes met MSB eerst nodig, ook al is het geheugen van de controller zelf verticaal. Kies de voorinstelling die past bij de functie die je code aanroept.
    Gebruik de pixelfonts voor 12 en 16 px
    Contourfonts onder ongeveer 20 px verliezen streken zodra je een drempelwaarde toepast. Fusion Pixel 12 en Unifont 16 zijn op het pixelraster getekend, en de 2×-opties leveren nette 24 × 24 en 32 × 32.
    Laat het kopcommentaar staan
    De eerste uitvoerregel legt scanrichting, bitvolgorde en grootte vast. Zes maanden later is dat het enige bewijs van hoe de array tot stand kwam.
    Test met een asymmetrisch teken
    Symmetrische glyphs zoals 中, 田 of H verbergen spiegelfouten. Probeer eerst F, 7 of 乙: is dat goed leesbaar, dan klopt elke optie.
    Los spiegeling van het hele scherm op in de driver
    Staat alles op het scherm gespiegeld of op zijn kop, en niet alleen je font, pas dan de segment-remap (A0h/A1h) en de COM-scanrichting (C0h/C8h) aan in de init-sequentie. De fontinstellingen aanpassen zou alleen andere code breken.

    Veelgestelde vragen

    Welke instellingen gebruik ik voor een SSD1306- of SH1106-OLED?
    Als je code de fontbytes rechtstreeks naar het display schrijft (de meeste voorbeelden voor 51 en STM32): kolommen per pagina, LSB eerst, pixel aan = 1 – de SSD1306-voorinstelling. Tekent hij via Adafruit_SSD1306 of U8g2 drawBitmap(), gebruik dan de voorinstelling Adafruit GFX, want die functies lezen horizontale bytes met MSB eerst en zetten ze zelf om.
    Mijn tekens staan gespiegeld, op hun kop of door elkaar. Wat is er mis?
    Elk symptoom wijst naar één instelling. Elke 8 pixels links-rechts gespiegeld: verkeerde bitvolgorde bij horizontale bytes. Elke 8 rijen op hun kop: verkeerde bitvolgorde bij verticale bytes. Boven- en onderhelft door elkaar: kolom voor kolom en kolommen per pagina verwisseld. Gespiegeld langs de diagonaal: horizontale en verticale bytes verwisseld. Kleuren omgekeerd: pixel aan = 1 en pixel aan = 0 verwisseld. Is het hele scherm gespiegeld en niet alleen je tekst, corrigeer dan de init-sequentie van de driver.
    Waarom kost 12 × 12 24 bytes en geen 18?
    Elke rij (of elke pagina van 8 rijen) wordt los aangevuld tot hele bytes: 12 pixels hebben 2 bytes nodig, en 12 rijen × 2 = 24. Displaylibraries adresseren rijen als (width + 7) / 8 bytes, dus een strak ingepakt glyph van 18 bytes zouden ze allemaal verkeerd lezen.
    Waarom wist mijn tekst van 12 pixels de regel eronder op het OLED?
    Bij kolommen per pagina vult een glyph van 12 pixels één volle pagina en de helft van de volgende; de overige 4 bits van die tweede pagina zijn opvulnullen. Een driver die hele pagina's schrijft, wist die 4 rijen. Teken via een framebuffer die losse pixels zet, of plaats tekst van 12 pixels zo dat de lege rijen vallen waar verder niets getekend wordt.
    Kan ik dit op een Mac gebruiken in plaats van PCtoLCD2002?
    Ja. Het draait in elke moderne browser, biedt dezelfde vier scanmodi, beide bitvolgordes en pixel aan = 1 / pixel aan = 0, en de C-uitvoer volgt de C51-stijl van PCtoLCD2002 met /*"字",0*/ als commentaar, zodat je hem kunt plakken in projecten die op arrays in de stijl van Hzk[][32] draaien. Volledige fontlibrarybestanden of indexen genereert het niet. De glyphvormen komen uit GNU Unifont en Fusion Pixel en niet uit SimSun van Windows, dus de bytes komen niet teken voor teken overeen met een array uit PCtoLCD2002 – genereer de hele tabel hier opnieuw in plaats van beide te mengen. Deze site is niet gelieerd aan PCtoLCD2002 of de maker ervan, is geen officiële webversie en biedt het programma niet als download aan.
    Waarom een pixelfont en niet mijn systeemfont?
    Systeemfonts zijn contouren met anti-aliasing, en die kan een browser niet uitzetten. Op 12 of 16 pixels gaan dunne streken verloren zodra je op die grijze rand een drempelwaarde toepast – de horizontale balken van 中 verdwijnen in een Song-lettertype van 12 pixels volledig. GNU Unifont (16 px) en Fusion Pixel (12 px) zijn op het pixelraster ontworpen, dus er gaat niets verloren. Voor grotere formaten blijven de systeemfonts beschikbaar: een schreefloos lettertype (Hei) houdt stand vanaf ongeveer 24 px, terwijl Song-lettertypen daar nog streken kunnen verliezen.
    Welke tekens dekken de pixelfonts?
    Heel GB2312 – 6.763 vereenvoudigde Chinese karakters plus leestekens op volle breedte – en afdrukbare ASCII, Latijnse letters met accenten (é, ß, ł, ş, ő), Grieks, Cyrillisch, Japanse kana en gangbare symbolen zoals ℃, pijlen en kaderlijnen. Fusion Pixel 12 px mist een paar zeldzame tekens en symbolen. Koreaans Hangul en Chinese karakters buiten GB2312 (traditionele vormen, veel Japanse kanji) worden in plaats daarvan met een systeemfont getekend en onder de preview vermeld, zodat je ziet welke glyphs je moet nalopen.
    Hoe zet ik een logo of icoon om naar een C-array?
    Open het tabblad Afbeelding, sleep het bestand hierheen, stel de displaygrootte in (128 × 64 voor een OLED van 0,96") en laat “Passend maken, verhoudingen behouden” aan staan om de verhoudingen te bewaren. Donkere pixels worden pixels die aan staan; vink inverteren aan voor lichte afbeeldingen op een donkere achtergrond. Gebruik geen dithering voor logo's en tekst, Floyd–Steinberg of Atkinson voor foto's.
    Hoe kom ik erachter hoe een bestaande fontarray gegenereerd is?
    Plak hem in het tabblad “Bestaande array bekijken”. Commentaar wordt genegeerd, en C-, Arduino-, A51- en MicroPython-syntaxis worden allemaal geaccepteerd. De glyphgrootte wordt geschat op basis van het aantal bytes en alle acht combinaties van scanrichting en bitvolgorde worden getekend. De combinatie die goed leesbaar is, is jouw instelling, en “Deze instellingen gebruiken” kopieert haar naar de generator.
    Wordt mijn tekst of afbeelding geüpload?
    Nee. Glyphs worden in je browser getekend en geëncodeerd. De pixelfonts worden één keer van deze site gedownload, en er gaat niets wat je typt of hierheen sleept naar een server.

    Gerelateerde tools

    Alle tools bekijken →