OLED简介
- OLED(分辨率为64×128):有机发光二极管,多类型多接口方式。
- 该模块提供了总共5种接口包括:6800、8080两种并行接口方式、3线或4线的穿行SPI接口方式,IIC接口方式。
- 模块有单色和双色两种可选,单色为纯蓝色,双色则为黄蓝双色。
- LCD需要背光,而OLED不需要,它是自发光的。
- 单片机 --> SSD1306(驱动芯片) --> OLED
- 引脚说明:
LOED配置
写命令
void Write_IIC_Command(unsigned char IIC_Command)
{
IIC_Start(); // 数据线 时钟线 配置
//主机通过IIC发送从机地址,也可写成IICWrite(0x3C<<1);
IICWrite(0x78);
IICWrite(0x00); // 写命令
IICWrite(IIC_Command);
IIC_Stop();
}
写数据
void Write_IIC_Data(unsigned char IIC_Data)
{
IIC_Start();
IICWrite(0x3C<<1);
IICWrite(0x40); // 写数据
IICWrite(IIC_Data);
IIC_Stop();
}
0x00/0x40参数解释:
- 主机先发起开始(START)信号,然后发送1byte首字节,包括从机地址(7位)和读写数据位(1位,最低位,0为写模式),从机地址确认后发出应答信号(ACK=0) 。
- 主机收到从机的应答信号后,随后传输1byte控制字节,一个控制字节主要由CO和 D/C# 位后面再加上六个0组成,Co位为0(一般写0)表示后面传输的信息就只包含数据字节。
- D/C#位决定了下个数据字节是作为命令还是数据:D/C#为0时,下一个数据被视为命令;D/C#为1时,下一个数据被视为数据。
OLED初始化
双行表示双字节命令,第一行为开启配置,第二行为配置参数,具体命令查看SSD1306手册。
void OLED_Init(void)
{
delay_ms(800);//初始化前延时,重要!
Write_IIC_Command(0xAE);//关闭显示
Write_IIC_Command(0xB0);//设置y坐标,页地址
Write_IIC_Command(0x00);//设置x坐标,低列地址
Write_IIC_Command(0x10);//设置x坐标,高列地址
//--设置显示开始行 [5:0],行数。设置起始行地址,集映射RAM显示起始行(0x00~0x3F)
Write_IIC_Command(0x40);
Write_IIC_Command(0xC8);//设置COM(行)扫描方向
Write_IIC_Command(0xA1);//设置列(seg)扫描方向,从左到右:seg128->seg0
Write_IIC_Command(0x81); // 对比度设置
Write_IIC_Command(0xFF);//--128
Write_IIC_Command(0xA6);设置显示方式;bit0:1,反相显示;0,正常显示
Write_IIC_Command(0xA8);//--设置驱动路数
Write_IIC_Command(0x3F);//--1/32 duty默认0X3F(1/64)
Write_IIC_Command(0xD3);//设置显示偏移位移映射RAM计数器(0x00~0x3F)
Write_IIC_Command(0x00);//默认为0
Write_IIC_Command(0x20);//设置内存寻址模式为页寻址
Write_IIC_Command(0x02);
Write_IIC_Command(0xD5);//设置时钟分频因子,震荡频率
Write_IIC_Command(0x80);//[3:0],分频因子;[7:4],震荡频率
Write_IIC_Command(0xD9);//设置预充电周期
Write_IIC_Command(0xF1);//[3:0],PHASE 1;[7:4],PHASE 2;
Write_IIC_Command(0xDA);//设置COM硬件引脚配置
Write_IIC_Command(0x12);//[5:4]配置
Write_IIC_Command(0xDB);//设置VCOMH 电压倍率
Write_IIC_Command(0x30);//[6:4] 000,0.65*vcc;001,0.77*vcc;011,0.83*vcc;
Write_IIC_Command(0x8D);//电荷泵设置
Write_IIC_Command(0x14);//bit2开启或者关闭
Write_IIC_Command(0xAF);//开显示
}
初始化参数解释:
取模
分辨率为64×128(行×列个小灯),分为8页(PAGE0~PAGE7),每页内 1个SEG对应1Byte数据,一页由 128 Byte 组成。一般来说,一个汉字占1616,一个字符占168。
取模软件设置,取模顺序是从低到高,即第一个点作为最低位,一行16字节,如:
{0x00,0x00,0xC0,0x38,0xE0,0x00,0x00,0x00,0x20,0x3C,0x23,0x02,0x02,0x27,0x38,0x20}表示为 “A”。
页寻址
GDDRAM(Graphic Display Data RAM),是SSD1306内置的一个单元,用于存储将显示在128*64点阵屏上的图像。
三种寻址模式:页寻址、水平寻址、垂直寻址。
- 页寻址模式是器件默认的GDDRAM寻址模式,“20H,02H”命令可以设置寻址模式为页寻址。
- 列地址指针每次自动加1,如果列地址指针到达最后一个地址,将会自动复位到开始的地址,页地址指针不变;
- 为了访问下一个页面内容,用户必须设置新的页面和列地址;
- 页地址的范围0-7,对应的命令是B0-B7;
- 低列地址的设置命令是00-0FH,高列地址的设置命令是10h-1Fh。
//坐标设置
void OLED_Set_Pos(unsigned char x, unsigned char y)
{ // 绿框左上角 (x,y) = (18,0)
Write_IIC_Command(0xb0+y); // y坐标
// x在每页的首行 !!!
Write_IIC_Command(((x&0xf0)>>4)|0x10);// x坐标高四位
Write_IIC_Command((x&0x0f)); // x坐标低四位
}
扫描方向设置
清屏/点亮
// 清屏
void OLED_Clear(void)
{
u8 i,n;
for(i=0;i<8;i++) // page0到page7
{
Write_IIC_Command(0xb0+i); // y=0->page0
Write_IIC_Command(0x00); // x=0->0x00 0x10
Write_IIC_Command(0x10);
for(n=0;n<128;n++) // seg0-seg128依次写0/0x00
Write_IIC_Data(0);
}
}
// 屏幕全部点亮
void OLED_On(void)
{
u8 i,n;
for(i=0;i<8;i++)
{
Write_IIC_Command(0xb0+i);
Write_IIC_Command(0x00);
Write_IIC_Command(0x10);
for(n=0;n<128;n++)
Write_IIC_Data(1); // 0x01
}
}
显示一个字符
- 确定区域大小:16*8
- 确定XY坐标
- 显示相应字符:要显示哪个字符,只需确定在数组的第几行。
// 参数: X坐标,Y坐标,要显示的字符,大小
void OLED_ShowChar(u8 x, u8 y, u8 chr, u8 Char_Size)
{
unsigned char c=0,i=0;
//另外一种写法 c=chr - ' ' ,确定在F8X16的行号,32是0(空格)的ASCII码10进制数
c=chr - 32;
if(x>128-1) // if(x>120) 取值 x: 0-127 y:0-7 超出行显示范围则换页显示 16*8
{
x=0;y=y+2;
}
if(Char_Size ==16)
{
OLED_Set_Pos(x,y);
for(i=0;i<8;i++)
Write_IIC_Data(F8X16[c*16+i]);//上8*8部分 一页 一行的前64位
OLED_Set_Pos(x,y+1);
for(i=0;i<8;i++)
Write_IIC_Data(F8X16[c*16+i+8]);//下8*8部分 一页 一行的后64位
}
else
{
OLED_Set_Pos(x,y);
for(i=0;i<6;i++)
Write_IIC_Data(F6x8[c][i]);
}
}
显示字符串
void OLED_ShowString(u8 x,u8 y,u8 *chr,u8 Char_Size)
{
while(*chr != '\0')
{
OLED_ShowChar(x,y,*chr++,Char_Size); // *char++自增取字符
x +=8; // 一个char字符占8个坐标/字节
if(x>120) // 超行范围就换页显示 16*8
{
x = 0;
y+=2;
}
}
}
显示一个汉字
取模软件输入汉字输出对应进制 ,补充到字库FX16X16[ ]中,0 表示第0行
// 16*16
// 参数: 坐标x 坐标y 行号 大小
void OLED_ShowCHinese(u8 x,u8 y,u8 no,u8 Size)
{
unsigned char i=0;
if(Size ==16)
{
OLED_Set_Pos(x,y);
for(i=0;i<16;i++)
Write_IIC_Data(F16X16[no*32+i]);//上页 8*16部分 前16个16进制数
OLED_Set_Pos(x,y+1);
for(i=0;i<16;i++)
Write_IIC_Data(F16X16[no*32+i+16]);//下半部分
}
}
显示一组数字
取出数组的每个数字8×16,然后将每个数字 + ‘0’ 转为字符后再显示在屏幕上
// Size = 16 num = 28
void OLED_ShowNum(u8 x,u8 y,int num,u8 Size)
{
u8 i=0;
u8 t=0;
u8 len=0;
u8 buf[3];
while(num>0)
{
buf[i++] = num%10;
num /= 10;
}
len = i; // 数字长度
for(t=0;t<i;t++)
{
// --len 先减再用, x+8*t 一个字符占8位
OLED_ShowChar(x+(Size/2)*t,y,buf[--len]+'0',Size);
}
}