1、OLED概述:
2、OLED的特点:
1、和单片机的接线方法:
2、写操作时序分析:如图所示是IIC协议数据总线上一帧数据的数据格式。
3、写指令函数封装:
void Oled_Write_Cmd(char dataCmd)
{
IIC_Start(); //1.发送起始信号
IIC_Send_Byte(0x78); //2.确认从机地址,准备写入
IIC_ACK(); //3.应答信号ACK读取
IIC_Send_Byte(0x00); //4.发送控制字节,确认发送指令
IIC_ACK(); //5.应答信号ACK读取
IIC_Send_Byte(dataCmd); //6.发送指令
IIC_ACK(); //7.应答信号ACK读取
IIC_Stop(); //8.发送停止信号
}
4、写数据函数封装:
void Oled_Write_Data(char dataData)
{
IIC_Start(); //1.发送起始信号
IIC_Send_Byte(0x78); //2.确认从机地址,准备写入
IIC_ACK(); //3.应答信号ACK读取
IIC_Send_Byte(0x40); //4.发送控制字节,确认发送数据
IIC_ACK(); //5.应答信号ACK读取
IIC_Send_Byte(dataData);//6.发送数据
IIC_ACK(); //7.应答信号ACK读取
IIC_Stop(); //8.发送停止信号
}
1、OLED点阵的管理:搞清在哪显示
OLED:128×64 | 0列 | 1列 | 2列 | 3列 | .............. | 124列 | 125列 | 126列 | 127列 | ||
PAGE0 | bit0 | 0行 | |||||||||
bit1 | 1行 | ||||||||||
bit2 | 2行 | ||||||||||
bit3 | 3行 | ||||||||||
bit4 | 4行 | ||||||||||
bit5 | 5行 | ||||||||||
bit6 | 6行 | ||||||||||
bit7 | 7行 | ||||||||||
PAGE1 | 8到15行 | ||||||||||
PAGE2 | 16到23行 | ||||||||||
PAGE3 | 24到31行 | ||||||||||
PAGE4 | 32到39行 | ||||||||||
PAGE5 | 40到47行 | ||||||||||
PAGE6 | 48到55行 | ||||||||||
PAGE7 | 56到63行 |
2、三种内存寻址模式:搞清显示地址指针移动方式
3、发送指令确认寻址模式:搞清如何显示,查阅地址设置控制表。
4、发送指令选择特定页:搞清如何显示,查阅地址设置控制表。
5、发送指令选择特定段:搞清如何显示,查阅地址设置控制表。
这种指令只适用于页寻址模式。
1、OLED初始化函数封装:叁议电子为我们整理了如下初始化过程
(01)display off (0xae)
(02)set low column address (0x00)
(03)set high column address (0x10)
(04)set start line address (0x40)
(05)set page address (0xb0)
(06)contract control (0x81)
(07)send 0xff(多字节指令)
(08)set segment remap (0xa1)
(09)set normal/reverse (0xa6)
(10)set multiplex ratio (1 to 64) (0xa8)
(11)set duty 1/32 (0x3f)
(12)com scan direction (0xc8)
(13)set display offset (0xd3)
(14)send 0x00
(15)set osc division(0xd5)
(16)send 0x80
(17)set area color mode off (0xd8)
(18)send 0x05
(19)set pre-charge period (0xd9)
(20)send 0xf1
(21)set com pin configuration (0xda)
(22)send 0x12
(23)set Vcomh(0xdb)
(24)send0x30
(25)set charge pump enable(0x8d)
(26)send 0x14
(27)turn on oled panel(0xaf)
void Oled_Init()
{
Oled_Write_Cmd(0xAE); //(01)display off (0xae)
Oled_Write_Cmd(0x00); //(02)set low column address (0x00)
Oled_Write_Cmd(0x10); //(03)set high column address (0x10)
Oled_Write_Cmd(0x40); //(04)set start line address (0x40)
Oled_Write_Cmd(0xB0); //(05)set page address (0xb0)
Oled_Write_Cmd(0x81); //(06)contract control (0x81)
Oled_Write_Cmd(0xFF); //(07)send 0xff(多字节指令)
Oled_Write_Cmd(0xA1); //(08)set segment remap (0xa1)
Oled_Write_Cmd(0xA6); //(09)set normal/reverse (0xa6)
Oled_Write_Cmd(0xA8); //(10)set multiplex ratio (1 to 64) (0xa8)
Oled_Write_Cmd(0x3F); //(11)set duty 1/32 (0x3f)
Oled_Write_Cmd(0xC8); //(12)com scan direction (0xc8)
Oled_Write_Cmd(0xD3); //(13)set display offset (0xd3)
Oled_Write_Cmd(0x00); //(14)send 0x00
Oled_Write_Cmd(0xD5); //(15)set osc division(0xd5)
Oled_Write_Cmd(0x80); //(16)send 0x80
Oled_Write_Cmd(0xD8); //(17)set area color mode off (0xd8)
Oled_Write_Cmd(0x05); //(18)send 0x05
Oled_Write_Cmd(0xD9); //(19)set pre-charge period (0xd9)
Oled_Write_Cmd(0xF1); //(20)send 0xf1
Oled_Write_Cmd(0xDA); //(21)set com pin configuration (0xda)
Oled_Write_Cmd(0x12); //(22)send 0x12
Oled_Write_Cmd(0xDB); //(23)set Vcomh(0xdb)
Oled_Write_Cmd(0x30); //(24)send0x30
Oled_Write_Cmd(0x8D); //(25)set charge pump enable(0x8d)
Oled_Write_Cmd(0x14); //(26)send 0x14
Oled_Write_Cmd(0xAF); //(27)turn on oled panel(0xaf)
}
1、OLED添加清屏函数:
void Oled_Clear()
{
int i;
int j;
for(i=0; i<8; i++){
Oled_Write_Cmd(0xB0 + i); // 依次指定PAGE0~PAGE7
// 指定SEG0
Oled_Write_Cmd(0x00);
Oled_Write_Cmd(0x10);
// 0到127列,每次写入0,每次写入数据列地址自动偏移
for(j=0; j<128; j++){
Oled_Write_Data(0);
}
}
}
1、OLED雪花BUG:
void IIC_Start()
{
scl = 0; // 防止OLED雪花
// o点:
scl = 1; // SCL置高电平
sda = 0; // SDA置低电平
// a点:
// SCL维持高电平
sda = 1; // SDA从低电平转折为高电平,时间未知
// a—>b:
// SCL维持高电平
_nop_(); // SDA延时4.7微秒
// b—>c:
// SCL维持高电平
sda = 0; // SDA从高电平转折为低电平,时间未知
// c—>d:
_nop_(); // SCL延时4微秒
// SDA维持低电平
// d点:
scl = 0; // SCL从高电平转折为低电平,时间未知
// SDA维持低电平
}
2、OLED显示一个点及一行水平线:
#include "reg52.h"
#include "intrins.h"
sbit scl = P0^1;
sbit sda = P0^3;
/* API1. 启动I2C */
void IIC_Start();
/* API2. 终止I2C */
void IIC_Stop();
/* API3. 获取IIC的应答位 */
char IIC_ACK();
/* API4. I2C发送1字节数据 */
void IIC_Send_Byte(char cdata);
/* API5. OLED写指令(1Byte) */
void Oled_Write_Cmd(char dataCmd);
/* API6. OLED写数据(1Byte) */
void Oled_Write_Data(char dataData);
/* API7. OLED初始化 */
void Oled_Init();
/* API8. OLED清屏 */
void Oled_Clear();
void main(void)
{
Oled_Init();
// 设置页寻址模式
Oled_Write_Cmd(0x20);
Oled_Write_Cmd(0x02);
// 清屏
Oled_Clear();
// 指定PAGE0
Oled_Write_Cmd(0xB0);
// 指定SEG0
Oled_Write_Cmd(0x00);
Oled_Write_Cmd(0x10);
// 写数据,显示一个点
Oled_Write_Data(0x08);
// 指定PAGE1
Oled_Write_Cmd(0xB1);
// 指定SEG0
Oled_Write_Cmd(0x00);
Oled_Write_Cmd(0x10);
// 写数据,显示一条线
Oled_Write_Data(0x08);
Oled_Write_Data(0x08);
Oled_Write_Data(0x08);
Oled_Write_Data(0x08);
Oled_Write_Data(0x08);
while(1); //防止程序退出
}
void IIC_Start()
{
scl = 0; // 防止OLED雪花
// o点:
scl = 1; // SCL置高电平
sda = 0; // SDA置低电平
// a点:
// SCL维持高电平
sda = 1; // SDA从低电平转折为高电平,时间未知
// a—>b:
// SCL维持高电平
_nop_(); // SDA延时4.7微秒
// b—>c:
// SCL维持高电平
sda = 0; // SDA从高电平转折为低电平,时间未知
// c—>d:
_nop_(); // SCL延时4微秒
// SDA维持低电平
// d点:
scl = 0; // SCL从高电平转折为低电平,时间未知
// SDA维持低电平
}
void IIC_Stop()
{
// o点:
scl = 0; // SCL置低电平
sda = 0; // SDA置低电平
// a点:
scl = 1; // SCL从低电平转折为高电平,时间未知
// SDA维持低电平
// a—>b:
// SCL维持高电平
_nop_(); // SDA延时4微秒
// b—>c:
// SCL维持高电平
sda = 1; // SDA从低电平折为高电平,时间未知
// c—>d:
// SCL维持低高电平
_nop_(); // SDA延时4.7微秒
// d点:
// SCL维持高电平
sda = 0; // SDA从高电平转折为低电平,时间未知
}
char IIC_ACK()
{
char flag;
// o点:
// SCL置低电平
sda = 1; // SDA:在主控设备发送完成一个字节数据后,就立马发送一个高电平,代表释放SDA数据线
// o—>a:
_nop_(); // SCL延时
// a点:
scl = 1; // SCL从低电平转折为高电平,代表释放SCL数据线
// a—>b:
_nop_(); // SCL延时4微秒,因为读取SDA的时候一定要保证SCL处于高电平的状态
flag = sda; // SDA被读
_nop_(); // SCL延时4微秒,因为读取SDA的时候一定要保证SCL处于高电平的状态
// b点:
scl = 0; // SCL从高电平转折为低电平
// b—>c:
_nop_(); // SCL延时
return flag;
}
void IIC_Send_Byte(char cdata)
{
int i;
for(i=0; i<8; i++){
// o点:
scl = 0; // SCL置低电平:允许数据翻转
sda = cdata & 0x80; // SDA发送1bit数据
// o—>a:
_nop_(); // SCL延时5微秒
// SDA正在发送数据
// a点:
scl = 1; // SCL从低电平转折为高电平
// a—>b:
_nop_(); // SCL延时5微秒
// SDA正在发送数据
// b点:
scl = 0; // SCL从高电平转折为低电平:为下一次数据翻转做准备
// b—>c:
_nop_(); // SCL延时5微秒
cdata = cdata << 1;
}
}
void Oled_Write_Cmd(char dataCmd)
{
IIC_Start(); //发送起始信号
IIC_Send_Byte(0x78); //确认从机地址,准备写入
IIC_ACK(); //应答信号ACK读取
IIC_Send_Byte(0x00); //发送控制字节,确认发送指令
IIC_ACK(); //应答信号ACK读取
IIC_Send_Byte(dataCmd); //发送指令
IIC_ACK(); //应答信号ACK读取
IIC_Stop(); //发送停止信号
}
void Oled_Write_Data(char dataData)
{
IIC_Start(); //发送起始信号
IIC_Send_Byte(0x78); //确认从机地址,准备写入
IIC_ACK(); //应答信号ACK读取
IIC_Send_Byte(0x40); //发送控制字节,确认发送数据
IIC_ACK(); //应答信号ACK读取
IIC_Send_Byte(dataData);//发送数据
IIC_ACK(); //应答信号ACK读取
IIC_Stop(); //发送停止信号
}
void Oled_Init()
{
Oled_Write_Cmd(0xAE); //(01)display off (0xae)
Oled_Write_Cmd(0x00); //(02)set low column address (0x00)
Oled_Write_Cmd(0x10); //(03)set high column address (0x10)
Oled_Write_Cmd(0x40); //(04)set start line address (0x40)
Oled_Write_Cmd(0xB0); //(05)set page address (0xb0)
Oled_Write_Cmd(0x81); //(06)contract control (0x81)
Oled_Write_Cmd(0xFF); //(07)send 0xff(多字节指令)
Oled_Write_Cmd(0xA1); //(08)set segment remap (0xa1)
Oled_Write_Cmd(0xA6); //(09)set normal/reverse (0xa6)
Oled_Write_Cmd(0xA8); //(10)set multiplex ratio (1 to 64) (0xa8)
Oled_Write_Cmd(0x3F); //(11)set duty 1/32 (0x3f)
Oled_Write_Cmd(0xC8); //(12)com scan direction (0xc8)
Oled_Write_Cmd(0xD3); //(13)set display offset (0xd3)
Oled_Write_Cmd(0x00); //(14)send 0x00
Oled_Write_Cmd(0xD5); //(15)set osc division(0xd5)
Oled_Write_Cmd(0x80); //(16)send 0x80
Oled_Write_Cmd(0xD8); //(17)set area color mode off (0xd8)
Oled_Write_Cmd(0x05); //(18)send 0x05
Oled_Write_Cmd(0xD9); //(19)set pre-charge period (0xd9)
Oled_Write_Cmd(0xF1); //(20)send 0xf1
Oled_Write_Cmd(0xDA); //(21)set com pin configuration (0xda)
Oled_Write_Cmd(0x12); //(22)send 0x12
Oled_Write_Cmd(0xDB); //(23)set Vcomh(0xdb)
Oled_Write_Cmd(0x30); //(24)send0x30
Oled_Write_Cmd(0x8D); //(25)set charge pump enable(0x8d)
Oled_Write_Cmd(0x14); //(26)send 0x14
Oled_Write_Cmd(0xAF); //(27)turn on oled panel(0xaf)
}
void Oled_Clear()
{
int i;
int j;
for(i=0; i<8; i++){
Oled_Write_Cmd(0xB0 + i); // 依次指定PAGE0~PAGE7
// 指定SEG0
Oled_Write_Cmd(0x00);
Oled_Write_Cmd(0x10);
// 0到127列,每次写入0,每次写入数据列地址自动偏移
for(j=0; j<128; j++){
Oled_Write_Data(0);
}
}
}
1、字模软件的使用:
/*-- 文字: A --*/
/*-- 宋体12; 此字体下对应的点阵为:宽x高=8x16 --*/
0x00,0x00,0xC0,0x38,0xE0,0x00,0x00,0x00,0x20,0x3C,0x23,0x02,0x02,0x27,0x38,0x20,
对于我们输入的文字A(字体样式为:宋体12),生成的点阵宽为8、高为16。这就意味着需要用到2个PAGE,那么我们就要将这个数据拆分成两个字符数组:
数组1:0x00,0x00,0xC0,0x38,0xE0,0x00,0x00,0x00
数组2:0x20,0x3C,0x23,0x02,0x02,0x27,0x38,0x20
2、字符'A'的点阵规划:
PAGE0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | |
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | |
0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | |
0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | |
0 | 0 | 0 | 1 | 1 | 0 | 0 | 0 | |
0 | 0 | 1 | 0 | 1 | 0 | 0 | 0 | |
0 | 0 | 1 | 0 | 1 | 0 | 0 | 0 | |
PAGE1 | 0 | 0 | 1 | 0 | 0 | 1 | 0 | 0 |
0 | 0 | 1 | 1 | 1 | 1 | 0 | 0 | |
0 | 1 | 0 | 0 | 0 | 1 | 0 | 0 | |
0 | 1 | 0 | 0 | 0 | 0 | 1 | 0 | |
0 | 1 | 0 | 0 | 0 | 0 | 1 | 0 | |
1 | 1 | 1 | 0 | 0 | 1 | 1 | 1 | |
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | |
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
3、OLED显示一个字符‘A’:
代码:其中API 1~API 8 是通用代码
#include "reg52.h"
#include "intrins.h"
sbit scl = P0^1;
sbit sda = P0^3;
/* API1. 启动I2C */
void IIC_Start();
/* API2. 终止I2C */
void IIC_Stop();
/* API3. 获取IIC的应答位 */
char IIC_ACK();
/* API4. I2C发送1字节数据 */
void IIC_Send_Byte(char cdata);
/* API5. OLED写指令(1Byte) */
void Oled_Write_Cmd(char dataCmd);
/* API6. OLED写数据(1Byte) */
void Oled_Write_Data(char dataData);
/* API7. OLED初始化 */
void Oled_Init();
/* API8. OLED清屏 */
void Oled_Clear();
/* API9. OLED显示字符'A' */
void Oled_Show_Char();
/*-- 文字: A --*/
/*-- 宋体12; 此字体下对应的点阵为:宽x高=8x16,用到两个PAGE,所以拆分成两个字符数组 --*/
char A1[8] = {0x00,0x00,0xC0,0x38,0xE0,0x00,0x00,0x00};
char A2[8] = {0x20,0x3C,0x23,0x02,0x02,0x27,0x38,0x20};
void main(void)
{
int i;
Oled_Init();
// 设置页寻址模式
Oled_Write_Cmd(0x20);
Oled_Write_Cmd(0x02);
// 清屏
Oled_Clear();
Oled_Show_Char();
while(1); //防止程序退出
}
void IIC_Start()
{
scl = 0; // 防止OLED雪花
// o点:
scl = 1; // SCL置高电平
sda = 0; // SDA置低电平
// a点:
// SCL维持高电平
sda = 1; // SDA从低电平转折为高电平,时间未知
// a—>b:
// SCL维持高电平
_nop_(); // SDA延时4.7微秒
// b—>c:
// SCL维持高电平
sda = 0; // SDA从高电平转折为低电平,时间未知
// c—>d:
_nop_(); // SCL延时4微秒
// SDA维持低电平
// d点:
scl = 0; // SCL从高电平转折为低电平,时间未知
// SDA维持低电平
}
void IIC_Stop()
{
// o点:
scl = 0; // SCL置低电平
sda = 0; // SDA置低电平
// a点:
scl = 1; // SCL从低电平转折为高电平,时间未知
// SDA维持低电平
// a—>b:
// SCL维持高电平
_nop_(); // SDA延时4微秒
// b—>c:
// SCL维持高电平
sda = 1; // SDA从低电平折为高电平,时间未知
// c—>d:
// SCL维持低高电平
_nop_(); // SDA延时4.7微秒
// d点:
// SCL维持高电平
sda = 0; // SDA从高电平转折为低电平,时间未知
}
char IIC_ACK()
{
char flag;
// o点:
// SCL置低电平
sda = 1; // SDA:在主控设备发送完成一个字节数据后,就立马发送一个高电平,代表释放SDA数据线
// o—>a:
_nop_(); // SCL延时
// a点:
scl = 1; // SCL从低电平转折为高电平,代表释放SCL数据线
// a—>b:
_nop_(); // SCL延时4微秒,因为读取SDA的时候一定要保证SCL处于高电平的状态
flag = sda; // SDA被读
_nop_(); // SCL延时4微秒,因为读取SDA的时候一定要保证SCL处于高电平的状态
// b点:
scl = 0; // SCL从高电平转折为低电平
// b—>c:
_nop_(); // SCL延时
return flag;
}
void IIC_Send_Byte(char cdata)
{
int i;
for(i=0; i<8; i++){
// o点:
scl = 0; // SCL置低电平:允许数据翻转
sda = cdata & 0x80; // SDA发送1bit数据
// o—>a:
_nop_(); // SCL延时5微秒
// SDA正在发送数据
// a点:
scl = 1; // SCL从低电平转折为高电平
// a—>b:
_nop_(); // SCL延时5微秒
// SDA正在发送数据
// b点:
scl = 0; // SCL从高电平转折为低电平:为下一次数据翻转做准备
// b—>c:
_nop_(); // SCL延时5微秒
cdata = cdata << 1;
}
}
void Oled_Write_Cmd(char dataCmd)
{
IIC_Start(); //发送起始信号
IIC_Send_Byte(0x78); //确认从机地址,准备写入
IIC_ACK(); //应答信号ACK读取
IIC_Send_Byte(0x00); //发送控制字节,确认发送指令
IIC_ACK(); //应答信号ACK读取
IIC_Send_Byte(dataCmd); //发送指令
IIC_ACK(); //应答信号ACK读取
IIC_Stop(); //发送停止信号
}
void Oled_Write_Data(char dataData)
{
IIC_Start(); //发送起始信号
IIC_Send_Byte(0x78); //确认从机地址,准备写入
IIC_ACK(); //应答信号ACK读取
IIC_Send_Byte(0x40); //发送控制字节,确认发送数据
IIC_ACK(); //应答信号ACK读取
IIC_Send_Byte(dataData);//发送数据
IIC_ACK(); //应答信号ACK读取
IIC_Stop(); //发送停止信号
}
void Oled_Init()
{
Oled_Write_Cmd(0xAE); //(01)display off (0xae)
Oled_Write_Cmd(0x00); //(02)set low column address (0x00)
Oled_Write_Cmd(0x10); //(03)set high column address (0x10)
Oled_Write_Cmd(0x40); //(04)set start line address (0x40)
Oled_Write_Cmd(0xB0); //(05)set page address (0xb0)
Oled_Write_Cmd(0x81); //(06)contract control (0x81)
Oled_Write_Cmd(0xFF); //(07)send 0xff(多字节指令)
Oled_Write_Cmd(0xA1); //(08)set segment remap (0xa1)
Oled_Write_Cmd(0xA6); //(09)set normal/reverse (0xa6)
Oled_Write_Cmd(0xA8); //(10)set multiplex ratio (1 to 64) (0xa8)
Oled_Write_Cmd(0x3F); //(11)set duty 1/32 (0x3f)
Oled_Write_Cmd(0xC8); //(12)com scan direction (0xc8)
Oled_Write_Cmd(0xD3); //(13)set display offset (0xd3)
Oled_Write_Cmd(0x00); //(14)send 0x00
Oled_Write_Cmd(0xD5); //(15)set osc division(0xd5)
Oled_Write_Cmd(0x80); //(16)send 0x80
Oled_Write_Cmd(0xD8); //(17)set area color mode off (0xd8)
Oled_Write_Cmd(0x05); //(18)send 0x05
Oled_Write_Cmd(0xD9); //(19)set pre-charge period (0xd9)
Oled_Write_Cmd(0xF1); //(20)send 0xf1
Oled_Write_Cmd(0xDA); //(21)set com pin configuration (0xda)
Oled_Write_Cmd(0x12); //(22)send 0x12
Oled_Write_Cmd(0xDB); //(23)set Vcomh(0xdb)
Oled_Write_Cmd(0x30); //(24)send0x30
Oled_Write_Cmd(0x8D); //(25)set charge pump enable(0x8d)
Oled_Write_Cmd(0x14); //(26)send 0x14
Oled_Write_Cmd(0xAF); //(27)turn on oled panel(0xaf)
}
void Oled_Clear()
{
int i;
int j;
for(i=0; i<8; i++){
Oled_Write_Cmd(0xB0 + i); // 依次指定PAGE0~PAGE7
// 指定SEG0
Oled_Write_Cmd(0x00);
Oled_Write_Cmd(0x10);
// 0到127列,每次写入0,每次写入数据列地址自动偏移
for(j=0; j<128; j++){
Oled_Write_Data(0);
}
}
}
void Oled_Show_Char()
{
/* 显示字符'A' */
// 指定PAGE0
Oled_Write_Cmd(0xB0);
// 指定SEG0
Oled_Write_Cmd(0x00);
Oled_Write_Cmd(0x10);
// 写数据,显示字符'A'的上半部分
for(i=0; i<8; i++){
Oled_Write_Data(A1[i]);
}
// 指定PAGE1
Oled_Write_Cmd(0xB1);
// 指定SEG0
Oled_Write_Cmd(0x00);
Oled_Write_Cmd(0x10);
// 写数据,显示字符'A'的下半部分
for(i=0; i<8; i++){
Oled_Write_Data(A2[i]);
}
}
1、汉字字模提取:
2、OLED显示“嵌入式软件”:
#include "reg52.h"
#include "intrins.h"
sbit scl = P0^1;
sbit sda = P0^3;
/* API1. 启动I2C */
void IIC_Start();
/* API2. 终止I2C */
void IIC_Stop();
/* API3. 获取IIC的应答位 */
char IIC_ACK();
/* API4. I2C发送1字节数据 */
void IIC_Send_Byte(char cdata);
/* API5. OLED写指令(1Byte) */
void Oled_Write_Cmd(char dataCmd);
/* API6. OLED写数据(1Byte) */
void Oled_Write_Data(char dataData);
/* API7. OLED初始化 */
void Oled_Init();
/* API8. OLED清屏 */
void Oled_Clear();
/* API9. OLED显示汉字 */
void Oled_Show_Hanzi();
/*-- 文字: 嵌 --*/
/*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/
code char qian1[16] = {0x80,0x80,0xEE,0x88,0x88,0x88,0xE8,0x8F,0x08,0x88,0x78,0x48,0x4E,0x40,0xC0,0x00};
code char qian2[16] = {0x00,0x00,0x7F,0x24,0x24,0x24,0x7F,0x00,0x81,0x40,0x30,0x0F,0x30,0x41,0x80,0x00};
/*-- 文字: 入 --*/
/*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/
code char ru1[16] = {0x00,0x00,0x00,0x00,0x00,0x01,0xE2,0x1C,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
code char ru2[16] = {0x80,0x40,0x20,0x10,0x0C,0x03,0x00,0x00,0x00,0x03,0x0C,0x30,0x40,0x80,0x80,0x00};
/*-- 文字: 式 --*/
/*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/
code char shi1[16] = {0x10,0x10,0x90,0x90,0x90,0x90,0x90,0x10,0x10,0xFF,0x10,0x10,0x11,0x16,0x10,0x00};
code char shi2[16] = {0x00,0x20,0x60,0x20,0x3F,0x10,0x10,0x10,0x00,0x03,0x0C,0x10,0x20,0x40,0xF8,0x00};
/*-- 文字: 软 --*/
/*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/
code char ruan1[16] = {0x08,0xC8,0xB8,0x8F,0xE8,0x88,0x88,0x40,0x30,0x0F,0xC8,0x08,0x28,0x18,0x00,0x00};
code char ruan2[16] = {0x08,0x18,0x08,0x08,0xFF,0x04,0x84,0x40,0x30,0x0E,0x01,0x0E,0x30,0x40,0x80,0x00};
/*-- 文字: 件 --*/
/*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/
code char jian1[16] = {0x00,0x80,0x60,0xF8,0x07,0x80,0x60,0x1C,0x10,0x10,0xFF,0x10,0x10,0x10,0x00,0x00};
code char jian2[16] = {0x01,0x00,0x00,0xFF,0x00,0x02,0x02,0x02,0x02,0x02,0xFF,0x02,0x02,0x02,0x02,0x00};
void main(void)
{
unsigned char i;
Oled_Init();
// 设置页寻址模式
Oled_Write_Cmd(0x20);
Oled_Write_Cmd(0x02);
// 清屏
Oled_Clear();
Oled_Show_Hanzi();
while(1); //防止程序退出
}
void IIC_Start()
{
scl = 0; // 防止OLED雪花
// o点:
scl = 1; // SCL置高电平
sda = 0; // SDA置低电平
// a点:
// SCL维持高电平
sda = 1; // SDA从低电平转折为高电平,时间未知
// a—>b:
// SCL维持高电平
_nop_(); // SDA延时4.7微秒
// b—>c:
// SCL维持高电平
sda = 0; // SDA从高电平转折为低电平,时间未知
// c—>d:
_nop_(); // SCL延时4微秒
// SDA维持低电平
// d点:
scl = 0; // SCL从高电平转折为低电平,时间未知
// SDA维持低电平
}
void IIC_Stop()
{
// o点:
scl = 0; // SCL置低电平
sda = 0; // SDA置低电平
// a点:
scl = 1; // SCL从低电平转折为高电平,时间未知
// SDA维持低电平
// a—>b:
// SCL维持高电平
_nop_(); // SDA延时4微秒
// b—>c:
// SCL维持高电平
sda = 1; // SDA从低电平折为高电平,时间未知
// c—>d:
// SCL维持低高电平
_nop_(); // SDA延时4.7微秒
// d点:
// SCL维持高电平
sda = 0; // SDA从高电平转折为低电平,时间未知
}
char IIC_ACK()
{
char flag;
// o点:
// SCL置低电平
sda = 1; // SDA:在主控设备发送完成一个字节数据后,就立马发送一个高电平,代表释放SDA数据线
// o—>a:
_nop_(); // SCL延时
// a点:
scl = 1; // SCL从低电平转折为高电平,代表释放SCL数据线
// a—>b:
_nop_(); // SCL延时4微秒,因为读取SDA的时候一定要保证SCL处于高电平的状态
flag = sda; // SDA被读
_nop_(); // SCL延时4微秒,因为读取SDA的时候一定要保证SCL处于高电平的状态
// b点:
scl = 0; // SCL从高电平转折为低电平
// b—>c:
_nop_(); // SCL延时
return flag;
}
void IIC_Send_Byte(char cdata)
{
int i;
for(i=0; i<8; i++){
// o点:
scl = 0; // SCL置低电平:允许数据翻转
sda = cdata & 0x80; // SDA发送1bit数据
// o—>a:
_nop_(); // SCL延时5微秒
// SDA正在发送数据
// a点:
scl = 1; // SCL从低电平转折为高电平
// a—>b:
_nop_(); // SCL延时5微秒
// SDA正在发送数据
// b点:
scl = 0; // SCL从高电平转折为低电平:为下一次数据翻转做准备
// b—>c:
_nop_(); // SCL延时5微秒
cdata = cdata << 1;
}
}
void Oled_Write_Cmd(char dataCmd)
{
IIC_Start(); //发送起始信号
IIC_Send_Byte(0x78); //确认从机地址,准备写入
IIC_ACK(); //应答信号ACK读取
IIC_Send_Byte(0x00); //发送控制字节,确认发送指令
IIC_ACK(); //应答信号ACK读取
IIC_Send_Byte(dataCmd); //发送指令
IIC_ACK(); //应答信号ACK读取
IIC_Stop(); //发送停止信号
}
void Oled_Write_Data(char dataData)
{
IIC_Start(); //发送起始信号
IIC_Send_Byte(0x78); //确认从机地址,准备写入
IIC_ACK(); //应答信号ACK读取
IIC_Send_Byte(0x40); //发送控制字节,确认发送数据
IIC_ACK(); //应答信号ACK读取
IIC_Send_Byte(dataData);//发送数据
IIC_ACK(); //应答信号ACK读取
IIC_Stop(); //发送停止信号
}
void Oled_Init()
{
Oled_Write_Cmd(0xAE); //(01)display off (0xae)
Oled_Write_Cmd(0x00); //(02)set low column address (0x00)
Oled_Write_Cmd(0x10); //(03)set high column address (0x10)
Oled_Write_Cmd(0x40); //(04)set start line address (0x40)
Oled_Write_Cmd(0xB0); //(05)set page address (0xb0)
Oled_Write_Cmd(0x81); //(06)contract control (0x81)
Oled_Write_Cmd(0xFF); //(07)send 0xff(多字节指令)
Oled_Write_Cmd(0xA1); //(08)set segment remap (0xa1)
Oled_Write_Cmd(0xA6); //(09)set normal/reverse (0xa6)
Oled_Write_Cmd(0xA8); //(10)set multiplex ratio (1 to 64) (0xa8)
Oled_Write_Cmd(0x3F); //(11)set duty 1/32 (0x3f)
Oled_Write_Cmd(0xC8); //(12)com scan direction (0xc8)
Oled_Write_Cmd(0xD3); //(13)set display offset (0xd3)
Oled_Write_Cmd(0x00); //(14)send 0x00
Oled_Write_Cmd(0xD5); //(15)set osc division(0xd5)
Oled_Write_Cmd(0x80); //(16)send 0x80
Oled_Write_Cmd(0xD8); //(17)set area color mode off (0xd8)
Oled_Write_Cmd(0x05); //(18)send 0x05
Oled_Write_Cmd(0xD9); //(19)set pre-charge period (0xd9)
Oled_Write_Cmd(0xF1); //(20)send 0xf1
Oled_Write_Cmd(0xDA); //(21)set com pin configuration (0xda)
Oled_Write_Cmd(0x12); //(22)send 0x12
Oled_Write_Cmd(0xDB); //(23)set Vcomh(0xdb)
Oled_Write_Cmd(0x30); //(24)send0x30
Oled_Write_Cmd(0x8D); //(25)set charge pump enable(0x8d)
Oled_Write_Cmd(0x14); //(26)send 0x14
Oled_Write_Cmd(0xAF); //(27)turn on oled panel(0xaf)
}
void Oled_Clear()
{
int i;
int j;
for(i=0; i<8; i++){
Oled_Write_Cmd(0xB0 + i); // 依次指定PAGE0~PAGE7
// 指定SEG0
Oled_Write_Cmd(0x00);
Oled_Write_Cmd(0x10);
// 0到127列,每次写入0,每次写入数据列地址自动偏移
for(j=0; j<128; j++){
Oled_Write_Data(0);
}
}
}
void Oled_Show_Hanzi()
{
/* 显示汉字"嵌入式软件"的上半部分 */
// 指定PAGE0
Oled_Write_Cmd(0xB0);
// 指定SEG0
Oled_Write_Cmd(0x00);
Oled_Write_Cmd(0x10);
// 写数据,显示汉字'嵌'的上半部分
for(i=0; i<16; i++){
Oled_Write_Data(qian1[i]);
}
// 写数据,显示汉字'入'的上半部分
for(i=0; i<16; i++){
Oled_Write_Data(ru1[i]);
}
// 写数据,显示汉字'式'的上半部分
for(i=0; i<16; i++){
Oled_Write_Data(shi1[i]);
}
// 写数据,显示汉字'软'的上半部分
for(i=0; i<16; i++){
Oled_Write_Data(ruan1[i]);
}
// 写数据,显示汉字'件'的上半部分
for(i=0; i<16; i++){
Oled_Write_Data(jian1[i]);
}
/* 显示汉字"嵌入式软件"的下半部分 */
// 指定PAGE1
Oled_Write_Cmd(0xB1);
// 指定SEG0
Oled_Write_Cmd(0x00);
Oled_Write_Cmd(0x10);
// 写数据,显示汉字'嵌'的下半部分
for(i=0; i<16; i++){
Oled_Write_Data(qian2[i]);
}
// 写数据,显示汉字'入'的下半部分
for(i=0; i<16; i++){
Oled_Write_Data(ru2[i]);
}
// 写数据,显示汉字'式'的下半部分
for(i=0; i<16; i++){
Oled_Write_Data(shi2[i]);
}
// 写数据,显示汉字'软'的下半部分
for(i=0; i<16; i++){
Oled_Write_Data(ruan2[i]);
}
// 写数据,显示汉字'件'的下半部分
for(i=0; i<16; i++){
Oled_Write_Data(jian2[i]);
}
}
1、图片字模提取:
2、OLED显示图片:
#include "reg52.h"
#include "intrins.h"
sbit scl = P0^1;
sbit sda = P0^3;
/* API1. 启动I2C */
void IIC_Start();
/* API2. 终止I2C */
void IIC_Stop();
/* API3. 获取IIC的应答位 */
char IIC_ACK();
/* API4. I2C发送1字节数据 */
void IIC_Send_Byte(char cdata);
/* API5. OLED写指令(1Byte) */
void Oled_Write_Cmd(char dataCmd);
/* API6. OLED写数据(1Byte) */
void Oled_Write_Data(char dataData);
/* API7. OLED初始化 */
void Oled_Init();
/* API8. OLED清屏 */
void Oled_Clear();
/* API9. OLED显示一张图片 */
void Oled_Show_Pic(char *image);
code unsigned char bmp[] = {
/*-- 调入了一幅图像:F:\51project\6.IIC协议\IIC协议与OLED\OLED显示图片\ikun.bmp --*/
/*-- 宽度x高度=127x64 --*/
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,0x00,0x00,0x00,0x00,0x80,0x80,0x80,
0xC0,0xC0,0xC0,0xC0,0xC0,0xE0,0xE0,0xE0,0x60,0x70,0x70,0x70,0x30,0x30,0x30,0x38,
0x38,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x38,0x38,0x30,0x30,0x30,0x30,0x30,
0x30,0x30,0x38,0x3C,0x3C,0x1C,0x0E,0x0E,0x0E,0x06,0x07,0x07,0x07,0x07,0x07,0x07,
0x07,0x07,0x06,0x06,0x06,0x0E,0x0E,0x0C,0x0C,0x0C,0x1C,0x1C,0x18,0x38,0x38,0x30,
0x30,0x70,0x70,0x70,0xE0,0xE0,0xC0,0xC0,0xC0,0x80,0x80,0x80,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,0x00,0x00,0x00,0x00,0x80,0x80,0xC0,0xC0,0xE0,0xE0,0x70,
0x70,0x78,0x38,0x38,0x1C,0x1C,0x1E,0x0E,0x0E,0x06,0x07,0x07,0x07,0x03,0x03,0x01,
0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xE0,0xF0,0xFC,0xFE,0xFE,
0xFE,0xFE,0x76,0x7A,0x78,0x7C,0x7C,0x7C,0x7E,0x7E,0x7E,0x77,0x76,0x7E,0x7E,0x7E,
0x7C,0x7C,0x78,0x78,0x78,0x70,0xF0,0xE0,0xE0,0xE0,0xC0,0x80,0x00,0x00,0x00,0x00,
0x40,0xC0,0xC0,0xC0,0xC1,0x81,0x81,0x81,0x03,0x07,0x07,0x07,0x0E,0x0E,0x1E,0x1C,
0x3C,0x38,0x78,0x78,0xF0,0xE0,0xE0,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00,0xC0,0xE0,
0xF0,0xF8,0x78,0x7C,0x1E,0x9E,0x8F,0x8F,0x87,0x83,0x01,0x01,0x01,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0xC0,0xF8,0xF8,0xFC,0xFC,0x3C,0x04,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,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x1F,0x1D,0x1C,0x1C,
0x18,0x18,0x18,0x18,0x18,0x18,0x38,0x30,0x30,0x70,0x60,0xE0,0xE0,0xC0,0x80,0x80,
0x00,0x80,0x80,0xC0,0xC0,0xE1,0x69,0x73,0x77,0x3F,0x3F,0xFF,0xFF,0xFE,0xF0,0xE0,
0x80,0x80,0x81,0x83,0x07,0x07,0x0F,0x3E,0x7E,0x7C,0xF8,0xF0,0xE0,0xC0,0x80,0x00,
0x00,0x00,0x00,0x00,0x01,0x03,0x07,0x07,0x3F,0x7F,0xFE,0xFC,0xE0,0x0F,0x0F,0x0F,
0x1D,0x1C,0x18,0xFF,0xFF,0xFF,0xFF,0xFF,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0xC0,0xE0,0xF0,0xF8,0xF8,0xF8,0xD0,0xC0,0xE0,0xE0,0xE0,0xEC,0xFC,0xFC,
0xFC,0xFC,0xF8,0xB8,0x38,0x30,0x30,0x3F,0x3F,0x3F,0x3F,0x20,0x00,0x00,0x00,0x00,
0x00,0x18,0x3C,0x3C,0x3C,0x3C,0x3C,0x3C,0x3C,0x3C,0x18,0x81,0xEF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xC3,0x81,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x03,0x03,0x03,0x1B,
0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x9F,0xDF,0xE7,0xFF,0xFF,0x7F,0x7F,0x7C,
0xFC,0xF0,0xE0,0xC0,0xC0,0xC0,0xC0,0xE0,0xE0,0xF1,0xFF,0x3F,0xC0,0xC0,0xC0,0xC0,
0xC0,0xE0,0x67,0x6F,0x6F,0x6F,0xEF,0xEC,0xEE,0xEE,0xFE,0xFE,0xFE,0xFF,0xFF,0x07,
0x07,0x0F,0x1F,0xFF,0xFF,0xFF,0xFF,0xFC,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xFC,
0xFC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFC,0xF8,0xF8,0x00,0x00,0x01,
0x01,0x03,0x03,0x03,0x07,0x07,0x06,0x0E,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0xEC,0xFC,
0xFC,0xFC,0x9C,0x1C,0x0C,0x0C,0x0E,0x07,0x07,0x07,0x07,0x07,0x07,0x06,0x06,0x06,
0x07,0x07,0x07,0x07,0x07,0x06,0x0E,0x8E,0x8C,0xCC,0xDC,0xFC,0xFC,0xFC,0xFC,0xEC,
0x0C,0x0C,0x06,0x06,0x06,0xE3,0xF3,0xFB,0xFB,0xFC,0xFC,0xFC,0xFE,0xFE,0xFE,0xFE,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x30,0x00,0x00,0x00,0x00,0x5D,0x1C,0x7D,0x1D,0x3C,
0x1C,0x1C,0x9C,0x9C,0x1C,0x3D,0xFD,0xFF,0xFF,0x7F,0xDF,0xFF,0xFF,0xFF,0xFE,0xFE,
0xFC,0xF8,0xF1,0xE1,0xE3,0xE7,0xE7,0xCF,0xCF,0x8F,0x8F,0x9F,0xDF,0xDF,0xDF,0xDF,
0xDF,0xDF,0xDF,0xDF,0xCF,0xCF,0xCF,0xE7,0xE7,0xE3,0xE1,0xE1,0xE0,0xE0,0xE0,0xE0,
0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE3,0xC7,0xC7,
0xC7,0xCF,0xCF,0xCF,0xDF,0xDB,0xDB,0xDF,0xDF,0xDE,0x96,0x96,0xB6,0xB6,0xB7,0xB7,
0x93,0x93,0x93,0x9B,0x9B,0x9B,0x99,0x1D,0x0D,0x0F,0x0F,0x07,0x03,0x03,0x01,0x00,
0x00,0x00,0x00,0x80,0xC1,0xC7,0xC7,0xCF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xBF,0x9F,
0x9F,0x8F,0x87,0x87,0x03,0x00,0x00,0x00,0x00,0x00,0x07,0x87,0x67,0x47,0x67,0x67,
0xE6,0xE6,0x2E,0x0E,0x0E,0xCF,0x4E,0x1E,0x1C,0xDF,0xFF,0xFF,0xFF,0xBF,0x9F,0x9F,
0x9F,0x9F,0x9F,0x9F,0x9F,0x9F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x3F,0x3F,0x3F,0x3F,
0x3F,0x7F,0x7F,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFE,0x7F,0x7F,0x7F,0x7F,0x3F,0x3F,0x3F,0x3F,0x3F,0x1F,0x1F,0x1F,0x1F,0x9F,0xFF,
0xFF,0xFF,0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x87,0x8F,0x4E,0x5E,0x2F,0x4F,0x1C,
0x3C,0x7D,0x79,0x7A,0x74,0x77,0xF8,0xFC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFE,0xFE,0xFC,0xFC,0xFC,
0xFC,0xF8,0x60,0x00,0x00,0x01,0x03,0x0F,0xFF,0xFD,0xFD,0xFD,0xFF,0xFF,0xFB,0xFB,
0xFB,0xFB,0xFB,0xFB,0xFB,0xF3,0xF3,0xF7,0xF7,0xF7,0xF7,0xF7,0x37,0x37,0x37,0x0F,
0x0F,0x07,0x17,0x37,0x37,0x37,0x77,0xF7,0xF7,0xF3,0xF3,0xFB,0xFB,0xFB,0xFB,0xFB,
0xFB,0xFF,0xFF,0xFF,0xFF,0xFD,0xFD,0xFD,0xFD,0x1F,0x07,0x03,0x03,0x01,0xC0,0xF0,
0xF8,0xF8,0xFC,0xFC,0xFC,0xFE,0xFE,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFC,0xFC,0xF8,0xF0,0xE0,0xC0,0x80,0x00
};
void main(void)
{
Oled_Init();
// 设置页寻址模式
Oled_Write_Cmd(0x20);
Oled_Write_Cmd(0x02);
// 清屏
Oled_Clear();
Oled_Show_Pic(bmp);
while(1); //防止程序退出
}
void IIC_Start()
{
scl = 0; // 防止OLED雪花
// o点:
scl = 1; // SCL置高电平
sda = 0; // SDA置低电平
// a点:
// SCL维持高电平
sda = 1; // SDA从低电平转折为高电平,时间未知
// a—>b:
// SCL维持高电平
_nop_(); // SDA延时4.7微秒
// b—>c:
// SCL维持高电平
sda = 0; // SDA从高电平转折为低电平,时间未知
// c—>d:
_nop_(); // SCL延时4微秒
// SDA维持低电平
// d点:
scl = 0; // SCL从高电平转折为低电平,时间未知
// SDA维持低电平
}
void IIC_Stop()
{
// o点:
scl = 0; // SCL置低电平
sda = 0; // SDA置低电平
// a点:
scl = 1; // SCL从低电平转折为高电平,时间未知
// SDA维持低电平
// a—>b:
// SCL维持高电平
_nop_(); // SDA延时4微秒
// b—>c:
// SCL维持高电平
sda = 1; // SDA从低电平折为高电平,时间未知
// c—>d:
// SCL维持低高电平
_nop_(); // SDA延时4.7微秒
// d点:
// SCL维持高电平
sda = 0; // SDA从高电平转折为低电平,时间未知
}
char IIC_ACK()
{
char flag;
// o点:
// SCL置低电平
sda = 1; // SDA:在主控设备发送完成一个字节数据后,就立马发送一个高电平,代表释放SDA数据线
// o—>a:
_nop_(); // SCL延时
// a点:
scl = 1; // SCL从低电平转折为高电平,代表释放SCL数据线
// a—>b:
_nop_(); // SCL延时4微秒,因为读取SDA的时候一定要保证SCL处于高电平的状态
flag = sda; // SDA被读
_nop_(); // SCL延时4微秒,因为读取SDA的时候一定要保证SCL处于高电平的状态
// b点:
scl = 0; // SCL从高电平转折为低电平
// b—>c:
_nop_(); // SCL延时
return flag;
}
void IIC_Send_Byte(char cdata)
{
int i;
for(i=0; i<8; i++){
// o点:
scl = 0; // SCL置低电平:允许数据翻转
sda = cdata & 0x80; // SDA发送1bit数据
// o—>a:
_nop_(); // SCL延时5微秒
// SDA正在发送数据
// a点:
scl = 1; // SCL从低电平转折为高电平
// a—>b:
_nop_(); // SCL延时5微秒
// SDA正在发送数据
// b点:
scl = 0; // SCL从高电平转折为低电平:为下一次数据翻转做准备
// b—>c:
_nop_(); // SCL延时5微秒
cdata = cdata << 1;
}
}
void Oled_Write_Cmd(char dataCmd)
{
IIC_Start(); //发送起始信号
IIC_Send_Byte(0x78); //确认从机地址,准备写入
IIC_ACK(); //应答信号ACK读取
IIC_Send_Byte(0x00); //发送控制字节,确认发送指令
IIC_ACK(); //应答信号ACK读取
IIC_Send_Byte(dataCmd); //发送指令
IIC_ACK(); //应答信号ACK读取
IIC_Stop(); //发送停止信号
}
void Oled_Write_Data(char dataData)
{
IIC_Start(); //发送起始信号
IIC_Send_Byte(0x78); //确认从机地址,准备写入
IIC_ACK(); //应答信号ACK读取
IIC_Send_Byte(0x40); //发送控制字节,确认发送数据
IIC_ACK(); //应答信号ACK读取
IIC_Send_Byte(dataData);//发送数据
IIC_ACK(); //应答信号ACK读取
IIC_Stop(); //发送停止信号
}
void Oled_Init()
{
Oled_Write_Cmd(0xAE); //(01)display off (0xae)
Oled_Write_Cmd(0x00); //(02)set low column address (0x00)
Oled_Write_Cmd(0x10); //(03)set high column address (0x10)
Oled_Write_Cmd(0x40); //(04)set start line address (0x40)
Oled_Write_Cmd(0xB0); //(05)set page address (0xb0)
Oled_Write_Cmd(0x81); //(06)contract control (0x81)
Oled_Write_Cmd(0xFF); //(07)send 0xff(多字节指令)
Oled_Write_Cmd(0xA1); //(08)set segment remap (0xa1)
Oled_Write_Cmd(0xA6); //(09)set normal/reverse (0xa6)
Oled_Write_Cmd(0xA8); //(10)set multiplex ratio (1 to 64) (0xa8)
Oled_Write_Cmd(0x3F); //(11)set duty 1/32 (0x3f)
Oled_Write_Cmd(0xC8); //(12)com scan direction (0xc8)
Oled_Write_Cmd(0xD3); //(13)set display offset (0xd3)
Oled_Write_Cmd(0x00); //(14)send 0x00
Oled_Write_Cmd(0xD5); //(15)set osc division(0xd5)
Oled_Write_Cmd(0x80); //(16)send 0x80
Oled_Write_Cmd(0xD8); //(17)set area color mode off (0xd8)
Oled_Write_Cmd(0x05); //(18)send 0x05
Oled_Write_Cmd(0xD9); //(19)set pre-charge period (0xd9)
Oled_Write_Cmd(0xF1); //(20)send 0xf1
Oled_Write_Cmd(0xDA); //(21)set com pin configuration (0xda)
Oled_Write_Cmd(0x12); //(22)send 0x12
Oled_Write_Cmd(0xDB); //(23)set Vcomh(0xdb)
Oled_Write_Cmd(0x30); //(24)send0x30
Oled_Write_Cmd(0x8D); //(25)set charge pump enable(0x8d)
Oled_Write_Cmd(0x14); //(26)send 0x14
Oled_Write_Cmd(0xAF); //(27)turn on oled panel(0xaf)
}
void Oled_Clear()
{
int i;
int j;
for(i=0; i<8; i++){
Oled_Write_Cmd(0xB0 + i); // 依次指定PAGE0~PAGE7
// 指定SEG0
Oled_Write_Cmd(0x00);
Oled_Write_Cmd(0x10);
// 0到127列,每次写入0,每次写入数据列地址自动偏移
for(j=0; j<128; j++){
Oled_Write_Data(0);
}
}
}
void Oled_Show_Pic(char *image)
{
char i;
int j;
for(i=0; i<8; i++){
Oled_Write_Cmd(0xB0 + i); // 依次指定PAGE0~PAGE7
// 指定SEG0
Oled_Write_Cmd(0x00);
Oled_Write_Cmd(0x10);
// 0到127列,每次写入0,每次写入数据列地址自动偏移
for(j=127*i; j<127*(i+1); j++){
Oled_Write_Data(image[j]);
}
}
}