目录
[1 STM32调试方式](#1 STM32调试方式)
[1.1 串口调试](#1.1 串口调试)
[1.2 显示屏调试](#1.2 显示屏调试)
[1.3 Keil调试模式(在线仿真调试)](#1.3 Keil调试模式(在线仿真调试))
[2 OLED显示屏简介](#2 OLED显示屏简介)
[2.1 概述](#2.1 概述)
[2.2 硬件解析](#2.2 硬件解析)
[2.2.1 模块外观与引脚定义](#2.2.1 模块外观与引脚定义)
[2.2.2 连接方式](#2.2.2 连接方式)
[2.2.3 OLED 驱动芯片:SSD1306](#2.2.3 OLED 驱动芯片:SSD1306)
[2.2.3.1 图像显示RAM(GDDRAM)](#2.2.3.1 图像显示RAM(GDDRAM))
[2.2.3.2 字模取模原理与 OLED 显示流程解析](#2.2.3.2 字模取模原理与 OLED 显示流程解析)
[2.2.3.2.1 什么是字模取模](#2.2.3.2.1 什么是字模取模)
[2.2.3.2.2 8×16 字体字模的数据组织方式](#2.2.3.2.2 8×16 字体字模的数据组织方式)
[2.2.3.2.3 从"字模数组"到"屏幕像素"的完整映射关系](#2.2.3.2.3 从“字模数组”到“屏幕像素”的完整映射关系)
[2.3 软件驱动与示例](#2.3 软件驱动与示例)
[2.3.1 OLED_Init ------ OLED 初始化函数](#2.3.1 OLED_Init —— OLED 初始化函数)
[2.3.2 OLED_Clear ------ OLED 清屏函数](#2.3.2 OLED_Clear —— OLED 清屏函数)
[2.3.3 OLED_ShowChar ------ 显示单个字符(8×16 字体)](#2.3.3 OLED_ShowChar —— 显示单个字符(8×16 字体))
[2.3.4 OLED_ShowString ------ 显示字符串](#2.3.4 OLED_ShowString —— 显示字符串)
[2.3.5 OLED_ShowNum ------ 显示无符号十进制数](#2.3.5 OLED_ShowNum —— 显示无符号十进制数)
[2.3.6 OLED_ShowSignedNum ------ 显示有符号十进制数](#2.3.6 OLED_ShowSignedNum —— 显示有符号十进制数)
[2.3.7 OLED_ShowHexNum ------ 显示十六进制数](#2.3.7 OLED_ShowHexNum —— 显示十六进制数)
[2.3.8 OLED_ShowBinNum ------ 显示二进制数](#2.3.8 OLED_ShowBinNum —— 显示二进制数)
[2.4 驱动库文件](#2.4 驱动库文件)
[2.4.1 OLED.h文件](#2.4.1 OLED.h文件)
[2.4.3 OLED_Font.h文件](#2.4.3 OLED_Font.h文件)
前言: 在使用 0.96 寸 OLED 单色显示屏模块时,需要特别注意不同版本模块的引脚排序并不一致。
- 老版本模块:VCC -- GND -- SCL -- SDA
- 新版本模块(江科大教程使用):GND -- VCC -- SCL -- SDA
在实际接线前,务必核对手中 OLED 模块的丝印标识,避免因引脚顺序错误导致模块无法工作甚至损坏。
如果你使用的是老版本 OLED 模块,只需在硬件连接层面对 PB6 和 PB7 的连接方式进行调整(PB6 接 VCC,PB7 接 GND),软件程序无需修改,可直接沿用江科大教程中的代码。
本文将先介绍 STM32 中常见的三种调试方式,随后重点展开基于 0.96 寸 OLED 显示屏的调试方法与实现原理。
1 STM32调试方式
在 STM32 嵌入式开发过程中,常见的调试方式主要有以下三种,开发者可根据项目阶段和实际环境灵活选择。
1.1 串口调试
串口调试是最基础、也是使用最广泛的一种调试手段。其核心思想是通过 STM32 的 USART/UART 外设,将程序中的调试信息(如变量值、状态标志、流程提示等)以文本形式发送到计算机端。
- 硬件连接:通常使用 USB 转 TTL 串口模块,将 STM32 的 TX / RX 引脚与计算机的 USB 接口相连。
- 软件工具:计算机端需配合串口调试软件(如 SecureCRT、PuTTY、串口调试助手等)进行数据显示。
- 优点:实现简单、成本低,不依赖额外显示硬件,适合连续数据输出和日志记录。
- 局限性:依赖上位机,系统无法完全独立运行;显示形式为纯文本,可视化程度较低。
1.2 显示屏调试
显示屏调试是通过在系统中集成显示模块(如 OLED、LCD),将关键运行信息直接显示出来,实现"脱机可视化调试"。
- 硬件连接:显示屏可通过并口、SPI 或 I²C 接口与 STM32 相连。
- 实现方式:在程序中将变量、状态等信息转换为字符或图形数据,通过显示驱动函数输出到屏幕。
- 优点:系统自成一体,无需外部设备;显示信息直观,适合现场调试和产品运行状态监控。
- 局限性:增加硬件成本与功耗;显示信息量受屏幕尺寸与分辨率限制。
1.3 Keil调试模式(在线仿真调试)
Keil MDK 等集成开发环境提供了功能强大的在线仿真调试能力,允许开发者直接观察芯片内部运行状态。
- 硬件需求:通过 JTAG 或 SWD 接口连接调试器(如ST-LINK、J-Link)。
- 核心功能:
单步/多步执行:逐条语句运行程序,精细观察执行流程。
断点设置:在任意代码行设置断点,程序运行到此处会自动暂停。
实时查看:可随时查看和修改寄存器、内存、全局/局部变量的值。
外设寄存器查看:直观监控外设(如GPIO、TIM、USART)寄存器的状态变化。
逻辑分析仪:部分高级调试器支持跟踪引脚波形。
- 优点:调试能力最强,可精确定位逻辑错误、数据错误及时序问题。
- 局限性:需要额外调试硬件;部分对时序敏感的代码在仿真环境与真实硬件上可能存在差异。
2 OLED显示屏简介
2.1 概述
OLED(Organic Light-Emitting Diode,有机发光二极管)是一种基于有机半导体材料的电致发光显示技术。其基本原理是:当电流通过有机材料层时,电子与空穴在发光层中复合,并以光子的形式释放能量,从而产生可见光。
OLED 的每一个像素都是独立的自发光单元,不需要背光源,这一点与依赖背光源的传统 LCD 显示技术存在本质区别。因此,OLED 具备对比度高、响应速度快、视角大、功耗低等优点。
本文使用的 0.96 寸单色 OLED 模块分辨率为 128×64,工作电压范围为 3.3V~5V。根据通信接口不同,常见模块分为:
- 4 引脚 I²C 接口版本
- 7 引脚 SPI 接口版本
本文将以应用最为广泛的4 引脚 I²C 接口 OLED 模块为例,介绍其硬件连接方式与软件驱动原理。
2.2 硬件解析
2.2.1 模块外观与引脚定义
典型的4线I²C接口OLED模块实物如图所示:

模块的四个引脚定义及功能如下:
| 引脚名称 | 功能描述 | 连接说明 |
|---|---|---|
| GND | 电源地 | 连接至STM32及系统 GND |
| VCC | 电源正极 | 连接至3.3V或5V电源,模块内部集成升压电路 |
| SCL | I²C时钟线 | 连接至 STM32 的 I²C SCL 引脚或任意 GPIO(软件 I²C) |
| SDA | I²C数据线 | 连接至 STM32 的 I²C SDA 引脚或任意 GPIO(软件 I²C) |
地址配置说明: 大多数 4 线 I²C OLED 模块已在硬件上将地址选择引脚固定接地,其 7 位设备地址通常为 0x3C,对应的 8 位写地址为 0x78,读地址为 0x79。
2.2.2 连接方式
OLED 模块主要支持以下两种连接方式,由于初学阶段硬件 I²C 的初始化和调试成本较高,且引脚复用受限,江科大教程中采用软件模拟 I²C 的方式,便于理解通信过程,同时提高引脚使用灵活性。因此,本文采用软件模拟 I²C方式进行说明。
- 硬件I²C连接:将 SCL、SDA 直接连接至 STM32 支持 I²C 外设的引脚(如 I2C1 的 PB6 / PB7)。该方式通信效率高、CPU 占用少,是推荐方案。
- 软件模拟I²C(Bit-Banging)连接:将 SCL、SDA 连接到任意两个可用 GPIO 引脚,通过软件控制时序实现 I²C 通信。该方式引脚灵活性高,但对 CPU 占用较多,对时序控制要求更高。
Bit-Banging :直译为"位敲打",指不依赖MCU 的硬件I²C外设,而是通过软件按位控制 GPIO 的高低电平和时序,从而模拟通信协议的一种方法。
接线图如图所示:

注意:在 STM32 上电复位后,GPIO 默认处于浮空输入模式,此时引脚为高阻态,将其直接连接到 GND 或 VCC 在电气上是安全的,不会产生大电流或损坏芯片。因此在面包板实验中,临时使用 GPIO 代替电源给 OLED 供电是可行的。
但需要注意,这种方式仅适用于临时调试,后续一旦将该引脚配置为输出,必须确保不再与 GND/VCC 直连,否则可能造成引脚对拉。工程设计中仍应使用专用电源引脚为外设供电。
2.2.3 OLED 驱动芯片:SSD1306
该 OLED 模块的核心控制芯片为 SSD1306,它充当了 STM32 与 OLED 面板之间的桥梁。
OLED 面板本身由 128×64 = 8192 个独立像素点组成,如果直接由 STM32 控制每一个像素显然不现实。SSD1306 的作用是将复杂的像素控制封装为标准化的命令与数据接口,极大简化了软件设计。
实物与封装如图所示:

原理图如图所示,了解即可:

SSD1306 的主要特性包括:
- 集成度高:内部集成 GDDRAM、振荡器、DC-DC 升压电路及对比度调节模块。
- 供电简化:内置电荷泵升压电路,可将 3.3V / 5V 电压提升至 OLED 面板所需的驱动电压(约 7.5V~15V),无需外部提供高压电源。
- 显存管理 :内置 1KB 图形显示数据 RAM(GDDRAM,128 × 64 bit),其组织结构为 8 页(Page) × 128 列(Segment),即128×64 bit。整个128×64 bit 的显存完整映射到 128×64 像素的屏幕上,开发者只需向这片内存写入数据即可同步更新显示内容到指定的屏幕位置上。如图所示:

- 接口灵活:支持多种接口模式(通过模块上的BS0~BS2引脚配置),包括I²C、SPI及并行接口。
2.2.3.1 图像显示RAM(GDDRAM)
本小节内容是理解 OLED 字符显示和字模取模的关键,初次阅读可结合后文的 OLED_ShowChar 函数对照理解。
GDDRAM是一个位映射静态RAM,用于存储待显示的位模式。内存大小为128*64bit, 以 "页(Page)" 为单位进行管理,分为八个页,从PAGEO到PAGE7,用于单色128×64点阵显示。每一页包含 8 行像素,每页共 128 字节。如图所示:

当向 SSD1306 的 GDDRAM 写入一个数据字节时,写入操作是以字节为单位进行的。一个字节对应同一 Page 内、同一列方向上的 8 个像素点。
具体来说:
- GDDRAM 按 Page(页) 进行组织,每个 Page 包含垂直方向连续的 8 行像素;
- 当列地址和页地址确定后,向 GDDRAM 写入 1 个字节,该字节的 8 个 bit(D0~D7) 会依次映射到该列在当前 Page 中的 8 个像素点;
- 其中,D0 对应 Page 顶部的像素点,D7 对应 Page 底部的像素点,从而一次写入即可更新一整列的 8 个像素。
基于这一显存组织方式,可以推导出不同字体的屏幕占用关系:
- 8×16 字体:字符高度为 16 像素,需要占用 上下两个 Page;字符宽度为 8 像素,占用 8 列,因此总占用为 2 页 × 8 列;
- 6×8 字体:字符高度为 8 像素,仅占用 1 个 Page;字符宽度为 6 像素(通常按 8 列对齐存储),因此占用 1 页 × 8 列。

由于 SSD1306 的 GDDRAM 以"页"为单位组织,而每页对应垂直方向的 8 个像素,因此在 128×64 分辨率的 OLED 屏幕上,采用 8×16 字体时,屏幕最多可显示:4 行 × 16 列 的字符内容。
这里我将字符"A"的两种类型的字模数据都替换为0xFF,字母"D"的不变,通过程序编译下载后演示在屏幕中,方面大家直观的观察两种类型的字体在屏幕上的占用区域大小。如图所示:

2.2.3.2 字模取模原理与 OLED 显示流程解析
在 OLED 显示中,字符或图形最终呈现在屏幕上的本质,是向 SSD1306 的 GDDRAM 写入字节数据。而所谓"字模取模",实际上就是提前准备好一组与 GDDRAM 显存组织方式完全匹配的字节数据。
2.2.3.2.1 什么是字模取模
字模取模,是指将字符或图形按照 OLED 显示规则转换为一组二进制数据(字节数组),用于描述每个像素点的亮灭状态。
由于 SSD1306 的 GDDRAM 具有如下特性:
- 以 Page(页)为单位组织;
- 向 GDDRAM 写入 1 个字节 = 写入同一 Page、同一列的 8 个像素;
因此,在取模时,必须按照 "列优先、页内 8 像素一组" 的方式生成字模数据,否则显示结果将出现错位或颠倒。
2.2.3.2.2 8×16 字体字模的数据组织方式
以常见的 8×16 点阵字体为例:
- 字符宽度:8 像素 → 对应 8 列
- 字符高度:16 像素 → 对应 2 个 Page
因此,一个 8×16 字符在 SSD1306 的 GDDRAM 显示模型下,需要 16 个字节来描述,其字模数据通常按如下顺序存储:
- 前 8 个字节:字符 上半部分(Page N) 的 8 列数据
- 后 8 个字节:字符 下半部分(Page N+1) 的 8 列数据

每一个字节内部:
- bit0(D0)表示该列 最上方像素
- bit7(D7)表示该列 最下方像素
这正好与 SSD1306 的 GDDRAM 写入规则一一对应。
2.2.3.2.3 从"字模数组"到"屏幕像素"的完整映射关系
可以用一句话总结整个过程:字模数组中的每一个字节,最终都会原封不动地写入 SSD1306 的 GDDRAM,对应同一 Page、同一列方向上的 8 个像素点。
因此,字模数组的排列方式,必须与 GDDRAM 的存储方式严格一致。而OLED 显示函数的本质,无非就是把字模数据按顺序搬运到显存中。一旦理解了 GDDRAM 的页结构,字符显示、图像显示、取模方向等问题都会迎刃而解。
从本质上看,OLED 显示并不"懂字符",它只负责显示 GDDRAM 中的位数据;字符、字符串、数字等概念,全部是在软件层通过字模和显示函数人为抽象出来的。
2.3 软件驱动与示例
STM32 通过 I²C 总线向 SSD1306 发送命令和数据即可完成 OLED 的初始化与显示控制,相关的底层操作已被UP主封装为不同的库版本,我们直接使用即可。函数的具体实现这里就不涉及,想深入了解的话,建议观看江科大的[模块教程] 第1期 0.96寸OLED显示屏_哔哩哔哩_bilibili。
由于江科大UP在模块教程和STM32教程中使用的OLED驱动库的底层实现有所不同,且本文为STM32教程的学习笔记,所以本文以STM32教程中使用的OLED驱动库版本为基础,讲解和演示常用的功能接口的用法。
先看一下驱动库中常用的函数的所用:

上图中3~8行函数的显示效果如下图OLED显示屏所示:

可以看出,UP主将 128×64 的显示屏划分为: 4行x16列,函数的前两个参数分别表示显示的行位置(取值范围:1~4)和列位置(取值范围:1~16),且全部统一使用 8*16 类型字体。
下面将结合具体代码,对 8 个最常用的 OLED 接口函数做一个简要的说明。
2.3.1 OLED_Init ------ OLED 初始化函数
cpp
void OLED_Init(void)
{
uint32_t i, j;
for (i = 0; i < 1000; i++) //上电延时
{
for (j = 0; j < 1000; j++);
}
OLED_I2C_Init(); //端口初始化
OLED_WriteCommand(0xAE); //关闭显示
OLED_WriteCommand(0xD5); //设置显示时钟分频比/振荡器频率
OLED_WriteCommand(0x80);
OLED_WriteCommand(0xA8); //设置多路复用率
OLED_WriteCommand(0x3F);
OLED_WriteCommand(0xD3); //设置显示偏移
OLED_WriteCommand(0x00);
OLED_WriteCommand(0x40); //设置显示开始行
OLED_WriteCommand(0xA1); //设置左右方向,0xA1正常 0xA0左右反置
OLED_WriteCommand(0xC8); //设置上下方向,0xC8正常 0xC0上下反置
OLED_WriteCommand(0xDA); //设置COM引脚硬件配置
OLED_WriteCommand(0x12);
OLED_WriteCommand(0x81); //设置对比度控制
OLED_WriteCommand(0xCF);
OLED_WriteCommand(0xD9); //设置预充电周期
OLED_WriteCommand(0xF1);
OLED_WriteCommand(0xDB); //设置VCOMH取消选择级别
OLED_WriteCommand(0x30);
OLED_WriteCommand(0xA4); //设置整个显示打开/关闭
OLED_WriteCommand(0xA6); //设置正常/倒转显示
OLED_WriteCommand(0x8D); //设置充电泵
OLED_WriteCommand(0x14);
OLED_WriteCommand(0xAF); //开启显示
OLED_Clear(); //OLED清屏
}
功能说明:
这是 OLED 驱动的入口函数,负责完成 OLED 模块的完整初始化流程,包括:
- 软件 I²C GPIO 端口初始化
- SSD1306 控制器初始化配置
- 开启显示
- 清屏
使用示例:
cpp
OLED_Init();
注意事项:
- 必须最先调用
- 在调用任何 OLED_ShowXXX() 函数之前执行
- 内部已包含上电延时和清屏等操作
2.3.2 OLED_Clear ------ OLED 清屏函数
cpp
void OLED_Clear(void)
{
uint8_t i, j;
for (j = 0; j < 8; j++)
{
OLED_SetCursor(j, 0);
for(i = 0; i < 128; i++)
{
OLED_WriteData(0x00);
}
}
}
功能说明:
将 OLED 显存(GDDRAM)全部写为 0x00,实现整屏清空。实现原理(简述):
- SSD1306 共 8 页(Page),每页 128 字节
- 逐页逐列写入 0x00
使用示例:
cpp
OLED_Clear();
典型使用场景:
- 初始化后清屏
- 刷新显示内容前清空旧内容
2.3.3 OLED_ShowChar ------ 显示单个字符(8×16 字体)
cpp
void OLED_ShowChar(uint8_t Line, uint8_t Column, char Char)
{
uint8_t i;
OLED_SetCursor((Line - 1) * 2, (Column - 1) * 8); //设置光标位置在上半部分,用于指定8x16类型字体的上半部分字模数据显示的位置
for (i = 0; i < 8; i++)
{
OLED_WriteData(OLED_F8x16[Char - ' '][i]); //显示上半部分内容
}
OLED_SetCursor((Line - 1) * 2 + 1, (Column - 1) * 8); //设置光标位置在下半部分,用于指定8x16类型字体的下半部分字模数据显示的位置
for (i = 0; i < 8; i++)
{
OLED_WriteData(OLED_F8x16[Char - ' '][i + 8]); //显示下半部分内容
}
}
功能说明:
在指定的行、列位置显示一个 ASCII 字符,使用 8×16 点阵字体。之后介绍的很多函数都是基于此函数进行封装的。
参数说明:
| 参数 | 含义 | 取值范围 |
|---|---|---|
| Line | 行号 | 1 ~ 4 |
| Column | 列号 | 1 ~ 16 |
| Char | 要显示的字符 | ASCII 可见字符 |
- 1 行 = 2 个 Page = 16 个像素宽度
- 1 列 = 8 个像素宽度
函数的显示逻辑:
在 OLED_ShowChar 函数中,字符显示流程可以概括为以下三步(这一部分大概了解即可,想更详细了解,建议去看UP主发布的模块教程):
(1)计算显示起始位置
cpp
OLED_SetCursor((Line - 1) * 2, (Column - 1) * 8);
-
(Line - 1) * 2: 将行号转换为 **Page 地址,**每一行字符占用 2 个 Page(8×16 字体)
-
(Column - 1) * 8: 将列号转换为 **Column 列地址,**每个字符占用 8 列像素
(2)写入字模上半部分(前 8 个字节)
cpp
OLED_WriteData(OLED_F8x16[Char - ' '][i]);
- 依次写入字模数组中前 8 个字节;
- 每写入 1 个字节,即更新当前 Page 中 一整列的 8 个像素;
- 连续写 8 次,完成字符上半部分的显示。
(3)切换到下一 Page,写入下半部分
cpp
OLED_SetCursor((Line - 1) * 2 + 1, (Column - 1) * 8); OLED_WriteData(OLED_F8x16[Char - ' '][i + 8]);
- Page 地址加 1,移动到字符的下半部分;
- 写入字模数组后 8 个字节;
- 完成整个 8×16 字符的显示。
使用示例:
cpp
OLED_ShowChar(1, 1, 'A');
2.3.4 OLED_ShowString ------ 显示字符串
cpp
void OLED_ShowString(uint8_t Line, uint8_t Column, char *String)
{
uint8_t i;
for (i = 0; String[i] != '\0'; i++)
{
OLED_ShowChar(Line, Column + i, String[i]);
}
}
功能说明:
从指定位置开始,连续显示一个字符串。
当字符串长度超过当前行的可显示范围时,由于函数内部未对列位置进行边界判断,后续字符会覆盖本行起始位置的显示内容,而不会自动换行。
参数说明:
| 参数 | 含义 |
|---|---|
| Line | 起始行(1~4) |
| Column | 起始列(1~16) |
| String | 字符串首地址 |
实现方式:
- 内部逐字符调用 OLED_ShowChar()
- 遇到 空字符 ' \0*'*结束
使用示例:
cpp
OLED_ShowString(1, 3, "HelloWorld!");
2.3.5 OLED_ShowNum ------ 显示无符号十进制数
cpp
void OLED_ShowNum(uint8_t Line, uint8_t Column, uint32_t Number, uint8_t Length)
{
uint8_t i;
for (i = 0; i < Length; i++)
{
OLED_ShowChar(Line, Column + i, Number / OLED_Pow(10, Length - i - 1) % 10 + '0');
}
}
功能说明:
以十进制形式指定长度的显示一个无符号整数,且高位不足时补0显示。
参数说明:
| 参数 | 含义 |
|---|---|
| Line | 起始行位置,范围:1~4 |
| Column | 起始列位置,范围:1~16 |
| Number | 要显示的数字,范围:0~4294967295 |
| Length | 要显示数字的长度,范围:1~10 |
使用示例:
cpp
OLED_ShowNum(2, 1, 12345, 5);
2.3.6 OLED_ShowSignedNum ------ 显示有符号十进制数
cpp
void OLED_ShowSignedNum(uint8_t Line, uint8_t Column, int32_t Number, uint8_t Length)
{
uint8_t i;
uint32_t Number1;
if (Number >= 0)
{
OLED_ShowChar(Line, Column, '+');
Number1 = Number;
}
else
{
OLED_ShowChar(Line, Column, '-');
Number1 = -Number;
}
for (i = 0; i < Length; i++)
{
OLED_ShowChar(Line, Column + i + 1, Number1 / OLED_Pow(10, Length - i - 1) % 10 + '0');
}
}
功能说明:
显示带正负号的十进制整数。
参数说明:
| 参数 | 含义 |
|---|---|
| Line | 起始行位置,范围:1~4 |
| Column | 起始列位置,范围:1~16 |
| Number | 要显示的数字,范围:-2147483648~2147483647 |
| Length | 要显示数字的长度,范围:1~10,Length 不包含符号位,符号占用 1 列 |
使用示例:
cpp
OLED_ShowSignedNum(2, 7, -66, 2);
2.3.7 OLED_ShowHexNum ------ 显示十六进制数
cpp
void OLED_ShowHexNum(uint8_t Line, uint8_t Column, uint32_t Number, uint8_t Length)
{
uint8_t i, SingleNumber;
for (i = 0; i < Length; i++)
{
SingleNumber = Number / OLED_Pow(16, Length - i - 1) % 16;
if (SingleNumber < 10)
{
OLED_ShowChar(Line, Column + i, SingleNumber + '0');
}
else
{
OLED_ShowChar(Line, Column + i, SingleNumber - 10 + 'A');
}
}
}
功能说明:
以 十六进制格式显示无符号整数,不自动加 0x 前缀
参数说明:
| 参数 | 含义 |
| Line | 起始行位置,范围:1~4 |
| Column | 起始列位置,范围:1~16 |
| Number | 要显示的数字,范围:0~0xFFFFFFFF |
| Length | 要显示数字的长度,范围:1~8 |
|---|
使用示例:
cpp
OLED_ShowHexNum(3, 1, 0xAA55, 4);
2.3.8 OLED_ShowBinNum ------ 显示二进制数
cpp
void OLED_ShowBinNum(uint8_t Line, uint8_t Column, uint32_t Number, uint8_t Length)
{
uint8_t i;
for (i = 0; i < Length; i++)
{
OLED_ShowChar(Line, Column + i, Number / OLED_Pow(2, Length - i - 1) % 2 + '0');
}
}
功能说明:
以二进制形式显示一个整数。
参数说明:
| 参数 | 含义 |
| Line | 起始行位置,范围:1~4 |
| Column | 起始列位置,范围:1~16 |
| Number | 要显示的数字,范围:0~1111 1111 1111 1111 |
| Length | 要显示的二进制位数,范围:1~16 |
|---|
使用示例:
cpp
OLED_ShowBinNum(4, 1, 0xAA55, 16);
2.4 驱动库文件
2.4.1 OLED.h文件
cpp
#ifndef __OLED_H
#define __OLED_H
#include "stm32f10x.h"
void OLED_Init(void);
void OLED_Clear(void);
void OLED_ShowChar(uint8_t Line, uint8_t Column, char Char);
void OLED_ShowString(uint8_t Line, uint8_t Column, char *String);
void OLED_ShowNum(uint8_t Line, uint8_t Column, uint32_t Number, uint8_t Length);
void OLED_ShowSignedNum(uint8_t Line, uint8_t Column, int32_t Number, uint8_t Length);
void OLED_ShowHexNum(uint8_t Line, uint8_t Column, uint32_t Number, uint8_t Length);
void OLED_ShowBinNum(uint8_t Line, uint8_t Column, uint32_t Number, uint8_t Length);
#endif
2.4.2OLED.c文件
cpp
#include "OLED.h"
#include "OLED_Font.h"
/*引脚配置*/
#define OLED_W_SCL(x) GPIO_WriteBit(GPIOB, GPIO_Pin_8, (BitAction)(x))
#define OLED_W_SDA(x) GPIO_WriteBit(GPIOB, GPIO_Pin_9, (BitAction)(x))
/*引脚初始化*/
void OLED_I2C_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_Init(GPIOB, &GPIO_InitStructure);
OLED_W_SCL(1);
OLED_W_SDA(1);
}
/**
* @brief I2C开始
* @param 无
* @retval 无
*/
void OLED_I2C_Start(void)
{
OLED_W_SDA(1);
OLED_W_SCL(1);
OLED_W_SDA(0);
OLED_W_SCL(0);
}
/**
* @brief I2C停止
* @param 无
* @retval 无
*/
void OLED_I2C_Stop(void)
{
OLED_W_SDA(0);
OLED_W_SCL(1);
OLED_W_SDA(1);
}
/**
* @brief I2C发送一个字节
* @param Byte 要发送的一个字节
* @retval 无
*/
void OLED_I2C_SendByte(uint8_t Byte)
{
uint8_t i;
for (i = 0; i < 8; i++)
{
OLED_W_SDA(!!(Byte & (0x80 >> i)));
OLED_W_SCL(1);
OLED_W_SCL(0);
}
OLED_W_SCL(1); //额外的一个时钟,不处理应答信号
OLED_W_SCL(0);
}
/**
* @brief OLED写命令
* @param Command 要写入的命令
* @retval 无
*/
void OLED_WriteCommand(uint8_t Command)
{
OLED_I2C_Start();
OLED_I2C_SendByte(0x78); //从机地址
OLED_I2C_SendByte(0x00); //写命令
OLED_I2C_SendByte(Command);
OLED_I2C_Stop();
}
/**
* @brief OLED写数据
* @param Data 要写入的数据
* @retval 无
*/
void OLED_WriteData(uint8_t Data)
{
OLED_I2C_Start();
OLED_I2C_SendByte(0x78); //从机地址
OLED_I2C_SendByte(0x40); //写数据
OLED_I2C_SendByte(Data);
OLED_I2C_Stop();
}
/**
* @brief OLED设置光标位置
* @param Y 以左上角为原点,向下方向的坐标,范围:0~7
* @param X 以左上角为原点,向右方向的坐标,范围:0~127
* @retval 无
*/
void OLED_SetCursor(uint8_t Y, uint8_t X)
{
OLED_WriteCommand(0xB0 | Y); //设置Y位置
OLED_WriteCommand(0x10 | ((X & 0xF0) >> 4)); //设置X位置高4位
OLED_WriteCommand(0x00 | (X & 0x0F)); //设置X位置低4位
}
/**
* @brief OLED清屏
* @param 无
* @retval 无
*/
void OLED_Clear(void)
{
uint8_t i, j;
for (j = 0; j < 8; j++)
{
OLED_SetCursor(j, 0);
for(i = 0; i < 128; i++)
{
OLED_WriteData(0x00);
}
}
}
/**
* @brief OLED显示一个字符
* @param Line 行位置,范围:1~4
* @param Column 列位置,范围:1~16
* @param Char 要显示的一个字符,范围:ASCII可见字符
* @retval 无
*/
void OLED_ShowChar(uint8_t Line, uint8_t Column, char Char)
{
uint8_t i;
OLED_SetCursor((Line - 1) * 2, (Column - 1) * 8); //设置光标位置在上半部分
for (i = 0; i < 8; i++)
{
OLED_WriteData(OLED_F8x16[Char - ' '][i]); //显示上半部分内容
}
OLED_SetCursor((Line - 1) * 2 + 1, (Column - 1) * 8); //设置光标位置在下半部分
for (i = 0; i < 8; i++)
{
OLED_WriteData(OLED_F8x16[Char - ' '][i + 8]); //显示下半部分内容
}
}
/**
* @brief OLED显示字符串
* @param Line 起始行位置,范围:1~4
* @param Column 起始列位置,范围:1~16
* @param String 要显示的字符串,范围:ASCII可见字符
* @retval 无
*/
void OLED_ShowString(uint8_t Line, uint8_t Column, char *String)
{
uint8_t i;
for (i = 0; String[i] != '\0'; i++)
{
OLED_ShowChar(Line, Column + i, String[i]);
}
}
/**
* @brief OLED次方函数
* @retval 返回值等于X的Y次方
*/
uint32_t OLED_Pow(uint32_t X, uint32_t Y)
{
uint32_t Result = 1;
while (Y--)
{
Result *= X;
}
return Result;
}
/**
* @brief OLED显示数字(十进制,正数)
* @param Line 起始行位置,范围:1~4
* @param Column 起始列位置,范围:1~16
* @param Number 要显示的数字,范围:0~4294967295
* @param Length 要显示数字的长度,范围:1~10
* @retval 无
*/
void OLED_ShowNum(uint8_t Line, uint8_t Column, uint32_t Number, uint8_t Length)
{
uint8_t i;
for (i = 0; i < Length; i++)
{
OLED_ShowChar(Line, Column + i, Number / OLED_Pow(10, Length - i - 1) % 10 + '0');
}
}
/**
* @brief OLED显示数字(十进制,带符号数)
* @param Line 起始行位置,范围:1~4
* @param Column 起始列位置,范围:1~16
* @param Number 要显示的数字,范围:-2147483648~2147483647
* @param Length 要显示数字的长度,范围:1~10
* @retval 无
*/
void OLED_ShowSignedNum(uint8_t Line, uint8_t Column, int32_t Number, uint8_t Length)
{
uint8_t i;
uint32_t Number1;
if (Number >= 0)
{
OLED_ShowChar(Line, Column, '+');
Number1 = Number;
}
else
{
OLED_ShowChar(Line, Column, '-');
Number1 = -Number;
}
for (i = 0; i < Length; i++)
{
OLED_ShowChar(Line, Column + i + 1, Number1 / OLED_Pow(10, Length - i - 1) % 10 + '0');
}
}
/**
* @brief OLED显示数字(十六进制,正数)
* @param Line 起始行位置,范围:1~4
* @param Column 起始列位置,范围:1~16
* @param Number 要显示的数字,范围:0~0xFFFFFFFF
* @param Length 要显示数字的长度,范围:1~8
* @retval 无
*/
void OLED_ShowHexNum(uint8_t Line, uint8_t Column, uint32_t Number, uint8_t Length)
{
uint8_t i, SingleNumber;
for (i = 0; i < Length; i++)
{
SingleNumber = Number / OLED_Pow(16, Length - i - 1) % 16;
if (SingleNumber < 10)
{
OLED_ShowChar(Line, Column + i, SingleNumber + '0');
}
else
{
OLED_ShowChar(Line, Column + i, SingleNumber - 10 + 'A');
}
}
}
/**
* @brief OLED显示数字(二进制,正数)
* @param Line 起始行位置,范围:1~4
* @param Column 起始列位置,范围:1~16
* @param Number 要显示的数字,范围:0~1111 1111 1111 1111
* @param Length 要显示数字的长度,范围:1~16
* @retval 无
*/
void OLED_ShowBinNum(uint8_t Line, uint8_t Column, uint32_t Number, uint8_t Length)
{
uint8_t i;
for (i = 0; i < Length; i++)
{
OLED_ShowChar(Line, Column + i, Number / OLED_Pow(2, Length - i - 1) % 2 + '0');
}
}
/**
* @brief OLED初始化
* @param 无
* @retval 无
*/
void OLED_Init(void)
{
uint32_t i, j;
for (i = 0; i < 1000; i++) //上电延时
{
for (j = 0; j < 1000; j++);
}
OLED_I2C_Init(); //端口初始化
OLED_WriteCommand(0xAE); //关闭显示
OLED_WriteCommand(0xD5); //设置显示时钟分频比/振荡器频率
OLED_WriteCommand(0x80);
OLED_WriteCommand(0xA8); //设置多路复用率
OLED_WriteCommand(0x3F);
OLED_WriteCommand(0xD3); //设置显示偏移
OLED_WriteCommand(0x00);
OLED_WriteCommand(0x40); //设置显示开始行
OLED_WriteCommand(0xA1); //设置左右方向,0xA1正常 0xA0左右反置
OLED_WriteCommand(0xC8); //设置上下方向,0xC8正常 0xC0上下反置
OLED_WriteCommand(0xDA); //设置COM引脚硬件配置
OLED_WriteCommand(0x12);
OLED_WriteCommand(0x81); //设置对比度控制
OLED_WriteCommand(0xCF);
OLED_WriteCommand(0xD9); //设置预充电周期
OLED_WriteCommand(0xF1);
OLED_WriteCommand(0xDB); //设置VCOMH取消选择级别
OLED_WriteCommand(0x30);
OLED_WriteCommand(0xA4); //设置整个显示打开/关闭
OLED_WriteCommand(0xA6); //设置正常/倒转显示
OLED_WriteCommand(0x8D); //设置充电泵
OLED_WriteCommand(0x14);
OLED_WriteCommand(0xAF); //开启显示
OLED_Clear(); //OLED清屏
}
2.4.3 OLED_Font.h文件
cpp
#ifndef __OLED_FONT_H
#define __OLED_FONT_H
#include "stm32f10x.h" // Device header
/*OLED字模库,宽8像素,高16像素*/
const uint8_t OLED_F8x16[][16]=
{
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,// 0
0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x33,0x30,0x00,0x00,0x00,//! 1
0x00,0x10,0x0C,0x06,0x10,0x0C,0x06,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//" 2
0x40,0xC0,0x78,0x40,0xC0,0x78,0x40,0x00,
0x04,0x3F,0x04,0x04,0x3F,0x04,0x04,0x00,//# 3
0x00,0x70,0x88,0xFC,0x08,0x30,0x00,0x00,
0x00,0x18,0x20,0xFF,0x21,0x1E,0x00,0x00,//$ 4
0xF0,0x08,0xF0,0x00,0xE0,0x18,0x00,0x00,
0x00,0x21,0x1C,0x03,0x1E,0x21,0x1E,0x00,//% 5
0x00,0xF0,0x08,0x88,0x70,0x00,0x00,0x00,
0x1E,0x21,0x23,0x24,0x19,0x27,0x21,0x10,//& 6
0x10,0x16,0x0E,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//' 7
0x00,0x00,0x00,0xE0,0x18,0x04,0x02,0x00,
0x00,0x00,0x00,0x07,0x18,0x20,0x40,0x00,//( 8
0x00,0x02,0x04,0x18,0xE0,0x00,0x00,0x00,
0x00,0x40,0x20,0x18,0x07,0x00,0x00,0x00,//) 9
0x40,0x40,0x80,0xF0,0x80,0x40,0x40,0x00,
0x02,0x02,0x01,0x0F,0x01,0x02,0x02,0x00,//* 10
0x00,0x00,0x00,0xF0,0x00,0x00,0x00,0x00,
0x01,0x01,0x01,0x1F,0x01,0x01,0x01,0x00,//+ 11
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x80,0xB0,0x70,0x00,0x00,0x00,0x00,0x00,//, 12
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,//- 13
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x30,0x30,0x00,0x00,0x00,0x00,0x00,//. 14
0x00,0x00,0x00,0x00,0x80,0x60,0x18,0x04,
0x00,0x60,0x18,0x06,0x01,0x00,0x00,0x00,/// 15
0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,
0x00,0x0F,0x10,0x20,0x20,0x10,0x0F,0x00,//0 16
0x00,0x10,0x10,0xF8,0x00,0x00,0x00,0x00,
0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//1 17
0x00,0x70,0x08,0x08,0x08,0x88,0x70,0x00,
0x00,0x30,0x28,0x24,0x22,0x21,0x30,0x00,//2 18
0x00,0x30,0x08,0x88,0x88,0x48,0x30,0x00,
0x00,0x18,0x20,0x20,0x20,0x11,0x0E,0x00,//3 19
0x00,0x00,0xC0,0x20,0x10,0xF8,0x00,0x00,
0x00,0x07,0x04,0x24,0x24,0x3F,0x24,0x00,//4 20
0x00,0xF8,0x08,0x88,0x88,0x08,0x08,0x00,
0x00,0x19,0x21,0x20,0x20,0x11,0x0E,0x00,//5 21
0x00,0xE0,0x10,0x88,0x88,0x18,0x00,0x00,
0x00,0x0F,0x11,0x20,0x20,0x11,0x0E,0x00,//6 22
0x00,0x38,0x08,0x08,0xC8,0x38,0x08,0x00,
0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x00,//7 23
0x00,0x70,0x88,0x08,0x08,0x88,0x70,0x00,
0x00,0x1C,0x22,0x21,0x21,0x22,0x1C,0x00,//8 24
0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,
0x00,0x00,0x31,0x22,0x22,0x11,0x0F,0x00,//9 25
0x00,0x00,0x00,0xC0,0xC0,0x00,0x00,0x00,
0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00,//: 26
0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,
0x00,0x00,0x80,0x60,0x00,0x00,0x00,0x00,//; 27
0x00,0x00,0x80,0x40,0x20,0x10,0x08,0x00,
0x00,0x01,0x02,0x04,0x08,0x10,0x20,0x00,//< 28
0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,
0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x00,//= 29
0x00,0x08,0x10,0x20,0x40,0x80,0x00,0x00,
0x00,0x20,0x10,0x08,0x04,0x02,0x01,0x00,//> 30
0x00,0x70,0x48,0x08,0x08,0x08,0xF0,0x00,
0x00,0x00,0x00,0x30,0x36,0x01,0x00,0x00,//? 31
0xC0,0x30,0xC8,0x28,0xE8,0x10,0xE0,0x00,
0x07,0x18,0x27,0x24,0x23,0x14,0x0B,0x00,//@ 32
0x00,0x00,0xC0,0x38,0xE0,0x00,0x00,0x00,
0x20,0x3C,0x23,0x02,0x02,0x27,0x38,0x20,//A 33
0x08,0xF8,0x88,0x88,0x88,0x70,0x00,0x00,
0x20,0x3F,0x20,0x20,0x20,0x11,0x0E,0x00,//B 34
0xC0,0x30,0x08,0x08,0x08,0x08,0x38,0x00,
0x07,0x18,0x20,0x20,0x20,0x10,0x08,0x00,//C 35
0x08,0xF8,0x08,0x08,0x08,0x10,0xE0,0x00,
0x20,0x3F,0x20,0x20,0x20,0x10,0x0F,0x00,//D 36
0x08,0xF8,0x88,0x88,0xE8,0x08,0x10,0x00,
0x20,0x3F,0x20,0x20,0x23,0x20,0x18,0x00,//E 37
0x08,0xF8,0x88,0x88,0xE8,0x08,0x10,0x00,
0x20,0x3F,0x20,0x00,0x03,0x00,0x00,0x00,//F 38
0xC0,0x30,0x08,0x08,0x08,0x38,0x00,0x00,
0x07,0x18,0x20,0x20,0x22,0x1E,0x02,0x00,//G 39
0x08,0xF8,0x08,0x00,0x00,0x08,0xF8,0x08,
0x20,0x3F,0x21,0x01,0x01,0x21,0x3F,0x20,//H 40
0x00,0x08,0x08,0xF8,0x08,0x08,0x00,0x00,
0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//I 41
0x00,0x00,0x08,0x08,0xF8,0x08,0x08,0x00,
0xC0,0x80,0x80,0x80,0x7F,0x00,0x00,0x00,//J 42
0x08,0xF8,0x88,0xC0,0x28,0x18,0x08,0x00,
0x20,0x3F,0x20,0x01,0x26,0x38,0x20,0x00,//K 43
0x08,0xF8,0x08,0x00,0x00,0x00,0x00,0x00,
0x20,0x3F,0x20,0x20,0x20,0x20,0x30,0x00,//L 44
0x08,0xF8,0xF8,0x00,0xF8,0xF8,0x08,0x00,
0x20,0x3F,0x00,0x3F,0x00,0x3F,0x20,0x00,//M 45
0x08,0xF8,0x30,0xC0,0x00,0x08,0xF8,0x08,
0x20,0x3F,0x20,0x00,0x07,0x18,0x3F,0x00,//N 46
0xE0,0x10,0x08,0x08,0x08,0x10,0xE0,0x00,
0x0F,0x10,0x20,0x20,0x20,0x10,0x0F,0x00,//O 47
0x08,0xF8,0x08,0x08,0x08,0x08,0xF0,0x00,
0x20,0x3F,0x21,0x01,0x01,0x01,0x00,0x00,//P 48
0xE0,0x10,0x08,0x08,0x08,0x10,0xE0,0x00,
0x0F,0x18,0x24,0x24,0x38,0x50,0x4F,0x00,//Q 49
0x08,0xF8,0x88,0x88,0x88,0x88,0x70,0x00,
0x20,0x3F,0x20,0x00,0x03,0x0C,0x30,0x20,//R 50
0x00,0x70,0x88,0x08,0x08,0x08,0x38,0x00,
0x00,0x38,0x20,0x21,0x21,0x22,0x1C,0x00,//S 51
0x18,0x08,0x08,0xF8,0x08,0x08,0x18,0x00,
0x00,0x00,0x20,0x3F,0x20,0x00,0x00,0x00,//T 52
0x08,0xF8,0x08,0x00,0x00,0x08,0xF8,0x08,
0x00,0x1F,0x20,0x20,0x20,0x20,0x1F,0x00,//U 53
0x08,0x78,0x88,0x00,0x00,0xC8,0x38,0x08,
0x00,0x00,0x07,0x38,0x0E,0x01,0x00,0x00,//V 54
0xF8,0x08,0x00,0xF8,0x00,0x08,0xF8,0x00,
0x03,0x3C,0x07,0x00,0x07,0x3C,0x03,0x00,//W 55
0x08,0x18,0x68,0x80,0x80,0x68,0x18,0x08,
0x20,0x30,0x2C,0x03,0x03,0x2C,0x30,0x20,//X 56
0x08,0x38,0xC8,0x00,0xC8,0x38,0x08,0x00,
0x00,0x00,0x20,0x3F,0x20,0x00,0x00,0x00,//Y 57
0x10,0x08,0x08,0x08,0xC8,0x38,0x08,0x00,
0x20,0x38,0x26,0x21,0x20,0x20,0x18,0x00,//Z 58
0x00,0x00,0x00,0xFE,0x02,0x02,0x02,0x00,
0x00,0x00,0x00,0x7F,0x40,0x40,0x40,0x00,//[ 59
0x00,0x0C,0x30,0xC0,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x01,0x06,0x38,0xC0,0x00,//\ 60
0x00,0x02,0x02,0x02,0xFE,0x00,0x00,0x00,
0x00,0x40,0x40,0x40,0x7F,0x00,0x00,0x00,//] 61
0x00,0x00,0x04,0x02,0x02,0x02,0x04,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//^ 62
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,//_ 63
0x00,0x02,0x02,0x04,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//` 64
0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,
0x00,0x19,0x24,0x22,0x22,0x22,0x3F,0x20,//a 65
0x08,0xF8,0x00,0x80,0x80,0x00,0x00,0x00,
0x00,0x3F,0x11,0x20,0x20,0x11,0x0E,0x00,//b 66
0x00,0x00,0x00,0x80,0x80,0x80,0x00,0x00,
0x00,0x0E,0x11,0x20,0x20,0x20,0x11,0x00,//c 67
0x00,0x00,0x00,0x80,0x80,0x88,0xF8,0x00,
0x00,0x0E,0x11,0x20,0x20,0x10,0x3F,0x20,//d 68
0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,
0x00,0x1F,0x22,0x22,0x22,0x22,0x13,0x00,//e 69
0x00,0x80,0x80,0xF0,0x88,0x88,0x88,0x18,
0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//f 70
0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x00,
0x00,0x6B,0x94,0x94,0x94,0x93,0x60,0x00,//g 71
0x08,0xF8,0x00,0x80,0x80,0x80,0x00,0x00,
0x20,0x3F,0x21,0x00,0x00,0x20,0x3F,0x20,//h 72
0x00,0x80,0x98,0x98,0x00,0x00,0x00,0x00,
0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//i 73
0x00,0x00,0x00,0x80,0x98,0x98,0x00,0x00,
0x00,0xC0,0x80,0x80,0x80,0x7F,0x00,0x00,//j 74
0x08,0xF8,0x00,0x00,0x80,0x80,0x80,0x00,
0x20,0x3F,0x24,0x02,0x2D,0x30,0x20,0x00,//k 75
0x00,0x08,0x08,0xF8,0x00,0x00,0x00,0x00,
0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//l 76
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x00,
0x20,0x3F,0x20,0x00,0x3F,0x20,0x00,0x3F,//m 77
0x80,0x80,0x00,0x80,0x80,0x80,0x00,0x00,
0x20,0x3F,0x21,0x00,0x00,0x20,0x3F,0x20,//n 78
0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,
0x00,0x1F,0x20,0x20,0x20,0x20,0x1F,0x00,//o 79
0x80,0x80,0x00,0x80,0x80,0x00,0x00,0x00,
0x80,0xFF,0xA1,0x20,0x20,0x11,0x0E,0x00,//p 80
0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x00,
0x00,0x0E,0x11,0x20,0x20,0xA0,0xFF,0x80,//q 81
0x80,0x80,0x80,0x00,0x80,0x80,0x80,0x00,
0x20,0x20,0x3F,0x21,0x20,0x00,0x01,0x00,//r 82
0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x00,
0x00,0x33,0x24,0x24,0x24,0x24,0x19,0x00,//s 83
0x00,0x80,0x80,0xE0,0x80,0x80,0x00,0x00,
0x00,0x00,0x00,0x1F,0x20,0x20,0x00,0x00,//t 84
0x80,0x80,0x00,0x00,0x00,0x80,0x80,0x00,
0x00,0x1F,0x20,0x20,0x20,0x10,0x3F,0x20,//u 85
0x80,0x80,0x80,0x00,0x00,0x80,0x80,0x80,
0x00,0x01,0x0E,0x30,0x08,0x06,0x01,0x00,//v 86
0x80,0x80,0x00,0x80,0x00,0x80,0x80,0x80,
0x0F,0x30,0x0C,0x03,0x0C,0x30,0x0F,0x00,//w 87
0x00,0x80,0x80,0x00,0x80,0x80,0x80,0x00,
0x00,0x20,0x31,0x2E,0x0E,0x31,0x20,0x00,//x 88
0x80,0x80,0x80,0x00,0x00,0x80,0x80,0x80,
0x80,0x81,0x8E,0x70,0x18,0x06,0x01,0x00,//y 89
0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x00,
0x00,0x21,0x30,0x2C,0x22,0x21,0x30,0x00,//z 90
0x00,0x00,0x00,0x00,0x80,0x7C,0x02,0x02,
0x00,0x00,0x00,0x00,0x00,0x3F,0x40,0x40,//{ 91
0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,//| 92
0x00,0x02,0x02,0x7C,0x80,0x00,0x00,0x00,
0x00,0x40,0x40,0x3F,0x00,0x00,0x00,0x00,//} 93
0x00,0x06,0x01,0x01,0x02,0x02,0x04,0x04,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//~ 94
};
#endif