news 2026/5/10 11:00:31

手把手教你用SH1107驱动1.3寸OLED屏:从点亮第一个像素到显示自定义图片

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
手把手教你用SH1107驱动1.3寸OLED屏:从点亮第一个像素到显示自定义图片

从零构建SH1107 OLED驱动:点亮像素到图像显示的实战指南

当一块1.3寸OLED屏幕首次连接到开发板时,许多嵌入式开发者会面临相似的困惑——如何让那些微小的像素点按照预期亮起?SH1107作为一款广泛应用的OLED驱动芯片,其寄存器配置和内存寻址模式往往成为初学者的第一道门槛。本文将采用"问题驱动"的教学方式,通过实际案例演示如何从单个像素控制逐步实现复杂图形显示,过程中会特别关注那些容易导致显示异常的技术细节。

1. 硬件基础与初始化配置

1.1 SH1107的物理内存布局

SH1107驱动芯片采用分页式内存架构,这对于刚接触OLED开发的工程师来说是个关键概念。我们以常见的64x128分辨率屏幕为例:

  • 页(Page):16个逻辑页(Page0-Page15)
  • 行(Row):每页包含8行,共128行(16页×8行)
  • 列(Column):64列(实际芯片支持128列,但屏幕物理限制为64)

内存寻址时需要特别注意列地址的拆分方式。以下是典型的初始化命令序列:

// 初始化命令序列示例 OLED_WR_Byte(0xAE, OLED_CMD); // 关闭显示 OLED_WR_Byte(0xD5, OLED_CMD); // 设置时钟分频 OLED_WR_Byte(0x80, OLED_CMD); // 建议值 OLED_WR_Byte(0xA8, OLED_CMD); // 设置多路复用率 OLED_WR_Byte(0x3F, OLED_CMD); // 对应128行 OLED_WR_Byte(0x20, OLED_CMD); // 设置内存模式

注意:0x20命令设置的是页地址模式(Page Addressing Mode),这种模式下写入数据后列地址自动递增,但页地址需要手动切换。

1.2 电气连接与通信验证

在开始编程前,确保硬件连接正确至关重要。SH1107通常支持I2C和SPI接口,以下是I2C连接的典型引脚配置:

引脚名称连接目标备注
VCC3.3V绝对不要超过3.3V
GND地线
SCLMCU的SCL引脚需接上拉电阻(4.7kΩ)
SDAMCU的SDA引脚需接上拉电阻(4.7kΩ)

验证通信是否正常的最简单方法是发送一个基本命令并检查ACK信号:

# Python示例:使用smbus库检测设备 import smbus bus = smbus.SMBus(1) # 树莓派使用I2C-1 try: bus.write_byte(0x3C, 0xAE) # 尝试关闭显示 print("SH1107响应正常") except IOError: print("通信失败,检查连接")

2. 像素级控制实战

2.1 点亮单个像素的原理

理解SH1107如何控制单个像素是掌握OLED编程的基础。每个像素对应内存中的一个bit,但写入时需要以列为单位,每列8个像素(D0-D7)。以下是点亮第2页第16列全部像素的代码:

OLED_WR_Byte(0xB1, OLED_CMD); // 选择Page2(0xB0 + 页号) OLED_WR_Byte(0x0F, OLED_CMD); // 列低地址(0x0F = 第16列) OLED_WR_Byte(0x10, OLED_CMD); // 列高地址 OLED_WR_Byte(0xFF, OLED_DATA); // 写入数据(全亮)

这个操作涉及三个关键点:

  1. 页地址命令的高4位固定为1011,低4位表示页号
  2. 列地址需要拆分为高4位和低4位分别发送
  3. 数据0xFF表示该列8个像素全部点亮

2.2 坐标定位函数封装

为了提高代码可重用性,我们可以封装一个设置坐标的函数:

void OLED_Set_Pos(uint8_t x, uint8_t y) { OLED_WR_Byte(0xB0 + y, OLED_CMD); OLED_WR_Byte(((x & 0xF0) >> 4) | 0x10, OLED_CMD); OLED_WR_Byte(x & 0x0F, OLED_CMD); }

这个函数处理了列地址的拆分逻辑:

  • (x & 0xF0) >> 4获取高4位
  • x & 0x0F获取低4位
  • | 0x10是因为列高地址命令的前导位是0001

3. 字符显示的实现

3.1 字模提取与存储

显示字符需要预先准备好字模数据。以8x16英文字符为例,使用PCtoLCD2002软件生成字模:

  1. 设置取模方式:逐列式、高位在前
  2. 字符大小:宽8像素,高16像素
  3. 生成的字模数据会按列排列,每字符16字节

存储字模通常使用常量数组:

const uint8_t F8X16[] = { // 字符'E'的字模示例 0x08,0xF8,0x88,0x88,0xE8,0x08,0x10,0x00, 0x20,0x3F,0x20,0x20,0x23,0x20,0x18,0x00, // 其他字符... };

3.2 字符显示函数实现

基于字模数据显示字符的函数需要考虑跨页处理:

void OLED_ShowChar(uint8_t x, uint8_t y, uint8_t chr, uint8_t size) { uint8_t i = 0; if(size == 16) { OLED_Set_Pos(x, y); for(i=0; i<8; i++) OLED_WR_Byte(F8X16[chr*16+i], OLED_DATA); OLED_Set_Pos(x, y+1); for(i=0; i<8; i++) OLED_WR_Byte(F8X16[chr*16+i+8], OLED_DATA); } else { // 8x6字体 OLED_Set_Pos(x, y); for(i=0; i<6; i++) OLED_WR_Byte(F6x8[chr][i], OLED_DATA); } }

提示:对于中文显示,通常需要16x16点阵,这意味着每个汉字需要跨两个页和32字节的字模数据。

4. 高级图形显示技术

4.1 位图显示原理

显示自定义图像需要将位图转换为适合OLED的二进制格式。这个过程称为"取模",关键参数包括:

  • 图像宽度:必须与OLED列数对齐(如64像素)
  • 图像高度:必须是8的倍数(因为每页8行)
  • 颜色深度:单色(1位深度)

使用图像处理软件生成的数据格式如下:

const uint8_t logo_bmp[] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0, // 更多数据... };

4.2 位图显示函数优化

高效的位图显示函数需要考虑内存访问模式:

void OLED_DrawBMP(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, const uint8_t BMP[]) { uint16_t j = 0; uint8_t x, y; for(y = y0; y < y1; y++) { OLED_Set_Pos(x0, y); for(x = x0; x < x1; x++) { OLED_WR_Byte(BMP[j++], OLED_DATA); } } }

实际使用示例:

// 显示从(0,0)到(64,16)的图像 OLED_DrawBMP(0, 0, 64, 16, logo_bmp);

4.3 动态效果实现技巧

通过结合定时器和部分刷新技术,可以实现流畅的动画效果:

  1. 局部刷新:只更新发生变化的部分区域
  2. 双缓冲:在内存中准备完整帧后再一次性显示
  3. 滚动效果:利用SH1107内置的垂直滚动命令
// 设置垂直滚动区域 OLED_WR_Byte(0x29, OLED_CMD); // 连续垂直滚动 OLED_WR_Byte(0x00, OLED_CMD); // 虚拟页开始 OLED_WR_Byte(0x07, OLED_CMD); // 滚动时间间隔 OLED_WR_Byte(0x0F, OLED_CMD); // 虚拟页结束 OLED_WR_Byte(0x2F, OLED_CMD); // 启动滚动

5. 性能优化与调试

5.1 常见问题排查

当显示出现异常时,可以按照以下步骤排查:

  1. 全屏测试:先尝试点亮所有像素(写入0xFF)
  2. 单页测试:单独测试每一页的显示
  3. 通信验证:用逻辑分析仪检查I2C/SPI信号
  4. 电源检查:确保供电稳定无噪声

5.2 帧率优化技巧

提高刷新率的关键技术:

优化方法实施手段预期效果
部分区域刷新只更新变化区域减少数据传输量
命令流水线批量发送命令和数据减少通信开销
使用硬件SPI替代软件模拟I2C提高传输速度
内存缓冲在MCU端维护显示缓存实现双缓冲

5.3 低功耗设计考虑

OLED应用的功耗优化策略:

// 进入睡眠模式 OLED_WR_Byte(0xAE, OLED_CMD); // 关闭显示 // 唤醒时重新初始化 void OLED_WakeUp() { OLED_Init(); // 重新初始化 OLED_WR_Byte(0xAF, OLED_CMD); // 开启显示 }

实际项目中,可以根据内容更新频率动态调整刷新率,静态显示时降低到1-2Hz可显著节省功耗。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/10 10:58:36

5分钟彻底告别乱码!GBKtoUTF-8编码转换终极指南

5分钟彻底告别乱码&#xff01;GBKtoUTF-8编码转换终极指南 【免费下载链接】GBKtoUTF-8 To transcode text files from GBK to UTF-8 项目地址: https://gitcode.com/gh_mirrors/gb/GBKtoUTF-8 还在为Windows和Mac之间文件传输乱码而烦恼吗&#xff1f;GBKtoUTF-8编码转…

作者头像 李华
网站建设 2026/5/10 10:55:33

SIGGRAPH‘26 | 英伟达新作ArtiFixer:革新3D重建,自回归扩散让PSNR暴涨3 dB!

点击下方卡片&#xff0c;关注「3D视觉工坊」公众号选择星标&#xff0c;干货第一时间送达来源&#xff1a;3D视觉工坊「3D视觉从入门到精通」知识星球(点开有惊喜) &#xff01;星球内有20多门3D视觉系统课程、3DGS独家系列视频教程、顶会论文最新解读、海量3D视觉行业源码、项…

作者头像 李华
网站建设 2026/5/10 10:52:39

从一次代码重构说起:我是如何用C# virtual方法,让老项目支持新需求的

从一次代码重构说起&#xff1a;我是如何用C# virtual方法让老项目支持新需求的 去年接手一个电商平台的支付模块维护任务时&#xff0c;遇到个典型场景&#xff1a;系统原有支付宝和银行卡支付功能&#xff0c;现在要接入微信支付。核心挑战在于——原有支付处理类已经稳定运行…

作者头像 李华
网站建设 2026/5/10 10:48:43

U-Net与自编码器在医学图像分割与特征提取中的实战应用

1. 项目概述&#xff1a;从像素到洞察的桥梁在医学影像分析领域&#xff0c;我们每天面对的是海量的CT、MRI、病理切片图像。对于临床医生和研究员而言&#xff0c;仅仅“看到”图像是不够的&#xff0c;关键在于“理解”和“量化”。比如&#xff0c;一张肺部CT中&#xff0c;…

作者头像 李华