SSD1306
-
- OLED特性
- 手册说明
-
- GDDRAM寻址模式(0x20)
- I2C地址与时序
- 软件配置
-
- I2C的配置
- OLED初始化过程
- 显示中文
- 显示英文
- 显示图片
OLED特性
SSD1306是单芯片CMOS OLED/PLED带有有机/聚合物发光二极管点阵图形显示系统的控制器。它由128段和64个公共区域组成。集成电路为普通阴极OLED面板设计。
SSD1306内置对比度控制,显示RAM振荡器减少了外部元件的数量和功耗。它有256步亮度控制。数据/命令与硬件可选的6800/8000系列兼容并行接口,I2C从用接口或串行外围接口MCU发送。
它适用于手机子显示器等许多小型便携式应用,MP播放器、计算器等。
手册说明
GDDRAM存储显示数据,大小为128x64bits.RAM从PAGE0~PAGE7. 每页内1个SEG对于一个Byte一页有128个数据Byte组成。10241024Byte
从下图可以看出
涉及到一些配置寄存器,需要查看手册。手册中有几组寄存器
命令 | 含义 | 使用说明 |
---|---|---|
81 | 设置对比度 | 0x00~0xff 双字节命令,1-256对比等级,增加值,增加对比度 |
A4/A5 | 全显示开关 | A4 x0=0b 重新显示RAM内容;A5 X0=1b 全部显示开 |
A6/A7 | 设置正常/翻转显示 | A6,X[0]=0b,正常显示;A7,X[0]=1b:翻转显示 |
AE/AF | 设置显示开/关 | AE,X[0]=0b,关(睡眠模式);AF,X[0]=01b ON |
二、地址设置命令
命令 | 含义 | 使用说明 |
---|---|---|
00-0F | 页地址模式下,设置低列起始地址 | 起始行寄存器显示重置后设置0000b |
10-1F | 在页面地址模式下,设置高列起始地址 | 起始行寄存器显示重置后设置0000b |
20 | 设置寄存器地址模式 | A[1:0]=00b01水平地址模式b 垂直地址模式,10页地址模式,11页地址模式b无效 |
21 | 设置列地址 | 设置列开始结束地址,A[6:0],start ;B[6:0] end |
22 | 设置页地址 | A[2:0]:起始地址范围07d,B[2:0]页末地址范围07d(复位:7d) |
B0~B7 | 在页面地址模式下,设置页面起始地址 | (PAGE0~PAGE7) for Page Addressing Modeusing X[2:0] |
三、硬件配置命令
命令 | 含义 | 使用说明 |
---|---|---|
40~7F | 设置显示开始行 | |
A0/A1 | 设置SEG重映射 | A0h,X[0]=0b:列地址0,映射到SEG0(复位);A1h,x[0]=1b:127映射列地址SEG0 |
A8 | 多路复用设置 | |
C0/C8 | 设置COM输出扫描模式 | C0h,X[3]=0b:z=扫描正常模式 COM0COM[N-1];C8xX[3]=1b:重映射模式,扫描COM[N-1]COM[0] |
D3 | 设置显示偏移 | 设置垂直偏移 |
DA | 设置COM引脚硬件配置 |
四、滚动命令
命令 | 含义 | 使用说明 |
---|---|---|
26/27 | 垂直水平滚动 | 26h x[0]=0 ,水平向右滚动;27 x[0]=1 水平向左滚动 |
29/2A | 垂直滚动 | 29,向右 (上下);2A向左 (上下) |
打开命令码后,设置以下内容A,B,C,D,E参数如下: 滚动实例,在初始化时调用,26/27没有实验成功,29/2A可以实现滚动
void roll()
{
WriteCmd(0x2e);//OFF
WriteCmd(0x2A);//29,2a
WriteCmd(0x00);//A:Dummy byte
WriteCmd(0x00);//B:设置页起始地址
WriteCmd(0x02);//C:滚动速度 000b-5frames 100b-3frames
WriteCmd(0x01);//D:设置页结束地址
WriteCmd(0x00);//E:垂直滚动偏移
WriteCmd(0x2f);//START ROLL
}
GDDRAM寻址模式(0x20)
有三种模式设置,例如:
OLED_WriteC(0X20); // 设置模式
OLED_WriteC(0X00); // 设置值(水平寻址模式 )
页寻址、A[1:0]=10 水平寻址、A[1:0]=00 垂直寻址 A[1:0]=01
I2C地址与时序
这段话的意思是,SA0 提供可扩展的从机地址,通过SA0(D/C#)脚的上拉和下拉来设置从机地址,拉高则为1,即 0111101;拉低则为0,即0111100 最后一个是读写R/W
IIC写入时序如下所示:
-
主机先发起开始(START)信号(SDA从高到底,SCL从底到高),
-
然后发送1byte首字节,包括从机地址(7位)和读写数据位(1位,最低位,0为写模式),
-
驱动器识别从机地址为本机地址之后,将会发出 应答信号(ACK)
-
主机收到从机的应答信号之后,随后传输命令或者数据。一个控制字节主要由CO 和 D/C# 位后面再加上六个0组成的。
-
接受每一个控制字节或者数据字节都要产生ACK信号
-
传输完毕之后主机发出结束(STOP)信号,SDA 从低到高 SCL保持高
软件配置
- I2C配置,配置SCL、SDL的GPIO SCL <—>PB6 SDA <—>PB7
- 根据手册配置OLED
I2C的配置
#define OLED_I2C I2C1
#define OLED_I2C_CLK RCC_APB1Periph_I2C1
#define OLED_I2C_CLK_INIT RCC_APB1PeriphClockCmd
#define OLED_I2C_SCL_PIN GPIO_Pin_6
#define OLED_I2C_SCL_GPIO_PORT GPIOB
#define OLED_I2C_SCL_GPIO_CLK RCC_APB2Periph_GPIOB
#define OLED_I2C_SCL_SOURCE GPIO_PinSource6
#define OLED_I2C_SCL_AF GPIO_AF_I2C1
#define OLED_I2C_SDA_PIN GPIO_Pin_7
#define OLED_I2C_SDA_GPIO_PORT GPIOB
#define OLED_I2C_SDA_GPIO_CLK RCC_APB2Periph_GPIOB
#define OLED_I2C_SDA_SOURCE GPIO_PinSource7
#define OLED_I2C_SDA_AF GPIO_AF_I2C1
void I2C_Configuration(void)
{
I2C_InitTypeDef I2C_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
//外设I2C时钟使能
OLED_I2C_CLK_INIT(OLED_I2C_CLK,ENABLE);
//外设GPIO时钟使能
RCC_APB2PeriphClockCmd(OLED_I2C_SCL_GPIO_CLK | OLED_I2C_SDA_GPIO_CLK,ENABLE);
/* I2C_SCL、I2C_SDA*/
GPIO_InitStructure.GPIO_Pin = OLED_I2C_SCL_PIN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
GPIO_Init(OLED_I2C_SCL_GPIO_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = OLED_I2C_SDA_PIN;
GPIO_Init(OLED_I2C_SDA_GPIO_PORT, &GPIO_InitStructure);
/* I2C */
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
I2C_InitStructure.I2C_OwnAddress1 =OLED_ADDRESS; //I2C地址
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable ;
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; //寻址方式
I2C_InitStructure.I2C_ClockSpeed = I2C_Speed;//速度
I2C_Init(OLED_I2C, &I2C_InitStructure); //使能初始化
I2C_Cmd(OLED_I2C, ENABLE); //使能I2C
}
通过I2C写数据
//硬件I2C时序配置
void I2C_WriteByte(uint8_t addr,uint8_t data)
{
//Checks whether the specified I2C flag is set or not.
while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY));
I2C_GenerateSTART(I2C1, ENABLE);//产生I2C起始信号
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));/*EV5,,主模式*/
I2C_Send7bitAddress(I2C1, OLED_ADDRESS, I2C_Direction_Transmitter);//器件I2C地址0x78
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
I2C_SendData(I2C1, addr);//寄存器地址
while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
I2C_SendData(I2C1, data);//数据
while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
I2C_GenerateSTOP(I2C1, ENABLE);//关闭I2C
}
//写命令
void WriteCmd(unsigned char I2C_Command)
{
I2C_WriteByte(0x00, I2C_Command);
}
//写数据
void WriteDat(unsigned char I2C_Data)
{
I2C_WriteByte(0x40, I2C_Data);
}
OLED初始化过程
- 关闭显示(AEH)
- 128x64 显示模式
- 恢复到默认的SEG和COM映射关系(A0H,D3H-00H)
- 清除串行接口中移位寄存器内的数据
- 显示开始行设为0
- 列地址计数器重置为0
- COM输出的默认扫描方向(C0H)
- 对比度寄存器初始化为7FH
- 正常显示模式(A4H)
//手册中提供的初始化函数
void OLED_Init(void)
{
Delay_s(1); // 1s,
WriteCmd(0xAE); //屏幕关
WriteCmd(0x20); //设置寻址模式
WriteCmd(0x10); //00,Horizontal Addressing Mode;
01,Vertical Addressing Mode;
10,Page Addressing Mode (RESET);
11,Invalid
WriteCmd(0xb0); //Set Page Start Address for Page Addressing Mode,0-7
WriteCmd(0xc8); //COM扫描反向
WriteCmd(0x00); //起始列地址低位
WriteCmd(0x10); //起始列地址高位
WriteCmd(0x40); //--set start line address
WriteCmd(0x81); //设置对比度
WriteCmd(0xff); //亮度调节 范围0x00~0xff
WriteCmd(0xa1); //set segment re-map 0 to 127
WriteCmd(0xa6); //正常显示
WriteCmd(0xa8); //设置MUX数(1 to 64)
WriteCmd(0x3F); //MUX=63 显示63行
WriteCmd(0xa4); //0xa4,输出 RAM 内容;0xa5,忽略 RAM 内容
WriteCmd(0xd3); // 设置显示偏移
WriteCmd(0x00); //没有偏移
WriteCmd(0xd5); //设置显示时钟分频数、振荡器频率
WriteCmd(0xf0); //--set divide ratio
WriteCmd(0xd9); //设置预充电周期
WriteCmd(0x22); //
WriteCmd(0xda); //COM引脚配置
WriteCmd(0x12);//启用左右反置
WriteCmd(0xdb); //设置 vcomh 输出
WriteCmd(0x20); //0x20,0.77xVcc
WriteCmd(0x8d); //--set DC-DC enable
WriteCmd(0x14); //
WriteCmd(0xaf); //--turn on oled panel
}
//OLED_ON 从休眠中唤醒
void OLED_ON(void)
{
WriteCmd(0X8D); //
WriteCmd(0X14); //
WriteCmd(0XAF); //
}
// OLED_OFF 休眠
void OLED_OFF(void)
{
WriteCmd(0X8D); //
WriteCmd(0X10); //
WriteCmd(0XAE); //
}
//设置读写坐标
void OLED_SetPos(unsigned char x, unsigned char y) //设置起始坐标
{
WriteCmd(0xb0+y);//y取值 0 -7 (B0h~B7h)
WriteCmd(((x&0xf0)>>4)|0x10);//取高位
WriteCmd((x&0x0f)|0x01);//取低位
}
void OLED_Fill(unsigned char fill_Data)
{
unsigned char m,n;
for(m=0;m<8;m++)
{
//Set Page Start Address for Page Addressing Mode (B0h~B7h)
WriteCmd(0xb0+m); //page0-page1
WriteCmd(0x00); //low column start address
WriteCmd(0x10); //high column start address
for(n=0;n<128;n++)
{
WriteDat(fill_Data);
}
}
}
void OLED_CLS(void)
{
OLED_Fill(0x00);
}
显示中文
字位图(bmp)提取软件 pctolcd2002 所需要的配置 生成的汉字bmp数据 //16*16点阵,维护世界和平
unsigned char F16x16[]=
{
0x20,0x30,0xAC,0x63,0x20,0x58,0x20,0xF8,0x4F,0x48,0x49,0xFA,0x48,0x48,0x08,0x00,
0x22,0x67,0x22,0x12,0x12,0x12,0x00,0xFF,0x22,0x22,0x22,0x3F,0x22,0x22,0x20,0x00,//维
0x10,0x10,0x10,0xFF,0x10,0x90,0x00,0xF8,0x88,0x89,0x8E,0x88,0x88,0x88,0xF8,0x00,
0x04,0x44,0x82,0x7F,0x81,0x40,0x30,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,//护
0x20,0x20,0x20,0xFE,0x20,0x20,0xFF,0x20,0x20,0x20,0xFF,0x20,0x20,0x20,0x20,0x00,
0x00,0x00,0x00,0x7F,0x40,0x40,0x47,0x44,0x44,0x44,0x47,0x40,0x40,0x40,0x00,0x00,//世
0x00,0x00,0x00,0xFE,0x92,0x92,0x92,0xFE,0x92,0x92,0x92,0xFE,0x00,0x00,0x00,0x00,
0x08,0x08,0x04,0x84,0x62,0x1E,0x01,0x00,0x01,0xFE,0x02,0x04,0x04,0x08,0x08,0x00,//界
0x20,0x24,0x24,0xA4,0xFE,0x23,0x22,0x20,0x00,0xF8,0x08,0x08,0x08,0xF8,0x00,0x00,
0x10,0x08,0x06,0x01,0xFF,0x01,0x06,0x00,0x00,0x3F,0x10,0x10,0x10,0x3F,0x00,0x00,//和
0x00,0x02,0x02,0x12,0x62,0x02,0x02,0xFE,0x02,0x02,0x42,0x32,0x02,0x02,0x00,0x00,
0x01,0x01,0x01,0x01,0x01,0x01,0x01,0xFF,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x00,//平
};
//显示中文函数
void OLED_ShowCN(unsigned char x, unsigned char y, unsigned char N)
{
unsigned char wm=0;
unsigned int adder=32*N;
OLED_SetPos(x , y);
for(wm = 0;wm < 16;wm++)
{
WriteDat(F16x16[adder]);
adder += 1;
}
OLED_SetPos(x,y + 1);
for(wm = 0;wm < 16;wm++)
{
WriteDat(F16x16[adder]);
adder += 1;
}
}
//主函数调用
for(i=0;i<6;i++)//6 代表有6个字
{
OLED_ShowCN(22+i*16,0,i); //测试显示中文
}
显示英文
//6*8点阵 const unsigned char F6x8[][6] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,// sp 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00,// ! 0x00, 0x00, 0x07, 0x00, 0x07, 0x00,// " 0x00, 0x14, 0x7f, 0x14, 0x7f, 0x14,// # 0x00, 0x24, 0x2a, 0x7f, 0x2a, 0x12,// $ 0x00, 0x62, 0x64, 0x08, 0x13, 0x23,// % 0x00, 0x36, 0x49, 0x55, 0x22, 0x50,// & 0x00, 0x00, 0x05, 0x03, 0x00, 0x00,// ' 0x00,