ssd1306日志打印机(带动画)

YIN 发布于 2025-07-17 168 次阅读


简介

一个适用于esp32系列的oled12864 iic (ssd1306)的日志打印程序(带有动画)

使用方法

  1. 将附件内的工程以及两个字库复制到工程内
  2. 使用网站内的ssd1306简单驱动 或者自行实现驱动
    自行实现需要一个刷新函数,一个刷新缓冲区
  3. 调用logAutoInit()初始化
  4. 使用consoleLog(bool isInvert,const char *format, ...)发送日志,日志会自行显示到屏幕上
    其中,isInvert决定日志是否反色

附件1

C

#include "esp_log.h"
#include "esp_timer.h"
#include "zpix.h"
#include "tinyFont.h"
#include <stdbool.h>
#include <stdarg.h>
#include <stdio.h>
#include <math.h>
#include "ssd1306_driver.h"  //需要一个函数用于刷新屏幕,还需要预留一个接口用于直接访问屏幕缓冲区

extern uint8_t* vBuf;       // 外界的屏幕接口
uint8_t vBuf2[1024];
SemaphoreHandle_t vBuf2Mutex;

QueueHandle_t updateRectQueue;
typedef struct {
    uint8_t width;
    uint8_t height;
} UpdateRectQueuePack_t;


void putChar(uint8_t* vFrame, uint8_t row, uint8_t column, uint8_t code, bool isInvert)
{
    if (code < ' ' || code > '~') return;
    row = row%8;
    row = 7 - row;
    if (isInvert) {
        for (uint8_t i = 0; i < 12; i++) {
            vFrame[row + ((column + i) << 3)] = ~zpix_ascii[(code - ' ') * 12 + i];
        }
    } else {
        for (uint8_t i = 0; i < 12; i++) {
            vFrame[row + ((column + i) << 3)] = zpix_ascii[(code - ' ') * 12 + i];
        }
    }

}

// 全局预计算掩码表(常量数组)
const uint8_t BIT_MASK[8] = {
    0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80
};

void setPixel(uint8_t* vFrame,uint8_t x, uint8_t y, bool isTrue) {
    uint8_t row = y >> 3;         // 行索引(y/8)
    uint16_t pos = x; 
    pos <<= 3;
    pos += row;
    uint8_t mask = BIT_MASK[y & 0x07]; // 直接查表获取位掩码

    if (isTrue) {
        vFrame[pos] |= mask;       // 置位像素
    } else {
        vFrame[pos] &= ~mask;      // 清除像素
    }
}

/** 
 * 高效绘制矩形(空心或实心)
 * @param x0, y0  矩形左上角坐标
 * @param x1, y1  矩形右下角坐标
 * @param isFilled true=实心填充, false=仅边框
 * @param isTrue   true=置位像素, false=清除像素
 */
void drawRectangle(uint8_t* vFrame,uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, bool isTrue) {
    // 1. 参数校验:确保 x0<=x1, y0<=y1
    if (x0 > x1) { uint8_t tmp = x0; x0 = x1; x1 = tmp; }
    if (y0 > y1) { uint8_t tmp = y0; y0 = y1; y1 = tmp; }

    for (uint16_t i = x0;i <= x1;i++){
        for (uint16_t j = y0;j <= y1;j++) {
            setPixel(vFrame, i, j, isTrue);
        }
    }
}

void drawRectangle_Optimized(uint8_t* vFrame,uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, bool isFilled, bool isRoundCorner,bool isTrue) {
    // 1. 参数校验与坐标归一化
    if (x0 > x1) { uint8_t tmp = x0; x0 = x1; x1 = tmp; }
    if (y0 > y1) { uint8_t tmp = y0; y0 = y1; y1 = tmp; }
    if (x0 == x1 || y0 == y1) return;
    // 2. 绘制空心矩形边框(仅四条边)
    // 上/下水平边框(整行处理)
    for (uint8_t x = x0 + ((isRoundCorner) ? 1 : 0); x <= x1 - ((isRoundCorner) ? 1 : 0); x++) {
        setPixel(vFrame, x, y0, isTrue); // 上边框
        setPixel(vFrame, x, y1, isTrue); // 下边框
    }
    // 左/右边框(按页处理)
    uint8_t start_page = y0 >> 3;
    uint8_t end_page = y1 >> 3;

    for (uint8_t i = y0 + 1; i <= y1 - 1; i++) {
        setPixel(vFrame, x0, i, isTrue); // 左边框
        setPixel(vFrame, x1, i, isTrue); // 右边框
    }

    // 3. 实心填充优化(按列批量操作)
    if (isFilled) {
        for (uint16_t x = x0 + 1; x < x1; x++) { // 遍历每一列
            for (uint8_t page = start_page; page <= end_page; page++) {
                uint8_t *col_ptr = &vFrame[(x << 3) + page]; // 当前列显存地址
                uint8_t fill_mask = 0xFF; // 默认填充整页

                // 计算当前页的垂直掩码(首尾页裁剪)
                if (page == start_page) 
                    fill_mask &= (0xFF << (y0 & 0x07));   // 首页:屏蔽顶部无效位
                if (page == end_page) 
                    fill_mask &= (0xFF >> (7 - (y1 & 0x07))); // 尾页:屏蔽底部无效位

                // 整字节写入显存
                if (isTrue) *col_ptr |= fill_mask;
                else        *col_ptr &= ~fill_mask;
            }
        }
    }
}

void testPutChar(uint8_t* vFrame,uint8_t x, uint8_t y, uint8_t code, uint8_t zoom, bool isInvert)
{
    if (code < ' ' || code > '~') return;
    for (uint8_t i = 0; i < 12; i++) {
        uint8_t mask = zpix_ascii[(code - ' ') * 12 + i];
        if (isInvert) mask = ~mask;
        for (uint8_t j = 0; j < 8; j++) {
            uint8_t color = mask & (0x80 >> j);
            if (color || 1) {
                if(zoom <= 1) setPixel(vFrame, j + x, i + y, color);
                else drawRectangle (vFrame, j * zoom + x, i * zoom + y,(j + 1) * zoom + x - 1, (i + 1) * zoom + y - 1, color);
            }
        }
    }
}

void testPutTinyChar(uint8_t* vFrame,uint8_t x, uint8_t y, uint8_t code, uint8_t zoom, bool isInvert)
{
    y += 1;
    if (code < ' ' || code > '~') return;
    for (uint8_t i = 0; i < 5; i++) {
        uint8_t mask = tinyFont_ascii[(code - ' ') * 5 + i];
        if (isInvert) mask = ~mask;
        for (uint8_t j = 0; j < 5; j++) {
            uint8_t color = mask & (0x80 >> j);
            if (color || 1) {
                if(zoom <= 1) setPixel(vFrame, j + x, i + y, color);
                else drawRectangle (vFrame, j * zoom + x, i * zoom + y,(j + 1) * zoom + x - 1, (i + 1) * zoom + y - 1, color);
            }
        }
    }
    y -= 1;
    for (uint8_t i = 0; i < 5; i++) {
        setPixel(vFrame, i + x, y, isInvert);
    }
}

void frameBufferCopy(int16_t x,int16_t y, int16_t w, int16_t h)
{
    if (h < 1 || w < 1) return;
    uint16_t start_page = y >> 3;
    uint16_t end_page = (y + h) >> 3;
    for (uint16_t i = x; i <= (w + x) ; i++) {
        for (uint16_t page = start_page; page <= end_page; page++) {
            uint8_t *col_ptr = &vBuf[(i << 3) + page]; // 当前列显存地址
            uint16_t fill_mask = (vBuf2[((i - x) << 3) + page - start_page]);
            fill_mask <<= 8;
            if (page != start_page) {
                fill_mask += (vBuf2[((i - x) << 3) + page - start_page - 1]);
                fill_mask >>= 8 - (y% 8);
            } else {
                fill_mask += (vBuf2[((i - x) << 3) + page - start_page]);
                fill_mask <<= (y% 8);
            }
            uint8_t maskUint8 = fill_mask & 0x00FF;
            // 计算当前页的垂直掩码(首尾页裁剪)
                if (page == start_page) 
                    maskUint8 &= (0xFF << (y & 0x07));   // 首页:屏蔽顶部无效位
                if (page == end_page) 
                    maskUint8 &= (0xFF >> (7 - ((y + h) & 0x07))); // 尾页:屏蔽底部无效位

                // 整字节写入显存
                *col_ptr |= maskUint8;
        }
    }
}

typedef struct {
    uint16_t currFrame;
    uint16_t totalFrame;
    int16_t targetWidth;
    int16_t targetHeight;
    int16_t currWidth;
    int16_t currHeight;
    int16_t startWidth;
    int16_t startHeight;

} UpdateRect_t;

UpdateRect_t rectInfo;
SemaphoreHandle_t rectMutex;

#define MIN(a, b) ((a) < (b) ? (a) : (b))
#define MAX(a, b) ((a) > (b) ? (a) : (b))

float animationCalc(float t);
void updateRect(TimerHandle_t xTimer)
{
    static bool isRunning = false;
    if (isRunning) return;
    isRunning = true;
    xSemaphoreTake(rectMutex, portMAX_DELAY);
    xSemaphoreTake(vBuf2Mutex, portMAX_DELAY);
    /* 检查合法性 */
    // rectInfo.targetWidth = MAX (0, rectInfo.targetWidth);
    // rectInfo.targetWidth = MIN (127, rectInfo.targetWidth);
    // rectInfo.targetHeight = MAX (0, rectInfo.targetHeight);
    // rectInfo.targetHeight = MIN (63, rectInfo.targetHeight);
    // rectInfo.currWidth = MAX (0, rectInfo.currWidth);
    // rectInfo.currWidth = MIN (127, rectInfo.currWidth);
    // rectInfo.currHeight = MAX (0, rectInfo.currHeight);
    // rectInfo.currHeight = MIN (63, rectInfo.currHeight);
    // rectInfo.startWidth = MAX (0, rectInfo.startWidth);
    // rectInfo.startWidth = MIN (127, rectInfo.startWidth);
    // rectInfo.startHeight = MAX (0, rectInfo.startHeight);
    // rectInfo.startHeight = MIN (63, rectInfo.startHeight);

    float time = 1.0f * rectInfo.currFrame / rectInfo.totalFrame;
    if (rectInfo.currFrame > rectInfo.totalFrame || time > 1.0f) {
        xTimerStop(xTimer, 0);
        xSemaphoreGive(rectMutex);
        xSemaphoreGive(vBuf2Mutex);
        isRunning = false;
        return;
    }
    float div = animationCalc(time);
    if (div > 1.0) div = 1.0;
    int16_t newHeight = rectInfo.startHeight + (rectInfo.targetHeight - rectInfo.startHeight) * div;
    int16_t newWidth = rectInfo.startWidth + (rectInfo.targetWidth - rectInfo.startWidth) * div;
    if (newHeight > 63 || newWidth > 127)
    ESP_LOGW(__func__,"%d,%d,%d,%d,%f",newWidth, rectInfo.currWidth, rectInfo.startWidth, rectInfo.targetWidth,time);

    // drawRectangle_Optimized(vBuf, 0,0,newWidth,newHeight,false,true,true);


    if (rectInfo.currHeight != newHeight || rectInfo.currWidth != newWidth || rectInfo.currFrame != 0) {
        drawRectangle_Optimized(vBuf, 
        63 - (newWidth >> 1), 
        31 - (newHeight >> 1), 
        63 + newWidth - (newWidth >> 1),
        31 + newHeight - (newHeight >> 1),
        false,true,true);
        rectInfo.currHeight = newHeight;
        rectInfo.currWidth = newWidth;
        if(newWidth >= 1 && newHeight >= 1 && newWidth <= 126 && newHeight <= 62) {
            frameBufferCopy(63 - (newWidth >> 1) + 2, 31 - (newHeight >> 1) + 2,newWidth - 4,newHeight - 4);
        }
        ssd1306FreshScreen();
    }
    rectInfo.currFrame++;
    xSemaphoreGive(rectMutex);
    xSemaphoreGive(vBuf2Mutex);
    isRunning = false;
}

TaskHandle_t logAutoHandler = NULL;
esp_timer_handle_t timer_handle;

float animationCalc(float t) {
    if (t < 0.5) 
        return 0.5f * pow(2*t, 2);
    else if (t != 1.0)
        return 1.0f - 0.5f * pow(2*(1-t), 2); // 后半段减速
    else return 1.0f;
}

void setNewRectAnimation(int16_t targetWidth, int16_t targetHeight, int16_t frame)
{
    rectInfo.currFrame = 0;
    rectInfo.targetHeight = targetHeight;
    rectInfo.targetWidth = targetWidth;
    rectInfo.totalFrame = frame;
    rectInfo.startHeight = rectInfo.currHeight;
    rectInfo.startWidth = rectInfo.currWidth;
}

static void logAuto()
{
    rectInfo.startHeight = 0;
    rectInfo.startWidth = 0;
    TimerHandle_t xTimer = xTimerCreate(
        "updateRect",                  // 定时器名称(调试用)
        pdMS_TO_TICKS(33),            // 周期:20ms 
        pdTRUE,                       // 自动重载(周期性)
        (void *)0,          // 定时器 ID(可传递参数)
        updateRect                // 回调函数
    );
    bool isClose = true;
    uint8_t skipCount = 0;
    UpdateRectQueuePack_t queueData = {
        .height = 0,
        .width = 0
    };
    while (true) {
        if (xQueueReceive(updateRectQueue, &queueData, (isClose) ? portMAX_DELAY : 10000/portTICK_PERIOD_MS) == pdTRUE) {
            isClose = false;
            queueData.height += 4;
            queueData.width += 4;
        } else {
            ESP_LOGI(__func__,"timeout");
            queueData.height = 0;
            queueData.width = 0;
            skipCount = 0;
            isClose = true;
        }
        if (true) {
            xSemaphoreTake(rectMutex, portMAX_DELAY);
            if (rectInfo.currFrame < rectInfo.totalFrame) {
                if (skipCount < 9)
                    skipCount ++;
            } else {
                if (skipCount) skipCount --;
            }
            xTimerStop(xTimer, 0);
            setNewRectAnimation(queueData.width,queueData.height, 40 / (skipCount + 1));
            xSemaphoreGive(rectMutex);
            xTimerStart(xTimer, 0); 
        }
        vTaskDelay (200/portTICK_PERIOD_MS);
    }
}

void setRect(uint8_t width, uint8_t height) 
{
    UpdateRectQueuePack_t sendData = {
        .width = width,
        .height = height,
    };
    ESP_LOGI(__func__,"W: %d, H: %d", width,height);
    xQueueSend(updateRectQueue, &sendData, 0);
}

QueueHandle_t updateConsoleQueue;
typedef struct {
    uint8_t flag;
    uint16_t len;
    uint8_t str[224];
} ConsoleQueuePack_t;
void consoleLogDeamon()
{
    ConsoleQueuePack_t ret;
    while (true) {
        if (xQueueReceive(updateConsoleQueue, (void*)&ret, portMAX_DELAY) == pdTRUE) {
            xSemaphoreTake(vBuf2Mutex, portMAX_DELAY);
            // memset(vBuf2, 0x00, 1024);
            uint8_t* recvBuf = ret.str;
            uint16_t len = ret.len;
            uint8_t isInvert = ret.flag;
            uint8_t row = 0;
            uint8_t maxRow = 0;
            uint8_t column = 0;
            if (len > 44) {
                for (uint16_t i = 0; i < len; i++) {
                    if (recvBuf[i] == '\n') {
                        row = 0;
                        column++;
                    } else {
                        testPutTinyChar(vBuf2,row * 5, 6 * column, recvBuf[i], 1,isInvert);
                    }
                    maxRow = (row > maxRow) ? row : maxRow;
                    row++;
                    if (row > 20) {
                        column++;
                        row = 0;
                    }
                }
                setRect((1 + maxRow) * 5,(column + 1) * 6);
            } else {
                for (uint16_t i = 0; i < len; i++) {
                    if (recvBuf[i] == '\n') {
                        row = 0;
                        column++;
                    } else {
                        testPutChar(vBuf2,row * 8, 12 * column, recvBuf[i], 1,isInvert);
                    }
                    maxRow = (row > maxRow) ? row : maxRow;
                    row++;
                    if (row > 14) {
                        column++;
                        row = 0;
                    }
                }
                setRect((1 + maxRow) * 8,(column + 1) * 12);
            }

            // uint8_t width = (len / 25) ? 25 : (len % 25);
            // uint8_t height = (len / 25) * 5 + 5;
            // setRect(width * 5,height);
            xSemaphoreGive(vBuf2Mutex);
        }
    }
}

void logAutoInit() 
{
    // for (uint16_t i = 0; i < 1024; i++) {
    //     if((i >> 3) % 2) {
    //         vBuf2[i] = 0x55;
    //     } else {
    //         vBuf2[i] = 0xAA;
    //     }
    // }
    // drawRectangle_Optimized(vBuf2,1,1,10,10,true,false,true);
    updateRectQueue = xQueueCreate(3, sizeof(UpdateRectQueuePack_t));
    updateConsoleQueue = xQueueCreate(2, sizeof(ConsoleQueuePack_t));
    rectMutex = xSemaphoreCreateMutex();
    vBuf2Mutex = xSemaphoreCreateMutex();
    xTaskCreatePinnedToCore(logAuto, "logAuto", 8192, NULL, 6, &logAutoHandler,0);
    xTaskCreatePinnedToCore(consoleLogDeamon, "consoleLogDeamon", 3072, NULL, 7, NULL,0);
}


void consoleLog(bool isInvert,const char *format, ...) 
{
    ConsoleQueuePack_t ret = {
        .flag = isInvert,
    };
    va_list args;
    va_start(args, format);
    ret.len = vsnprintf((char*)ret.str, sizeof(ret.str), format, args);
    va_end(args);
    ret.str[223] = 0x00;
    xQueueSend(updateConsoleQueue, &ret, 0);
}

h

#ifndef SSD1306_GRAPHICS_H
#define SSD1306_GRAPHICS_H

#include "esp_log.h"
#include <stdbool.h>

void consoleLog(bool isInvert,const char *format, ...);
void logAutoInit();

#endif

附件2

zpix (github开源)

#ifndef ZPIX_H
#define ZPIX_H

#include <stdint.h>

uint8_t zpix_ascii[] = {
/*   [0x0020]    8x12 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
/*  ![0x0021]    8x12 */ 0x00,0x00,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x10,0x10,0x00,
/*  "[0x0022]    8x12 */ 0x00,0x00,0x28,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
/*  #[0x0023]    8x12 */ 0x00,0x00,0x28,0x28,0x7C,0x28,0x28,0x28,0x7C,0x28,0x28,0x00,
/*  $[0x0024]    8x12 */ 0x00,0x00,0x10,0x38,0x54,0x50,0x38,0x14,0x54,0x38,0x10,0x00,
/*  %[0x0025]    8x12 */ 0x00,0x00,0x00,0x24,0x54,0x58,0x28,0x14,0x1A,0x2A,0x24,0x00,
/*  &[0x0026]    8x12 */ 0x00,0x00,0x30,0x48,0x48,0x30,0x20,0x54,0x54,0x48,0x34,0x00,
/*  '[0x0027]    8x12 */ 0x00,0x00,0x10,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
/*  ([0x0028]    8x12 */ 0x00,0x08,0x10,0x10,0x20,0x20,0x20,0x20,0x20,0x10,0x10,0x08,
/*  )[0x0029]    8x12 */ 0x00,0x20,0x10,0x10,0x08,0x08,0x08,0x08,0x08,0x10,0x10,0x20,
/*  *[0x002A]    8x12 */ 0x00,0x00,0x00,0x00,0x10,0x10,0x7C,0x10,0x28,0x00,0x00,0x00,
/*  +[0x002B]    8x12 */ 0x00,0x00,0x00,0x00,0x10,0x10,0x7C,0x10,0x10,0x00,0x00,0x00,
/*  ,[0x002C]    8x12 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x08,
/*  -[0x002D]    8x12 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x00,0x00,
/*  .[0x002E]    8x12 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x10,0x00,
/*  /[0x002F]    8x12 */ 0x00,0x00,0x08,0x08,0x08,0x10,0x10,0x10,0x20,0x20,0x20,0x00,
/*  0[0x0030]    8x12 */ 0x00,0x00,0x38,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x38,0x00,
/*  1[0x0031]    8x12 */ 0x00,0x00,0x08,0x18,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x00,
/*  2[0x0032]    8x12 */ 0x00,0x00,0x38,0x44,0x44,0x04,0x08,0x10,0x20,0x40,0x7C,0x00,
/*  3[0x0033]    8x12 */ 0x00,0x00,0x38,0x44,0x44,0x04,0x18,0x04,0x44,0x44,0x38,0x00,
/*  4[0x0034]    8x12 */ 0x00,0x00,0x08,0x18,0x18,0x28,0x28,0x48,0x7C,0x08,0x08,0x00,
/*  5[0x0035]    8x12 */ 0x00,0x00,0x7C,0x40,0x40,0x78,0x44,0x04,0x04,0x44,0x38,0x00,
/*  6[0x0036]    8x12 */ 0x00,0x00,0x38,0x44,0x40,0x78,0x44,0x44,0x44,0x44,0x38,0x00,
/*  7[0x0037]    8x12 */ 0x00,0x00,0x7C,0x44,0x04,0x08,0x08,0x10,0x10,0x10,0x10,0x00,
/*  8[0x0038]    8x12 */ 0x00,0x00,0x38,0x44,0x44,0x44,0x38,0x44,0x44,0x44,0x38,0x00,
/*  9[0x0039]    8x12 */ 0x00,0x00,0x38,0x44,0x44,0x44,0x44,0x3C,0x04,0x44,0x38,0x00,
/*  :[0x003A]    8x12 */ 0x00,0x00,0x00,0x00,0x00,0x10,0x10,0x00,0x00,0x10,0x10,0x00,
/*  ;[0x003B]    8x12 */ 0x00,0x00,0x00,0x00,0x00,0x08,0x08,0x00,0x00,0x08,0x08,0x10,
/*  <[0x003C]    8x12 */ 0x00,0x00,0x04,0x08,0x10,0x20,0x40,0x20,0x10,0x08,0x04,0x00,
/*  =[0x003D]    8x12 */ 0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x00,0x7C,0x00,0x00,0x00,
/*  >[0x003E]    8x12 */ 0x00,0x00,0x40,0x20,0x10,0x08,0x04,0x08,0x10,0x20,0x40,0x00,
/*  ?[0x003F]    8x12 */ 0x00,0x00,0x38,0x44,0x04,0x08,0x10,0x10,0x00,0x10,0x10,0x00,
/*  @[0x0040]    8x12 */ 0x00,0x00,0x38,0x44,0x4C,0x54,0x54,0x54,0x5C,0x40,0x38,0x00,
/*  A[0x0041]    8x12 */ 0x00,0x00,0x10,0x10,0x28,0x28,0x28,0x38,0x44,0x44,0x44,0x00,
/*  B[0x0042]    8x12 */ 0x00,0x00,0x78,0x44,0x44,0x44,0x78,0x44,0x44,0x44,0x78,0x00,
/*  C[0x0043]    8x12 */ 0x00,0x00,0x38,0x44,0x44,0x40,0x40,0x40,0x44,0x44,0x38,0x00,
/*  D[0x0044]    8x12 */ 0x00,0x00,0x78,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x78,0x00,
/*  E[0x0045]    8x12 */ 0x00,0x00,0x7C,0x40,0x40,0x40,0x7C,0x40,0x40,0x40,0x7C,0x00,
/*  F[0x0046]    8x12 */ 0x00,0x00,0x7C,0x40,0x40,0x40,0x78,0x40,0x40,0x40,0x40,0x00,
/*  G[0x0047]    8x12 */ 0x00,0x00,0x38,0x44,0x44,0x40,0x5C,0x44,0x44,0x4C,0x34,0x00,
/*  H[0x0048]    8x12 */ 0x00,0x00,0x44,0x44,0x44,0x44,0x7C,0x44,0x44,0x44,0x44,0x00,
/*  I[0x0049]    8x12 */ 0x00,0x00,0x7C,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x7C,0x00,
/*  J[0x004A]    8x12 */ 0x00,0x00,0x04,0x04,0x04,0x04,0x04,0x04,0x44,0x44,0x38,0x00,
/*  K[0x004B]    8x12 */ 0x00,0x00,0x44,0x48,0x48,0x50,0x60,0x50,0x48,0x48,0x44,0x00,
/*  L[0x004C]    8x12 */ 0x00,0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x7C,0x00,
/*  M[0x004D]    8x12 */ 0x00,0x00,0x44,0x44,0x6C,0x6C,0x54,0x54,0x44,0x44,0x44,0x00,
/*  N[0x004E]    8x12 */ 0x00,0x00,0x44,0x64,0x64,0x54,0x54,0x4C,0x4C,0x44,0x44,0x00,
/*  O[0x004F]    8x12 */ 0x00,0x00,0x38,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x38,0x00,
/*  P[0x0050]    8x12 */ 0x00,0x00,0x78,0x44,0x44,0x44,0x78,0x40,0x40,0x40,0x40,0x00,
/*  Q[0x0051]    8x12 */ 0x00,0x00,0x38,0x44,0x44,0x44,0x44,0x44,0x44,0x54,0x38,0x04,
/*  R[0x0052]    8x12 */ 0x00,0x00,0x78,0x44,0x44,0x44,0x78,0x48,0x44,0x44,0x44,0x00,
/*  S[0x0053]    8x12 */ 0x00,0x00,0x38,0x44,0x44,0x20,0x10,0x08,0x44,0x44,0x38,0x00,
/*  T[0x0054]    8x12 */ 0x00,0x00,0x7C,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x00,
/*  U[0x0055]    8x12 */ 0x00,0x00,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x38,0x00,
/*  V[0x0056]    8x12 */ 0x00,0x00,0x44,0x44,0x44,0x28,0x28,0x28,0x10,0x10,0x10,0x00,
/*  W[0x0057]    8x12 */ 0x00,0x00,0x54,0x54,0x54,0x54,0x54,0x54,0x28,0x28,0x28,0x00,
/*  X[0x0058]    8x12 */ 0x00,0x00,0x44,0x44,0x28,0x28,0x10,0x28,0x28,0x44,0x44,0x00,
/*  Y[0x0059]    8x12 */ 0x00,0x00,0x44,0x44,0x44,0x28,0x28,0x10,0x10,0x10,0x10,0x00,
/*  Z[0x005A]    8x12 */ 0x00,0x00,0x7C,0x04,0x08,0x08,0x10,0x20,0x20,0x40,0x7C,0x00,
/*  [[0x005B]    8x12 */ 0x00,0x18,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x18,
/*  \[0x005C]    8x12 */ 0x00,0x00,0x20,0x20,0x20,0x10,0x10,0x10,0x08,0x08,0x08,0x00,
/*  ][0x005D]    8x12 */ 0x00,0x18,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x18,
/*  ^[0x005E]    8x12 */ 0x00,0x00,0x18,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
/*  _[0x005F]    8x12 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x00,
/*  `[0x0060]    8x12 */ 0x00,0x00,0x10,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
/*  a[0x0061]    8x12 */ 0x00,0x00,0x00,0x00,0x78,0x04,0x04,0x3C,0x44,0x44,0x3C,0x00,
/*  b[0x0062]    8x12 */ 0x00,0x00,0x40,0x40,0x78,0x44,0x44,0x44,0x44,0x44,0x78,0x00,
/*  c[0x0063]    8x12 */ 0x00,0x00,0x00,0x00,0x38,0x44,0x40,0x40,0x40,0x44,0x38,0x00,
/*  d[0x0064]    8x12 */ 0x00,0x00,0x04,0x04,0x3C,0x44,0x44,0x44,0x44,0x44,0x3C,0x00,
/*  e[0x0065]    8x12 */ 0x00,0x00,0x00,0x00,0x38,0x44,0x44,0x7C,0x40,0x44,0x38,0x00,
/*  f[0x0066]    8x12 */ 0x00,0x00,0x0C,0x10,0x10,0x3C,0x10,0x10,0x10,0x10,0x10,0x00,
/*  g[0x0067]    8x12 */ 0x00,0x00,0x00,0x00,0x3C,0x44,0x44,0x44,0x3C,0x04,0x44,0x38,
/*  h[0x0068]    8x12 */ 0x00,0x00,0x40,0x40,0x78,0x44,0x44,0x44,0x44,0x44,0x44,0x00,
/*  i[0x0069]    8x12 */ 0x00,0x00,0x10,0x00,0x30,0x10,0x10,0x10,0x10,0x10,0x38,0x00,
/*  j[0x006A]    8x12 */ 0x00,0x00,0x08,0x00,0x18,0x08,0x08,0x08,0x08,0x08,0x08,0x30,
/*  k[0x006B]    8x12 */ 0x00,0x00,0x40,0x40,0x44,0x48,0x50,0x60,0x50,0x48,0x44,0x00,
/*  l[0x006C]    8x12 */ 0x00,0x00,0x30,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x38,0x00,
/*  m[0x006D]    8x12 */ 0x00,0x00,0x00,0x00,0x68,0x54,0x54,0x54,0x54,0x54,0x54,0x00,
/*  n[0x006E]    8x12 */ 0x00,0x00,0x00,0x00,0x78,0x44,0x44,0x44,0x44,0x44,0x44,0x00,
/*  o[0x006F]    8x12 */ 0x00,0x00,0x00,0x00,0x38,0x44,0x44,0x44,0x44,0x44,0x38,0x00,
/*  p[0x0070]    8x12 */ 0x00,0x00,0x00,0x00,0x78,0x44,0x44,0x44,0x44,0x78,0x40,0x40,
/*  q[0x0071]    8x12 */ 0x00,0x00,0x00,0x00,0x3C,0x44,0x44,0x44,0x44,0x3C,0x04,0x04,
/*  r[0x0072]    8x12 */ 0x00,0x00,0x00,0x00,0x2C,0x30,0x20,0x20,0x20,0x20,0x20,0x00,
/*  s[0x0073]    8x12 */ 0x00,0x00,0x00,0x00,0x38,0x44,0x40,0x38,0x04,0x44,0x38,0x00,
/*  t[0x0074]    8x12 */ 0x00,0x00,0x10,0x10,0x3C,0x10,0x10,0x10,0x10,0x10,0x0C,0x00,
/*  u[0x0075]    8x12 */ 0x00,0x00,0x00,0x00,0x44,0x44,0x44,0x44,0x44,0x44,0x3C,0x00,
/*  v[0x0076]    8x12 */ 0x00,0x00,0x00,0x00,0x44,0x44,0x44,0x28,0x28,0x10,0x10,0x00,
/*  w[0x0077]    8x12 */ 0x00,0x00,0x00,0x00,0x54,0x54,0x54,0x54,0x38,0x28,0x28,0x00,
/*  x[0x0078]    8x12 */ 0x00,0x00,0x00,0x00,0x44,0x44,0x28,0x10,0x28,0x44,0x44,0x00,
/*  y[0x0079]    8x12 */ 0x00,0x00,0x00,0x00,0x44,0x44,0x44,0x28,0x28,0x10,0x10,0x60,
/*  z[0x007A]    8x12 */ 0x00,0x00,0x00,0x00,0x7C,0x04,0x08,0x10,0x20,0x40,0x7C,0x00,
/*  {[0x007B]    8x12 */ 0x00,0x08,0x10,0x10,0x10,0x10,0x20,0x10,0x10,0x10,0x10,0x08,
/*  |[0x007C]    8x12 */ 0x00,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
/*  }[0x007D]    8x12 */ 0x00,0x20,0x10,0x10,0x10,0x10,0x08,0x10,0x10,0x10,0x10,0x20,
/*  ~[0x007E]    8x12 */ 0x00,0x34,0x48,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
/*  [0x007F]    8x12 */ 0x00,0x00,0xFF,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0xFF,0x00,
};


#endif

tinyFont (自己做的,无版权)

#ifndef TINYFONT_H
#define TINYFONT_H 

#include <stdint.h>

uint8_t tinyFont_ascii[] = {
/*   [0x0020]    4x5  */0x00,0x00,0x00,0x00,0x00,
/*  ![0x0021]    4x5  */0x20,0x20,0x20,0x00,0x20,
/*  "[0x0022]    4x5  */0x50,0x50,0x00,0x00,0x00,
/*  #[0x0023]    4x5  */0x50,0xF0,0xA0,0xF0,0xA0,
/*  $[0x0024]    4x5  */0x70,0xA0,0x70,0x20,0xF0,
/*  %[0x0025]    4x5  */0x00,0xD0,0xE0,0x70,0xB0,
/*  &[0x0026]    4x5  */0x40,0xA0,0x40,0xA0,0x50,
/*  '[0x0027]    4x5  */0x20,0x20,0x00,0x00,0x00,
/*  ([0x0028]    4x5  */0x20,0x40,0x40,0x40,0x20,
/*  )[0x0029]    4x5  */0x20,0x10,0x10,0x10,0x20,
/*  *[0x002A]    4x5  */0x50,0x20,0x70,0x20,0x50,
/*  +[0x002B]    4x5  */0x00,0x20,0x70,0x20,0x00,
/*  ,[0x002C]    4x5  */0x00,0x00,0x20,0x20,0x40,
/*  -[0x002D]    4x5  */0x00,0x00,0x70,0x00,0x00,
/*  .[0x002E]    4x5  */0x00,0x00,0x20,0x20,0x00,
/*  /[0x002F]    4x5  */0x00,0x10,0x20,0x40,0x00,
/*  0[0x0030]    4x5  */0x60,0xB0,0xD0,0x90,0x60,
/*  1[0x0031]    4x5  */0xC0,0x40,0x40,0x40,0xE0,
/*  2[0x0032]    4x5  */0x60,0x10,0x60,0x80,0xE0,
/*  3[0x0033]    4x5  */0x60,0x10,0x60,0x10,0x60,
/*  4[0x0034]    4x5  */0x20,0x60,0xA0,0xF0,0x20,
/*  5[0x0035]    4x5  */0xF0,0x80,0x60,0x10,0x60,
/*  6[0x0036]    4x5  */0x60,0x80,0xE0,0x90,0x60,
/*  7[0x0037]    4x5  */0xF0,0x10,0x20,0x20,0x20,
/*  8[0x0038]    4x5  */0x60,0x90,0x60,0x90,0x60,
/*  9[0x0039]    4x5  */0x60,0x90,0x70,0x10,0x60,
/*  :[0x003A]    4x5  */0x20,0x20,0x00,0x20,0x20,
/*  ;[0x003B]    4x5  */0x20,0x20,0x00,0x20,0x40,
/*  <[0x003C]    4x5  */0x10,0x20,0x40,0x20,0x10,
/*  =[0x003D]    4x5  */0x00,0x70,0x00,0x70,0x00,
/*  >[0x003E]    4x5  */0x40,0x20,0x10,0x20,0x40,
/*  ?[0x003F]    4x5  */0x60,0x10,0x20,0x00,0x20,
/*  @[0x0040]    4x5  */0x60,0x90,0xB0,0x80,0x70,
/*  A[0x0041]    4x5  */0x60,0x90,0x90,0xF0,0x90,
/*  B[0x0042]    4x5  */0xE0,0x90,0xE0,0x90,0xE0,
/*  C[0x0043]    4x5  */0x70,0x80,0x80,0x80,0x70,
/*  D[0x0044]    4x5  */0xE0,0x90,0x90,0x90,0xE0,
/*  E[0x0045]    4x5  */0xF0,0x80,0xE0,0x80,0xF0,
/*  F[0x0046]    4x5  */0xF0,0x80,0xE0,0x80,0x80,
/*  G[0x0047]    4x5  */0x70,0x80,0xB0,0x90,0x70,
/*  H[0x0048]    4x5  */0x90,0x90,0xF0,0x90,0x90,
/*  I[0x0049]    4x5  */0x70,0x20,0x20,0x20,0x70,
/*  J[0x004A]    4x5  */0x30,0x10,0x10,0x90,0x60,
/*  K[0x004B]    4x5  */0x90,0xA0,0xC0,0xA0,0x90,
/*  L[0x004C]    4x5  */0x80,0x80,0x80,0x80,0xF0,
/*  M[0x004D]    4x5  */0x90,0xF0,0xF0,0x90,0x90,
/*  N[0x004E]    4x5  */0x90,0xD0,0xB0,0x90,0x90,
/*  O[0x004F]    4x5  */0x60,0x90,0x90,0x90,0x60,
/*  P[0x0050]    4x5  */0xE0,0x90,0x90,0xE0,0x80,
/*  Q[0x0051]    4x5  */0x60,0x90,0x90,0xA0,0x50,
/*  R[0x0052]    4x5  */0x60,0x90,0xE0,0xA0,0x90,
/*  S[0x0053]    4x5  */0x70,0x80,0x60,0x10,0xE0,
/*  T[0x0054]    4x5  */0x70,0x20,0x20,0x20,0x20,
/*  U[0x0055]    4x5  */0x90,0x90,0x90,0x90,0x60,
/*  V[0x0056]    4x5  */0x90,0x90,0x90,0xA0,0x40,
/*  W[0x0057]    4x5  */0x90,0x90,0xF0,0xF0,0x90,
/*  X[0x0058]    4x5  */0x90,0x90,0x60,0x90,0x90,
/*  Y[0x0059]    4x5  */0x50,0x50,0x20,0x20,0x20,
/*  Z[0x005A]    4x5  */0xF0,0x20,0x40,0x80,0xF0,
/*  [[0x005B]    4x5  */0x70,0x40,0x40,0x40,0x70,
/*  \[0x005C]    4x5  */0x80,0x40,0x20,0x10,0x00,
/*  ][0x005D]    4x5  */0x70,0x10,0x10,0x10,0x70,
/*  ^[0x005E]    4x5  */0x20,0x50,0x00,0x00,0x00,
/*  _[0x005F]    4x5  */0x00,0x00,0x00,0x00,0x70,
/*  `[0x0060]    4x5  */0x40,0x20,0x00,0x00,0x00,
/*  a[0x0061]    4x5  */0x60,0x10,0x70,0x90,0x70,
/*  b[0x0062]    4x5  */0x80,0xE0,0x90,0x90,0xE0,
/*  c[0x0063]    4x5  */0x00,0x60,0x80,0x80,0x60,
/*  d[0x0064]    4x5  */0x10,0x70,0x90,0x90,0x70,
/*  e[0x0065]    4x5  */0x00,0x60,0xB0,0xC0,0x60,
/*  f[0x0066]    4x5  */0x20,0x40,0xE0,0x40,0x40,
/*  g[0x0067]    4x5  */0x70,0x90,0x70,0x10,0x60,
/*  h[0x0068]    4x5  */0x80,0xE0,0x90,0x90,0x90,
/*  i[0x0069]    4x5  */0x20,0x00,0x20,0x20,0x20,
/*  j[0x006A]    4x5  */0x20,0x00,0x60,0x20,0xC0,
/*  k[0x006B]    4x5  */0x80,0xB0,0xC0,0xA0,0x90,
/*  l[0x006C]    4x5  */0x40,0x40,0x40,0x40,0x20,
/*  m[0x006D]    4x5  */0x00,0x90,0xF0,0x90,0x90,
/*  n[0x006E]    4x5  */0x00,0x60,0x90,0x90,0x90,
/*  o[0x006F]    4x5  */0x00,0x60,0x90,0x90,0x60,
/*  p[0x0070]    4x5  */0xE0,0x90,0x90,0xE0,0x80,
/*  q[0x0071]    4x5  */0x70,0x90,0x90,0x70,0x10,
/*  r[0x0072]    4x5  */0x30,0x40,0x40,0x40,0x40,
/*  s[0x0073]    4x5  */0x60,0x80,0x60,0x10,0x60,
/*  t[0x0074]    4x5  */0x40,0xE0,0x40,0x40,0x30,
/*  u[0x0075]    4x5  */0x00,0x90,0x90,0x90,0x60,
/*  v[0x0076]    4x5  */0x00,0x90,0x90,0xA0,0x40,
/*  w[0x0077]    4x5  */0x00,0x90,0x90,0xF0,0x90,
/*  x[0x0078]    4x5  */0x00,0x50,0x20,0x20,0x50,
/*  y[0x0079]    4x5  */0x50,0x50,0x30,0x10,0x60,
/*  z[0x007A]    4x5  */0xF0,0x10,0x20,0x40,0xF0,
/*  {[0x007B]    4x5  */0x30,0x20,0x40,0x20,0x30,
/*  |[0x007C]    4x5  */0x20,0x20,0x20,0x20,0x20,
/*  }[0x007D]    4x5  */0x60,0x20,0x10,0x20,0x60,
/*  ~[0x007E]    4x5  */0x00,0x40,0xF0,0x20,0x00,
/*  [0x007F]    4x5  */0x00,0x00,0x00,0x00,0x00,

};

#endif

此作者没有提供个人介绍。
最后更新于 2025-07-17