工具
1.Proteus 8 仿真器
2.keil 5 编辑器
原理图
讲解
简介
OLED(Organic Light-Emitting Diode)显示屏,即有机发光二极管显示屏,是一种新型显示技术。它的工作原理是通过电流驱动有机材料发光,无需背光灯,采用非常薄的有机材料涂层和玻璃基板(或柔性有机基板)。
OLED显示屏具有诸多优点。首先,由于无需背光灯,其结构更轻更薄,可视角度更大。其次,OLED显示屏能够显著节省耗电量,提高能效。此外,它的色彩丰富、分辨率高,响应速度快,图像稳定。同时,OLED自身能够发光,因此其视域范围也要宽很多。
OLED显示屏的应用范围广泛。在博物馆和展览中,OLED透明屏可用于展示文物、艺术品、历史信息等,提供沉浸式的观展体验。在建筑和室内设计领域,OLED透明屏可以应用于建筑物的玻璃幕墙、楼梯扶手和室内装饰等,增强建筑的现代感和创意性。此外,OLED显示屏还广泛应用于汽车内部、户外广告牌、舞台和演艺表演等领域。
OLED本身是没有显存的,它的显存是依赖于SSD1306显存芯片提供的
从使用的角度上,我们驱动该OLED屏幕显示,实际是与驱动芯片SSD1306通信,让SSD1306控制OLED点阵显示。SSD1306相当于一个中介,我们只需要了解SSD1306的功能、寄存器、总线、驱动流程等参数或工作方式,根据SSD1306的工作方式通信即可。
SSD1306
特性
- 分辨率:128 x 64 点阵
- 电源:对于集成逻辑电路,VDD=1.65V---3.3V;对于面板驱动,VCC=7V---15V
- 点阵驱动:OLED驱动输出电压,最大15V;SEG最大源电流:100uA;COM最大汇电流:15mA;256阶对比度亮度电流控制
- 内置128 x 64位SRAM显示缓冲区
- 引脚可选择的MCU接口:8位6800/8080串并接口、 3/4线串行外围接口、I2C接口
- 水平和垂直方向的屏幕保持连续滚动功能
- RAM写同步信号
- 可编程帧速率和复用率
- 行重映射和列重映射
- 片内内置振荡器
- COG和COF的芯片封装
- 工作温度范围广:-40°C至85°C
注意:OLED显示器模块供电电压为:3.3V---5V
内部结构
引脚
MCU接口引脚 | 说明 |
BS0~BS2 | MCU总线接口选择脚。通过配置BS0~BS2来选择不同的MCU总线接口。 |
D0~D7 | 连接到MCU的8位双向数据总线,不同MCU总线接口有不同用法 |
D/C# | 数据/命令控制脚,不同MCU总线接口有不同用法 |
R/W#(WR#) | 与6800/8080通用并行总线接口相关,使用串行接口时作拉高处理 |
E (RD#) | 与6800/8080通用并行总线接口相关,使用串行接口时作拉高处理 |
RES# | 复位信号引脚,低电平有效。 |
CS# | 芯片片选引脚,低电平有效 |
驱动器输出引脚 | 说明 |
SEG0~SEG127 | 列输出脚,OLED关闭时,处于VSS状态 |
COM0~COM63 | 行输出脚,OLED关闭时,处于高阻抗状态 |
电源引脚 | 说明 |
VDD | 芯片逻辑器件供电引脚 1.65V---3.3V |
VCC | 显示面板驱动电源引脚 7V---15V |
VSS | 接地引脚 |
VLSS | 模拟接地引脚,在外部连接到VSS |
VCOMH | 用于COM的高电平电压输出的引脚,与VSS之间应该连接一个电容 |
其他引脚 | 说明 |
IREF | 段输出电流参考脚,VSS间应连接一个电阻,以将IREF电流保持在12.5uA |
CL | 外部时钟输入引脚。用外部时钟时,此引脚输入外部时钟信号。用内部时钟时应连接到VSS |
CLS | 内部时钟启用引脚。拉高时内部时钟启用,拉低时内部时钟禁用 |
FR | 用于输出RAM写同步信号,不使用当做NC |
TR0~TR6 | 测试保留引脚,当做NC |
NC | 空引脚 不接地 不组合 |
接口
引脚 | 8-bit 8080 | 8-bit 6800 | 3-wire SPI | 4-wire SPI | I2C |
BS0 | 0 | 0 | 1 | 0 | 0 |
BS1 | 1 | 0 | 0 | 0 | 1 |
BS2 | 1 | 1 | 0 | 0 | 0 |
接口协议\引脚名称 | Data\Command接口 | 控制信号 | |||||||||||
D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 | E | R\W# | CS# | D\C# | RES# | |
8-bit 8080 | D[7:0] | RD# | WR# | CS# | D\C# | RES# | |||||||
8-bit 6800 | D[7:0] | E | R\W# | CS# | D\C# | RES# | |||||||
3-wire SPI | Tie Low | NC | SDIN | SCLK | Tie Low | CS# | Tie Low | RES# | |||||
4-wire SPI | Tie Low | NC | SDIN | SCLK | Tie Low | CS# | D\C# | RES# | |||||
I2C | Tie Low | SDA out | SDA in | SCL | Tie Low | SA0 | RES# |
注意:Tie Low (低电平或0状态), NC (无需连接 不接地 不组合)
I2C接口协议
IIC设备在数据传输之前都必须识别从机地址。SSD1306的从机地址有 0111100X 和 0111101X 两种,通过将SA0(D/C#)脚上拉到高电平可以设置从机地址第七位为 1,将SA0(D/C#)脚下拉到低电平可以设置从机地址第七位为 0。通过SA0(D/C#)脚的上拉和下拉来设置从机地址,从而令总线上可以存在最多2个SSD1306驱动器。
B7 | B6 | B5 | B4 | B3 | B2 | B1 | B0 |
0 | 1 | 1 | 1 | 1 | 0 | SA0 | R\W |
注意:SDAOUT和SDAIN连接到一起作为SDA。SDAIN引脚必须连接到SDA,SDAOUT引脚可以不连接。当SDAOUT引脚不连接,应答信号将会被12C总线忽略。
SSD1306 通过 R/W# 和 D/C# 两位来确定:读/写数据,写命令和读状态四种通信行为
一个控制字节主要由CO 和 D/C# 位后面再加上六个0组成的。
如果将Co位设置为逻辑“0”,则传输以下信息将包含仅限数据字节。
D/C# 位决定了下个数据字节是作为命令还是数据。D/C# 为0时,下一个数据被视为命令;DC# 为1时,下一个数据被视为显示数据,存储到GDDRAM中。
R/W# | Co | D/C# | 说明 |
0 | 0 | 0 | 写命令 |
1 | 0 | 0 | 读状态 |
0 | 0 | 1 | 写数据 |
1 | 0 | 1 | 读数据 |
时序
GDDRAM内部结构
显示RAM:GDDRAM(Graphic Display Data RAM )内部结构如下所示:
GDDRAM是位映射静态RAM,大小为 128x64 位。GDDRAM分为8页(PAGE0~PAGE7),每页内 1个SEG对应1Byte数据,一页由 128 Byte 组成。一帧显示数据为 1024 Byte(1KB)。
1个数据字节写入GDDRAM时,数据位D0写入顶行,数据位D7写入底行。(由上到下,由低到高)
寻址模式
页寻址
页寻址模式是器件默认选择的GDDRAM寻址模式,通过“20H,02H”命令可以设置寻址模式为页寻址。
页寻址模式下,寻址只在一页(PAGEn)内进行,地址指针不会跳到其他页。每次向GDDRAM写入1byte显示数据后,列指针会自动+1。当128列都寻址完之后,列指针会重新指向SEG0而页指针仍然保持不变。通过页寻址模式我们可以方便地对一个小区域内数据进行修改。
水平寻址
水平寻址模式可以通过指令“20H,00H”来设置。
水平寻址模式下,每次向GDDRAM写入1byte数据后,列地址指针自动+1。列指针到达结束列之后会被重置到起始列,而页指针将会+1。页地址指针达到结束页之后,将会自动重置到起始页。水平寻址模式适用于大面积数据写入,例如一帧画面刷新
垂直寻址
垂直寻址模式可以通过指令“20H,01H”来设置。
垂直寻址模式下,每次向GDDRAM写入1byte数据之后,页地址指针将会自动+1。页指针到达结束页之后会被重置到0,而列指针将会+1。列地址指针达到结束页之后,将会自动重置到起始列。
指令
基础指令
1.设置对比度 (81H+A[7:0])
这是一条双字节指令,由第二条指令指定要设置的对比度级数。
A[7:0] 从 00H~FFH 分别指定对比度为 1~256 级。SEG(段)输出的电流大小随对比度级数的增加而增加。
2.设置全屏全亮 (A4H / A5H)
这是一条单字节指令,用于开关屏幕全亮模式。
A4H 设置显示模式为正常模式,此时屏幕输出GDDRAM中的显示数据。
A5H 设置显示模式为全亮模式,此时屏幕无视GDDRAM中的数据,并点亮全屏。
通过A5H设置全屏点亮之后可以通过A4H来回复正常显示。
3.设置正常/反转显示 (A6H / A7H)
这是一条单字节指令,用于设置屏幕显示
A6H 设置显示模式为 1亮0灭,而 A7H 设置显示模式为 0亮1灭
4.开关显示屏 (AEH / AFH)
这是一条单字节指令。
AEH 关闭屏幕,而 AFH 开启屏幕。
屏幕关闭时,所有SEG和COM的输出被分别置为Vss和高阻态。
地址指令
1.设置GDDRAM寻址模式 (20H+A[1:0])
这是一条双字节指令,由 A[1:0] 指定要设置的地址模式。
A[1:0]=00b时为水平地址模式;A[1:0]=01b时为垂直地址模式;A[1:0]=10b时为页地址模式;A[1:0]=11b时为无效指令;
由于第二条指令前6位值无规定,所以直接用0替代,得到:00H-水平;01H-垂直;02H页
2.设置起始/终止列地址 (21H+A[6:0]+B[6:0])
这是一条三字节指令,由A[6:0]指定起始列地址,B[6:0]指定终止列地址。
同样,由于前1位值无规定,所以:A[6:0] 和 B[6:0] 从 00H~7FH 的取值指定起始/终止列地址为 0~127。
这条指仅在水平/垂直模式下有效,用来设置水平/垂直模式的初始列和结束列
3.设置起始/终止页地址 (22H+A[2:0]+B[2:0])
这是一条三字节指令,由A[2:0]指定起始也地址,B[2:0]指定终止页地址。
由于前5位值无规定,所以:A[2:0]和B[2:0]从 00H~07H 的取值指定起始/终止页地址为 0~7。
这条指仅在水平/垂直模式下有效,用来设置水平/垂直模式的初始页和结束页
4.设置起始列地址低位 (00H~0FH)
这是一条单字节指令。
高4位恒定为0H,低4位为要设置的起始列地址的低4位。这条指令仅用于页寻址模式。
5.设置起始列地址高位 (10H~1FH)
这是一条单字节指令
高4位恒定为1H,低4位为要设置的起始列地址的高4位。这条指令仅用于页寻址模式。
6.设置页地址 (B0H~B7H)
这是一条单字节指令
高4位恒定为BH,第5位规定为0,低3位用于设置页地址,从 B0H~B7H 分别设置起始页为 0~7。这条指令仅用于页寻址模式。
硬件指令
1.设置GDDRAM起始行 (40H~7FH)
这是一条单字节指令。
高2位规定为01b,由低6位的取值来决定起始行。整体指令从 40H~7FH 分别设置起始行为 0~63。
2.设置SEG映射关系 (A0H / A1H)
这是一条单字节指令。
A0H 设置GDDRAM的COL0映射到驱动器输出SEG0。
A1H 设置COL127映射到SEG0
3.设置COM扫描方向 (C0H / C8H)
这是一条单字节指令。
C0H 设置 从COM0扫描到COM[N-1],N为复用率
C1H 设置 从COM[N-1]扫描到COM0
4.设置复用率 (A8H+A[5:0])
这是一条双字节指令,由A[5:0]指定要设置的复用率
复用率(MUX ratio)即选通的COM行数,不能低于16,通过A[5:0]来指定。
A[5:0] 高两位无规定视为0,所以第二条指令从 0FH~3FH 的取值设置复用率为 1~64(即A[5:0]+1)。A[5:0]从0到14的取值都是无效的。
5.设置垂直显示偏移 (D3H+A[5:0])
这是一条双字节指令,由A[5:0]指定偏移量。
垂直显示偏移即整个屏幕向上移动的行数,最顶部的行会移到最底行。
A[5:0] 高两位无规定视为0,所以第二条指令从0FH~3FH的取值设置垂直偏移为 0~636.设置COM硬件配置 (DAH+A[5:4])
这是一条双字节指令,由A[5:4]进行设置。
A[5] 位设置COM左右反置,A[4] 用来设置序列/备选引脚配置,其他位有规定,规定如下所示。
SSD1306的COMn引脚一共有左边 COM32~COM63 和右边 COM0~COM31 共64个(金手指面朝上方)。通过设置A[5]可以让左右COM引脚的输出互换。A[5]=0时禁止左右反置,A[5]=1时启用左右反置。
COM引脚的排列有序列和奇偶间隔(备选)两种,通过A[4]进行设置。A[4]=0时使用序列COM引脚配置,A[5]=1时使用奇偶间隔(备选)COM引脚配置。
时序和指令
1.设置显示时钟分频数和fosc (D5H+A[7:0])
2.设置预充电周期 (D9H+A[7:0])
3.设置VCOMH输出的高电平 (DBH+A[6:4])
4.空操作 (E3H)
滚动指令
取模
图片取模
软件:Image2lcd v4.0
1.打开选择图片
2.输出类型设置(c语言,数据水平字节垂直扫描模式,单色,最大宽度和高度)
3.字节内像素数据反序(低位在上,高位在下)
4.确认扫描模式与字节数据顺序,确认输出图像(宽48=48列,高48=6行/页)
5.保存(获取取模数据)
文字取模
软件:PCtoLCD2002完美版
1.设置输出格式
2.确认字符大小
3.输入文字---生成字模
4.复制数据或保存到文件
注意:字模是一个字一个字去取模的 应用到oled需要对字模数据进行整理
代码
#include <REGX51.H>
#include <intrins.H>
#include "DELAY.h"
#include "oledce.h"
sbit SDA = P2^1; //数据
sbit SCL = P2^0; //时钟
unsigned int i=0;
#define delay();{_nop_();_nop_();_nop_();_nop_();_nop_();} //五个机器周期 5微妙 一周期多长时间与晶振有关
// 开始 SCL高电平状态下 SDA 由高电平变低电平
void start()
{
SDA=1;
SCL=1;
delay();
SDA=0;
delay();
SCL=0;
}
// 结束 SCL高电平状态下 SDA 由低电平变高电平
void end()
{
SDA=0;
SCL=1;
delay(); //5us
SDA=1;
delay_ms(10); //10ms
}
// 发送
void send_data(unsigned char byte)
{
unsigned char i;
for(i=0;i<8;i++) //字节拆分按位传递
{ //SCL为高电平 读取SDA稳定数据 所以SDA变化在前
SDA=byte&(0x80>>i); //从最高位依次传递给SDA
delay();
SCL=1;
delay();
SCL=0;
}
}
// 接收
unsigned char read()
{
unsigned char i,byte=0x00;
SDA=1;
for(i=0;i<8;i++) //字节按位接收
{
SCL=1;
delay();
if(SDA){byte|=(0x80>>i);}
delay();
SCL=0;
}
return byte;
}
//发送应答
void send_sck(bit ACK ) {
// 根据ACK的值设置数据线SDA
SDA = ACK; // 注意:通常ACK是低电平,NACK是高电平
delay(); // 保持SDA状态,等待从机读取
SCL = 1; // 将时钟线SCL拉高
delay(); // 等待时钟线稳定
SCL = 0; // 将时钟线SCL拉低,结束应答
delay(); // 等待时钟线稳定
SDA = 1; //释放数据线 线权交给从机
}
//接收应答
bit read_sck()
{
bit ACK;
SDA=1;
delay(); //5us
SCL=1;
delay(); //5us
ACK=SDA;
delay(); //5us
SCL=0;
return ACK;
}
//oled初始化
void oled_Init()
{
start();
send_data(0x78); //器件地址
read_sck();
send_data(0x00); //写命令
read_sck();
send_data(0xAE); //进入睡眠状态
read_sck();
send_data(0XA4); //输出GDDRAM内容
read_sck();
send_data(0XA6); //正常显示(1亮0灭)
read_sck();
send_data(0X81); //设置对比度
read_sck();
send_data(0X7F); //第127级对比度
read_sck();
send_data(0XD3); //设置垂直显示偏移(向上)
read_sck();
send_data(0X00); //偏移0行
read_sck();
send_data(0X40); //设置GDDRAM起始行 0
read_sck();
send_data(0XA8); //设置MUX数 (显示行数)
read_sck();
send_data(0X3F); // MUX=63 (显示63行)
read_sck();
send_data(0XA1); // 左右反置关(段重映射)
read_sck();
send_data(0XC8); // 上下反置关(行重映射)
read_sck();
send_data(0XDA); // 设置COM引脚配置
read_sck();
send_data(0X02); // 序列COM配置,禁用左右反置
read_sck();
send_data(0X20); // 设置GDDRAM模式
read_sck();
send_data(0X00); // 水平寻址模式
read_sck();
send_data(0XAF); //开OLED显示
read_sck();
end();
}
//显示图片设置
void oled_ImagePage()
{
start();
send_data(0x78); //器件地址
read_sck();
send_data(0x00); //写命令
read_sck();
send_data(0X21); // 设置列起始和结束地址
read_sck();
send_data(0X00); // 列起始地址
read_sck();
send_data(0X2F); // 列终止地址
read_sck();
send_data(0X22); // 设置页起始和结束地址
read_sck();
send_data(0X03); // 页起始地址 0
read_sck();
send_data(0X07); // 页终止地址 7
read_sck();
end();
}
//写入图片数据
void oled_WriteImage()
{
unsigned int j=0;
oled_ImagePage(); //显示图片设置
start(); // 通信开始
send_data(0X78); // 写从机地址'0111 100' 读写符号'0'
read_sck();
send_data(0X40); // 写数据 Co='0' C/D='100 0000'
read_sck();
for(j;j<288;j++)
{
send_data(gImage_oledce[j]); // 写入数据
read_sck();
}
end();
}
//oled显示文字设置
void oled_TextPage()
{
start();
send_data(0x78); //器件地址
read_sck();
send_data(0x00); //写命令
read_sck();
send_data(0X21); // 设置列起始和结束地址
read_sck();
send_data(0X40); // 列起始地址 0
read_sck();
send_data(0X6f); // 列终止地址 127
read_sck();
send_data(0X22); // 设置页起始和结束地址
read_sck();
send_data(0X00); // 页起始地址 0
read_sck();
send_data(0X07); // 页终止地址 7
read_sck();
send_data(0X27); // 水平左滚动
read_sck();
send_data(0x00); // 空比特
read_sck();
send_data(0x00); // 滚动起始页地址
read_sck();
send_data(0x06); // 滚动速度
read_sck();
send_data(0x02); // 滚动结束页地址
read_sck();
send_data(0x00); // 空比特
read_sck();
send_data(0xff); // 空比特
read_sck();
send_data(0x2f); // 启动水平滚动
read_sck();
end();
}
void oled_WriteText()
{
unsigned int j=0;
oled_TextPage();//文字设置
start(); // 通信开始
send_data(0X78); // 写从机地址'0111 100' 读写符号'0'
read_sck();
send_data(0X40); // 写数据 Co='0' C/D='100 0000'
read_sck();
for(j;j<96;j++)
{
send_data(name_oledce[j]); // 写入数据
read_sck();
}
end();
}
void main()
{
oled_Init(); //初始化
oled_WriteImage(); //显示图片
oled_WriteText(); //显示文字
while(1)
{
}
}
实现
🚀本欧也处于学习阶段,所学所识将以笔记发布。
笔记会根据相关知识的接触而随时更新!
如果文章对你有帮助,请留下你宝贵的点赞吧👍
V:Werluo 本欧也很喜欢交朋友的哦!