OLED屏幕学习
1、OLED写命令
1.1、写数据
1.2、编程实现
2、OLED图像显示
2.1、GDDRAM是位映射静态RAM,保存要显示的位模式。RAM大小为128 x 64位,RAM分为8个页面,从PAGE0到PAGE7,用于单色128x64点阵显示。
以一列0列(SEG0)为例,Page2由8位组成,组成如下图
2.2、寻址模式
页地址模式
水平模式
垂直地址模式
寻址命令地址表(配置寻址模式)
选择Page
配置页寻址模式:1、发送cmd:0x20 2、再发送0x02
配置好后,默认到Page0的0列,若再0列写入数据后,默认去1列。
2.3、初始化OLED
void OLED_INIT()
{
OLED_Write_Cmd(0xAE);//--display off
OLED_Write_Cmd(0x00);//---set low column address
OLED_Write_Cmd(0x10);//---set high column address
OLED_Write_Cmd(0x40);//--set start line address
OLED_Write_Cmd(0xB0);//--set page address
OLED_Write_Cmd(0x81); // contract control
OLED_Write_Cmd(0xFF);//--128
OLED_Write_Cmd(0xA1);//set segment remap
OLED_Write_Cmd(0xA6);//--normal / reverse
OLED_Write_Cmd(0xA8);//--set multiplex ratio(1 to 64)
OLED_Write_Cmd(0x3F);//--1/32 duty
OLED_Write_Cmd(0xC8);//Com scan direction
OLED_Write_Cmd(0xD3);//-set display offset
OLED_Write_Cmd(0x00);//
OLED_Write_Cmd(0xD5);//set osc division
OLED_Write_Cmd(0x80);//
OLED_Write_Cmd(0xD8);//set area color mode off
OLED_Write_Cmd(0x05);//
OLED_Write_Cmd(0xD9);//Set Pre-Charge Period
OLED_Write_Cmd(0xF1);//
OLED_Write_Cmd(0xDA);//set com pin configuartion
OLED_Write_Cmd(0x12);//
OLED_Write_Cmd(0xDB);//set Vcomh
OLED_Write_Cmd(0x30);//
OLED_Write_Cmd(0x8D);//set charge pump enable
OLED_Write_Cmd(0x14);//
OLED_Write_Cmd(0xAF);//--turn on oled panel
}
2.4、在OLED屏幕上显示一条线
2.4.1、选择列地址显示
出现问题:1、雪花屏幕 2、Page0的终止列是Page5起始列
2.4.1.1、解决列问题:
2.4.1.2、解决雪花屏:
A、增加清屏函数
B、屏幕VCC连接3V
2.5、在屏屏幕上显示爱你一万年
1、用字模软件生成对应字符的矩阵
2、一次给屏幕发送数据
2.5.1、代码实现
#include "reg52.h"
#include "intrins.h"
sbit SCL = P0^1;
sbit SDA = P0^3;
void IIC_Start()
{
SCL = 0;
SDA = 1;
SCL = 1; //SCL一直为高电平
_nop_(); //SDA为高电平,持续时间>4.7us
SDA = 0; //SDA跳变成低电平,表示起始信号
_nop_(); //低电平持续时间>4us
}
void IIC_Stop()
{
SCL = 0;
SDA = 0;
SCL = 1;
_nop_(); //SDA为低电平,持续时间>4us
SDA = 1; //跳变到高电平,终止信号
_nop_(); //高电平持续时间>4.7us
}
char IIC_ACK() //判断是否有效应答
{
char flag;
SDA = 1; //在脉冲9释放数据线
_nop_(); //等待一段时间
SCL = 1; //在SCL高电平期间去读取SDA的状态
_nop_();
flag = SDA; //在SCL为高电平期间,读取SDA信号
_nop_();
SCL = 0;
_nop_();
return flag; //返回读取的SDA状态
}
void IIC_Send_Byte(char dataSend) //发送一个字节时序
{
char i;
for(i = 0 ; i<8 ; i++){ //每循环一次发送1位数据
SCL = 0; //拉低SCL,让SDA做好发数据准备
SDA = dataSend & 0x80; //建立发送数据,&操作取出发送的最高位
_nop_(); //发送数据建立时间
SCL = 1; //SCL为高电平,开始发送数据
_nop_(); //发送数据时间
SCL = 0; //发送完毕
_nop_();
dataSend <<= 1; // 左移将第二个数据放到最高位,以便下一次发送
}
}
void OLED_Write_Cmd(char dataCmd)
{
//1.Start 开始信号
IIC_Start();
//2. Slave Address从机地址(011110(SA0)(R/W#) SA0控制接入多个显示屏的选择 R/W#设置0为写入模式)
IIC_Send_Byte(0x78); //0111 1000 0x78
//3. 是否有效应答
IIC_ACK();
//4. Control byte ((C0)(D/C)000000) C0设置0表示传输的内容为Data byte D/0为0写入指令 为1写入数据
IIC_Send_Byte(0x00); // 0000 0000 0x00
//5. ACK
IIC_ACK();
//6. 写入指令/数据
IIC_Send_Byte(dataCmd); //写入数据
//7. ACK
IIC_ACK();
//8.STOP
IIC_Stop();
}
void OLED_Write_Data(char dataData)
{
//1.Start(IIC_Start) 开始信号
IIC_Start();
//2. Slave Address从机地址(011110(SA0)(R/W#) SA0控制接入多个显示屏的选择 R/W#设置0为写入模式)
IIC_Send_Byte(0x78); //0111 1000 0x78
//3. 是否有效应答
IIC_ACK();
//4. Control byte ((C0)(D/C)000000) C0设置0表示传输的内容为Data byte D/0为0写入指令 为1写入数据
IIC_Send_Byte(0x40); // 0100 0000 0x40
//5. ACK
IIC_ACK();
//6. 写入指令/数据
IIC_Send_Byte(dataData); //写入数据
//7. ACK
IIC_ACK();
//8.STOP
IIC_Stop();
}
void OLED_INIT()
{
OLED_Write_Cmd(0xAE);//--display off
OLED_Write_Cmd(0x00);//---set low column address
OLED_Write_Cmd(0x10);//---set high column address
OLED_Write_Cmd(0x40);//--set start line address
OLED_Write_Cmd(0xB0);//--set page address
OLED_Write_Cmd(0x81); // contract control
OLED_Write_Cmd(0xFF);//--128
OLED_Write_Cmd(0xA1);//set segment remap
OLED_Write_Cmd(0xA6);//--normal / reverse
OLED_Write_Cmd(0xA8);//--set multiplex ratio(1 to 64)
OLED_Write_Cmd(0x3F);//--1/32 duty
OLED_Write_Cmd(0xC8);//Com scan direction
OLED_Write_Cmd(0xD3);//-set display offset
OLED_Write_Cmd(0x00);//
OLED_Write_Cmd(0xD5);//set osc division
OLED_Write_Cmd(0x80);//
OLED_Write_Cmd(0xD8);//set area color mode off
OLED_Write_Cmd(0x05);//
OLED_Write_Cmd(0xD9);//Set Pre-Charge Period
OLED_Write_Cmd(0xF1);//
OLED_Write_Cmd(0xDA);//set com pin configuartion
OLED_Write_Cmd(0x12);//
OLED_Write_Cmd(0xDB);//set Vcomh
OLED_Write_Cmd(0x30);//
OLED_Write_Cmd(0x8D);//set charge pump enable
OLED_Write_Cmd(0x14);//
OLED_Write_Cmd(0xAF);//--turn on oled panel
}
void OLED_Clear() //给屏幕写入0
{
unsigned char i,j;
for(i = 0 ; i<8 ; i++){ //Page0~Page
// 选择Page
OLED_Write_Cmd( 0xB0 + i);
// 每选择一次Page,重新让光标指向0列
OLED_Write_Cmd(0x00);
OLED_Write_Cmd(0x10);
for(j = 0 ; j<128 ; j++){ //显示屏大小128x64
OLED_Write_Data(0); //0列到127列依次写入0,每写入数据,列地址自动偏移
}
}
}
/*-- 文字: 爱 --*/
/*-- 宋体18; 此字体下对应的点阵为:宽x高=24x24 --*/ //3Page 列 = (16*4+8)/3=24列
code char Love[3][24] = {0x00,0x00,0x00,0x88,0x88,0x18,0x78,0xF8,0xE8,0x48,0x1C,0x7C,0xFC,0xEC,0x0C,0x84,\
0xE4,0x7E,0x3E,0x16,0x86,0x84,0x00,0x00,\
0x00,0x0C,0x0E,0x1F,0x37,0x11,0x11,0x11,0xF1,0xFF,0xFF,0x5D,0x51,0x51,0x51,0x51,\
0xD1,0xF1,0xD9,0x1F,0x17,0x03,0x01,0x00,\
0x00,0x40,0x60,0x30,0x70,0x58,0x4E,0x67,0x63,0x21,0x33,0x37,0x1E,0x1C,0x1E,0x3F,\
0x33,0x31,0x70,0x70,0x60,0x60,0x20,0x00};
/*-- 文字: 你 --*/
/*-- 宋体18; 此字体下对应的点阵为:宽x高=24x24 --*/
code char You[3][24] = {0x00,0x00,0x00,0x00,0xC0,0xF0,0xFE,0x3E,0x0E,0x04,0xC0,0xF8,0x7E,0x5E,0x44,0x40,\
0x40,0x40,0x40,0xC0,0xE0,0xE0,0xC0,0x00,\
0x20,0x38,0x1C,0x0F,0xFF,0xFF,0xFF,0x09,0x0C,0xC7,0xFB,0xF9,0x38,0x10,0xFF,0xFF,\
0xFF,0x10,0x32,0xF3,0xE1,0xC0,0x00,0x00,\
0x00,0x00,0x00,0x00,0x7F,0x7F,0x7F,0x0C,0x0E,0x07,0x03,0x30,0x30,0x70,0x7F,0x7F,\
0x3F,0x00,0x00,0x00,0x03,0x0F,0x0F,0x00};
/*-- 文字: 一 --*/
/*-- 宋体18; 此字体下对应的点阵为:宽x高=24x24 --*/
code char One[3][24] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\
0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,\
0x08,0x08,0x08,0x0C,0x0C,0x0C,0x08,0x00,\
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
/*-- 文字: 万 --*/
/*-- 宋体18; 此字体下对应的点阵为:宽x高=24x24 --*/
code char Wan[3][24] = {0x00,0x10,0x30,0x10,0x10,0x10,0x10,0x10,0x90,0xF0,0xF0,0xF0,0x10,0x10,0x10,0x10,\
0x10,0x10,0x10,0x18,0x18,0x18,0x10,0x00,\
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xFF,0xFF,0x3F,0x03,0x02,0x02,0x02,0x02,\
0x02,0xFE,0xFF,0xFF,0x02,0x00,0x00,0x00,\
0x00,0x40,0x60,0x70,0x38,0x1C,0x0F,0x07,0x03,0x00,0x00,0x00,0x18,0x18,0x30,0x70,\
0x78,0x3F,0x3F,0x0F,0x00,0x00,0x00,0x00};
/*-- 文字: 年 --*/
/*-- 宋体18; 此字体下对应的点阵为:宽x高=24x24 --*/
code char Age[3][24] = {0x00,0x00,0x00,0xC0,0xF0,0x7C,0x3E,0x1E,0x16,0x10,0x10,0xF0,0xF0,0xF0,0x10,0x10,\
0x10,0x10,0x10,0x18,0x18,0x10,0x00,0x00,\
0x00,0x82,0x83,0x81,0xFC,0xFE,0xFC,0x84,0x84,0x84,0x84,0xFF,0xFF,0xFF,0x84,0x84,\
0x84,0x86,0x86,0x86,0xC4,0xC0,0x80,0x00,\
0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x7F,0x7F,0x00,0x00,\
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
void Print()
{
char i,j;
char ilen = sizeof(Love)/sizeof(Love[0]);
char jlen = sizeof(Love[0])/sizeof(Love[0][0]);
for(i = 0 ; i<ilen; i++){
OLED_Write_Cmd(0xB0 + i); //选择Page0 1011 0000 0XB0
// 每选择一次Page,重新让光标指向0列
OLED_Write_Cmd(0x00);
OLED_Write_Cmd(0x10);
for(j = 0 ; j<jlen ; j++){
OLED_Write_Data(Love[i][j]);
}
for(j = 0 ; j<jlen ; j++){
OLED_Write_Data(You[i][j]);
}
for(j = 0 ; j<jlen ; j++){
OLED_Write_Data(One[i][j]);
}
for(j = 0 ; j<jlen ; j++){
OLED_Write_Data(Wan[i][j]);
}
for(j = 0 ; j<jlen ; j++){
OLED_Write_Data(Age[i][j]);
}
}
}
void main()
{
// 1.初始化显示屏
OLED_INIT();
// 2.选择寻址模式
OLED_Write_Cmd(0x20);
OLED_Write_Cmd(0x02); //页寻址模式 光标默认在Page0的0列
// 2.1清屏
OLED_Clear();
/*
// 3.选择Page
OLED_Write_Cmd(0xB0 + 0); //选择Page0 1011 0000 0XB0
// 每选择一次Page,重新让光标指向0列
OLED_Write_Cmd(0x00);
OLED_Write_Cmd(0x10);
*/
Print();
while(1);
}