拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

SSD1306 OLED 驱动学习笔记(一):概述、原理与初始化

SSD1306 OLED 驱动学习笔记(一):概述、原理与初始化 SSD1306 OLED 驱动学习笔记一概述、原理与初始化这篇笔记是我跟完江协科技 OLED 教程之后整理的学习记录同时对照了 SSD1306 的官方数据手册。视频地址https://www.bilibili.com/video/BV1EN41177Pc/我当时调OLED好久没亮芯片也没有任何报错。后来把自己的初始化序列和手册逐条对比才发现电荷泵那条命令我写成了0xBD正确的应该是0x8D。这篇笔记就是那次之后把 SSD1306 从硬件到初始化重新理了一遍的结果。一、概述General Description1.1 芯片基本信息0.96 英寸 OLED 显示屏驱动芯片是 SSD1306。128 个段SEG输出和 64 个公共端COM输出对应 128×64 像素供电要求VDD 1.65~3.3VIC 逻辑供电VCC 7~15V面板驱动供电不过芯片内部有升压电路所以实际只需要接一个 3.3V 电源。这里要注意的是面板本身需要 7~15V 才能点亮我们只给了 3.3V中间靠的就是内部电荷泵升压。如果电荷泵没使能芯片逻辑是正常的命令也照收但面板没电屏幕就是全黑的。我那次黑屏就是这个原因。1.2 通信接口接口类型说明8 位并行接口6800 / 8080 系列SPI 接口3 线 / 4 线I2C 接口我使用的方案用软件 I2C 模拟1.3 芯片的主要任务接收数据来自 MCU显示存储存入 GDDRAM扫描刷新把 GDDRAM 的内容输出到屏幕二、原理讲解2.1 数据流的五个环节接收到一个字节后芯片会先做分流我们可以指定这个字节是命令还是数据环节作用1分流判断收到的是命令还是数据2命令走这里控制内部电路执行比如开启显示3数据走这里进入图形显示存储器 GDDRAM4扫描 GDDRAM把数据刷新到屏幕上5控制器输出SEG 的 0~127 对应 128 列COM 的 0~63 对应 64 行2.2 引脚说明类型图例I 输入O 输出I/O 双向P 电源引脚NC 不连接。引脚名类型说明VDDP核心逻辑电源引脚VCCP面板驱动电源也是最高正电压电源引脚VSSP地引脚VLSSP模拟地引脚外部应与 VSS 相连VCOMHOCOM 信号非选中电平引脚。需要在此脚与 VSS 之间接一个电容VBATP保留引脚应连接至 VDDBGGNDP保留引脚应接地C1P/C1N、C2P/C2NI保留引脚保持 NCVBREFP保留引脚保持 NCBS0/BS1/BS2IMCU 总线接口选择引脚详见下方接口选择IREFI段输出电流基准引脚。需要在此脚与 VSS 间接一个电阻使 IREF 电流维持在 12.5 µAFRO输出 RAM 写同步信号用于协调 MCU 写数据与帧显示时序防止撕裂效应。不用时保持 NCCLI外部时钟输入。内部时钟使能时CLS 为高此脚不用接 VSS内部时钟禁用时CLS 为低此脚作为外部时钟源输入CLSI内部时钟使能。拉高接 VDD启用内部时钟拉低禁用内部时钟此时必须由 CL 脚提供外部时钟RES#I复位信号输入。拉低执行芯片初始化正常工作时保持高电平接 VDDCS#I片选输入低有效D/C#I数据/命令控制引脚。拉高接 VDD写数据拉低写命令。I2C 模式下此脚作为 SA0用于从机地址选择。3 线 SPI 模式下此脚必须接 VSSE (RD#)I6800 系列作为 Enable(E) 信号拉高且片选时启动读/写。8080 系列接收 Read(RD#) 信号拉低且片选时启动读操作。串口模式下必须接 VSSR/W# (WR#)I读/写控制输入。6800 系列作为 R/W# 选择高为读、低为写。8080 模式作为 WR#拉低且片选时启动写操作。串口模式下必须接 VSSD0~D7I/O8 位双向数据总线接微处理器数据总线。串口模式下D0 SCLK串行时钟D1 SDIN串行数据D2 保持 NC2.3 接口选择说明不同接口模式下各引脚的接法对应手册 Table 8-1总线接口数据引脚接法控制引脚接法3 线 SPID7~D3 接低D2 NCD1 SDIND0 SCLKE 接低R/W# 接低CS# 接片选D/C# 接低RES# 接复位4 线 SPI同上E 接低R/W# 接低CS# 接片选D/C# 接数据/命令RES# 接复位I2CD7~D3 接低D2 SDA_OUTD1 SDA_IND0 SCLE 接低R/W# 接低CS# 接低D/C# 接 SA0RES# 接复位三、I2C 通信协议说明3.1 一次 I2C 传输的组成S起始条件起始条件之后的第一个字节必须是 7 位从机地址加 1 位读写位的格式。SSD1306 的从机地址格式是0 1 1 1 1 0 SA0 R/W# └──── 7 位从机地址 ────┘ └ 读写位 ┘SA0 由 D/C# 引脚电平配置用来改变从机地址的最低位。R/W# 是读写选择因为串行模式只能写入所以我们给 0。写模式下的完整字节是0111 1000也就是 0x78。如果 SA0 接高电平则变成0111 1010也就是 0x7A。ACK应答从机收到一个字节后拉低 SDA 表示应答。Co连续模式置 1每个 Data byte 前都要加 1 个 Control byte置 01 个 Control byte 后可以跟多个 Data byteControl byte 里的 D/C# 位指定后面是数据还是命令0x00后面是命令0x40后面是数据P终止时序主机发送停止条件结束本次传输。四、显存结构GDDRAM4.1 为什么要分页X 轴是 0~127一共 128 列Y 轴是 Page0~Page7一共 8 页每页 8 行像素之所以要分页是因为 1 个字节占 8 位。如果 8 位只表示一个像素点那就太浪费了。所以这里把 8 位竖着展开、从上到下排列低位在上高位在下。也就是说每次写入 1 个字节会控制纵向的 8 个像素点因此以 8 位为一组进行分页。写完一个字节会自动右移一列。总显存 8 页 × 128 字节 1024 字节。4.2 页地址和列地址怎么设置可以通过写命令根据相应的命令表来决定页地址和列地址。列地址X需要拆成两条命令发送。D/C# 写 0 表示写命令命令位模式说明第一行0000 xxxxD7~D4 为命令码 0000D3~D0 是列地址的低 4 位第二行0001 xxxxD7~D4 为命令码 0001D3~D0 是列地址的高 4 位第三行1011 0xxxD7~D3 为命令码 10110D2~D0 指定页地址 Page0~Page7三行组合起来就能覆盖 128 列 × 8 页的完整显存。对应到代码// 低 4 位0000 xxxxOLED_WriteCommand(0x00|(x0x0F));// 高 4 位0001 xxxxOLED_WriteCommand(0x10|((x0xF0)4));// 页地址1011 0xxxOLED_WriteCommand(0xB0|(y0x07));五、初始化过程内部提供 VCC5.1 写命令代码voidOLED_WriteCommand(uint8_tCommand){MyI2C_Start();MyI2C_SendByte(0x78);// 从机地址0111100 R/W#0也就是 0x78MyI2C_ReceiveAck();MyI2C_SendByte(0x00);// Control byte0x00 表示后面是命令MyI2C_ReceiveAck();MyI2C_SendByte(Command);// 命令本身MyI2C_ReceiveAck();MyI2C_Stop();}5.2 写数据代码voidOLED_WriteData(uint8_tData){MyI2C_Start();MyI2C_SendByte(0x78);// 从机地址MyI2C_ReceiveAck();MyI2C_SendByte(0x40);// Control byte0x40 表示后面是数据MyI2C_ReceiveAck();MyI2C_SendByte(Data);// 数据本身MyI2C_ReceiveAck();MyI2C_Stop();}0x78 的来历7 位从机地址0111100SA0 默认接低电平为 0加上 1 位读写位 0写入得到0111 1000也就是 0x78。5.3 完整初始化代码/* * OLED_Init() —— SSD1306 初始化软件 I2C 版 * 每条命令的作用都对照 SSD1306 数据手册Solomon Systech Rev 1.0标注 * 供电结构 * VDD 1.65~3.3V逻辑 * VCC 7~15V面板驱动靠内部电荷泵升压 * */voidOLED_Init(void){MyI2C_Init();// 初始化软件 I2C 的 GPIOSCL/SDA 引脚Delay_ms(100);// 上电延时等电源稳定手册要求 VDD 稳定后再发命令/* 1. 先关显示避免初始化过程中出现花屏 */OLED_WriteCommand(0xAE);// AEh Set Display OFF关闭显示RESET 默认值/* 2. 设置显示时钟分频比 / 振荡器频率 */OLED_WriteCommand(0xD5);// D5h Set Display Clock Divide Ratio / Oscillator FrequencyOLED_WriteCommand(0x80);// 高4位是振荡频率8默认低4位是分频比0分频1/* 3. 设置复用比MUX Ratio */OLED_WriteCommand(0xA8);// A8h Set Multiplex RatioMUX 比率 N1OLED_WriteCommand(0x3F);// 0x3F 63即 64 MUX对应 128×64 屏幕的 64 行/* 4. 设置显示偏移垂直平移 */OLED_WriteCommand(0xD3);// D3h Set Display OffsetCOM 垂直平移 0~63OLED_WriteCommand(0x00);// 偏移 0128×64 模块一般填 0/* 5. 设置显示起始行 */OLED_WriteCommand(0x40);// 40h~7Fh Set Display Start Line0x40 表示从第 0 行开始/* 6. 段重映射左右镜像 */OLED_WriteCommand(0xA1);// A1h 列地址 127 映射到 SEG0即左右镜像// 填 A0h 则不镜像。屏幕上图左右反了就改这条/* 7. COM 输出扫描方向上下翻转 */OLED_WriteCommand(0xC8);// C8h COM63 到 COM0 反向扫描// 填 C0h 则正向扫描。屏幕上下颠倒时改这条/* 8. COM 引脚硬件配置 */OLED_WriteCommand(0xDA);// DAh Set COM Pins Hardware ConfigurationOLED_WriteCommand(0x12);// 0x12 交替 COM 配置 左右反置// 128×64 模块常用值顺序配置是 0x02/* 9. 设置对比度亮度 */OLED_WriteCommand(0x81);// 81h Set Contrast Control双字节命令OLED_WriteCommand(0xCF);// 0x00~0xFF值越大越亮0xCF 约 81%// 屏幕太暗或太亮优先改这个值/* 10. 设置预充电周期 */OLED_WriteCommand(0xD9);// D9h Set Pre-charge PeriodOLED_WriteCommand(0xF1);// 高4位是阶段1周期数F15低4位是阶段2周期数1// 手册规定 0 是无效值/* 11. 设置 VCOMH 取消选择电平 */OLED_WriteCommand(0xDB);// DBh Set VCOMH Deselect LevelOLED_WriteCommand(0x30);// 00h 是 0.65×VCC20h 是 0.77×VCC复位值30h 是 0.83×VCC// 0x30 是最亮的一档/* 12. 整个显示 ON/OFF */OLED_WriteCommand(0xA4);// A4h 输出跟随 GDDRAM 内容正常显示// A5h 则是强制全屏点亮、忽略 RAM 内容一般只用于测试/* 13. 设置正常/反显 */OLED_WriteCommand(0xA6);// A6h 正常显示RAM 中 1 对应像素亮// A7h 则是反显1 对应像素灭/* 14. 设置电荷泵我黑屏就出在这条 */OLED_WriteCommand(0x8D);// 8Dh Set Charge Pump双字节命令// 作用是把 3.3V 升压到面板需要的 7~15V// 之前写成 0xBD芯片当作非法命令丢弃了// 结果电荷泵从未开启面板没电屏幕全黑OLED_WriteCommand(0x14);// 0x14 使能内部电荷泵0x10 关闭// 用内部 DC/DC 供电的模块这条是必需的/* 15. 开启显示 */OLED_WriteCommand(0xAF);// AFh Set Display ON真正点亮屏幕放在最后OLED_Clear();// 清屏防止上电随机噪点Delay_ms(100);// 等显示稳定}5.4 设置光标位置列地址 页地址voidOLED_SetCursor(uint8_tx,uint8_ty){// 列地址低 4 位命令 0000xxxxOLED_WriteCommand(0x00|(x0x0F));// 列地址高 4 位命令 0001xxxxOLED_WriteCommand(0x10|((x0xF0)4));// 页地址命令 10110xxxOLED_WriteCommand(0xB0|(y0x07));}位运算拆解以 x 0x5A0101 1010为例步骤运算结果作用1x 0x0F0000 1010 0x0A用 0x0F0000 1111保留低 4 位把高 4 位清零2x 0xF00101 0000 0x50用 0xF01111 0000保留高 4 位把低 4 位清零3(x 0xF0) 40000 0101 0x05把高 4 位移到低位方便拼命令40x10 | 0x050001 0101 0x15用或运算套上命令前缀 0001关于这两个位运算我记的口诀是与运算和 1 运算的结果照抄原数和 0 运算的结果永远是 0。也就是全 1 才得 1有一个 0 结果就是 0。或运算和 1 运算的结果永远是 1和 0 运算的结果照抄原数。也就是有一个 1 结果就是 1。参考资料江协科技 OLED 教程https://www.bilibili.com/video/BV1EN41177Pc/SSD1306 数据手册Solomon SystechRev 1.02007-09命令表Table 9-1第 28~32 页命令详细说明含电荷泵第 10 章第 34 页起引脚说明Table 7-1第 13~14 页官方初始化示例第 4.4 节0.96 寸 OLED 模块规格书Allvision QG-2864KLBEG01
返回列表