IIC协议--OLED

IIC 协议:

用于连接 微控制器 以及 外围设备

半双工: 同一时间 只能进行一个方向的 传输

特点:
简单性 和 有效性:

由于 接口直接在组件上,因此IIC占用空间 非常小 -- 降低了互联成本 -- 总线的长度可达 25英尺,

并且能够以 10 Kbps/s 的最大传输速率支持40个组件 (对比 串口 20k/s)

多主控:

任何可以进行发送 和 接收的设备都课程成为 主总线 -- 控制 信号的传输 和 时钟频率

构成:

IIC 串行总线 一般有两根信号线,一根双向的数据线 SDA , 一根时钟线 SCL , 其时钟信号是由主控器产生

所有 接到 IIC 总线设备上的串行数据 SDA 都接到 总线的 SDA,各设备 的时钟线 SCL 接到总线的 SCL上

对于并联在一条总线上的每个 IC 都有唯一的地址

code:code用于声明存储在只读存储器中。code关键字通常与函数或程序的定义一起使用,也可以用来修饰常量,限制其只能存储在ROM中,从而节省了宝贵的RAM资源

=================================

第一个支持 IIC 协议的设备 -- OLED 显示屏

延时函数 5us -- 什么都不做-- 压栈和出栈就耗时5us -- nop() -- 一次 5 us

OLED时序图

起始信号 和 终止信号

应答信号

OLED 的 起始信号

根据上图可得下面代码

void IIC_Start() //开始信号

{

scl=1;

sda=1;

nop();

sda=0;

nop();

}

OLED 的终止信号

void IIC_Stop()

{

sda=0;

scl=1;

nop();

sda=1;

nop();

}

应答信号:

定义 : 发送器每发送一个信号 (8 bit), 就在脉冲9之间释放数据线,由接收器反馈一个应答信号。

应答信号为:

低电平: 规定为有效应答位 (ACK),表示接收器 已经成功接收到了该字节

高电平: 规定为非应答位(NACK),一般表示没有接收成功

char IIC_ACK()
{
char flag;
sda =1; // 就在时钟脉冲 9 期间释放数据线 -- 高电平
nop();
scl=1; // 高电平状态读取
nop();
flag = sda;
nop();
scl=0; //读完后scl变成低电平
nop();
return flag;

}

=====================================

发送一个字节函数封装:

数据发送的时序注意:

在高电平期间不允许发生 数据翻转 -- 否者 可能误判为起始信号 or 终止信号退出

低电平 -- 数据可以翻转

高电平 -- 只能传输数据

void IIC_Send_Byte(char dataSend)

{

int i;

for(i=0;i<8;++i){

scl = 0; // scl 拉低,让 sda 做好数据准备

sda = dataSend & 0x80; // SDA 获得数据最高位 1000 000

nop(); // 发送数据建立准备时间

scl=1; // scl 拉高开始发送

nop(); // 数据发送时间

scl=0; // 发送完毕就拉低

nop(); //

dataSend <<= 1; //左移一位,让次高位切换为 最高位,下一次就轮到他的

}

}

=================================

OLED 写入指令和数据:

写命令 数据代码;

1.start()

2.写入 0x78 -- 从机地址

3.ACK

4.control byte: (0)(0)000000 -- 写入命令 (0)(1)000000 -- 写入数据

5.ACK

6.写入指令/数据

7.ACK

8.STOP

void Oled_Write_Cmd(char dataCmd)

{

//1.start()

IIC_Start();

//2.写入 0x78 -- 从机地址

IIC_Send_Byte(0x78);

//3.ACK

IIC_ACK();

//4.control byte: (0)(0)000000 -- 写入命令 (0)(1)000000 -- 写入数据

IIC_Send_Byte(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();

//2.写入 0x78 -- 从机地址

IIC_Send_Byte(0x78);

//3.ACK

IIC_ACK();

//4.control byte: (0)(0)000000 -- 写入命令 (0)(1)000000 -- 写入数据

IIC_Send_Byte(0x01); //写入命令

//5.ACK

IIC_ACK();

//6.写入指令/数据

IIC_Send_Byte(dataData);

//7.ACK

IIC_ACK();

//8.STOP

IIC_Stop();

}

===================================

如何在OLED 中 显示 一个点:

128 × 64 的点阵:

oled 的地址模式:

128 列 和 怕个 0 ~~page 7:

页地址模式: (默认)

遍历完所有列后,自动调回第一列,还是那行

1.发送cmd 0x20

2.发送cmd 0x02 -- 默认次模式 02 -- 0000 0010 -- 10 页寻址模式

水平地址模式:

遍历完所有列后,自动换行 ,然后调回第一列

垂直地址模式: -- 少用 -- 了解

================

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)send 0x30

(25)set charge pump enable (0x8d)

(26)send 0x14

(27)turn on oled panel(0xaf)

清屏函数:

void Oled_Clear()

{

int i;

int j;

for(i-0;i<8;++i){

//行 page0 ~ page7

Oled_Write_Cmd(0xB0+i);

//每个page 从0列 开始

Oled_Write_Cmd(0x00);

Oled_Write_Cmd(0x10);

//列 0 ~ 127 ,一次写入0 -- 默认情况下,每次写入数据,列地址自动偏移

for(j=0;j<128;++j){

Oled_Write_Data(0); //遍历完所有位置,实现清零

}

}

}

注意 不要为了省空间把 ij定义 为char 类型 ,定义为int 类型才行,不让可能会出现数据丢失 or 雪花屏等现象

因为 char -128 ~ 127 ++j 最后一次 j=128 会越界 so 可以使用 unsigned char 和 int 都行

===================================

每次都显示指定第一列

初始地址 低位 0x00 高位0x10

case1: 显示一个点,任何组成多个点就组成一行,并且通过cmd指定每次显示位置

#include "reg52.h"

#include "intrins.h"

sbit scl = P0^1;

sbit sda = P0^3;

void IIC_Start() //开始信号

{

scl=1;

sda=1;

nop();

sda=0;

nop();

}

void IIC_Stop()

{

sda=0;

scl=1;

nop();

sda=1;

nop();

}

char IIC_ACK()

{

char flag;

sda =1; // 就在时钟脉冲 9 期间释放数据线 -- 高电平

nop();

scl=1; // 高电平状态读取

nop();

flag = sda;

nop();

scl=0; //读完后scl变成低电平

nop();

return flag;

}

void IIC_Send_Byte(char dataSend)

{

int i;

for(i=0;i<8;++i){

scl = 0; // scl 拉低,让 sda 做好数据准备

sda = dataSend & 0x80; // SDA 获得数据最高位 1000 000

nop(); // 发送数据建立准备时间

scl=1; // scl 拉高开始发送

nop(); // 数据发送时间

scl=0; // 发送完毕就拉低

nop(); //

dataSend <<= 1; //左移一位,让次高位切换为 最高位,下一次就轮到他的

}

}

void Oled_Write_Cmd(char dataCmd)

{

//1.start()

IIC_Start();

//2.写入 0x78 -- 从机地址

IIC_Send_Byte(0x78);

//3.ACK

IIC_ACK();

//4.control byte: (0)(0)000000 -- 写入命令 (0)(1)000000 -- 写入数据

IIC_Send_Byte(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();

//2.写入 0x78 -- 从机地址

IIC_Send_Byte(0x78);

//3.ACK

IIC_ACK();

//4.control byte: (0)(0)000000 -- 写入命令 (0)(1)000000 -- 写入数据

IIC_Send_Byte(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);

Oled_Write_Cmd(0x00);

Oled_Write_Cmd(0x10);

Oled_Write_Cmd(0x40);

Oled_Write_Cmd(0xb0);

Oled_Write_Cmd(0x81);

Oled_Write_Cmd(0xff);

Oled_Write_Cmd(0xa1);

Oled_Write_Cmd(0xa6);

Oled_Write_Cmd(0xa8);

Oled_Write_Cmd(0x3f);

Oled_Write_Cmd(0xc8);

Oled_Write_Cmd(0xd3);

Oled_Write_Cmd(0x00);

Oled_Write_Cmd(0xd5);

Oled_Write_Cmd(0x80);

Oled_Write_Cmd(0xd8);

Oled_Write_Cmd(0x05);

Oled_Write_Cmd(0xd9);

Oled_Write_Cmd(0xf1);

Oled_Write_Cmd(0xda);

Oled_Write_Cmd(0x12);

Oled_Write_Cmd(0xdb);

Oled_Write_Cmd(0x30);

Oled_Write_Cmd(0x8d);

Oled_Write_Cmd(0x14);

Oled_Write_Cmd(0xaf);

}

void Oled_Clear()

{

int i;

int j;

for(i-0;i<8;++i){

//行 page0 ~ page7

Oled_Write_Cmd(0xB0+i);

//每个page 从0列 开始

Oled_Write_Cmd(0x00);

Oled_Write_Cmd(0x10);

//列 0 ~ 127 ,一次写入0 -- 默认情况下,每次写入数据,列地址自动偏移

for(j=0;j<128;++j){

Oled_Write_Data(0); //遍历完所有位置,实现清零

}

}

}

void main()

{

//1. oled 初始化

Oled_Init();

// 2. 选择一个位置

//2.1确认页寻址模式:

Oled_Write_Cmd(0x20);

Oled_Write_Cmd(0x02);

Oled_Clear();// 清屏

//2.2选择PAGEO -- 1011 0000 -- 0xB0

Oled_Write_Cmd(0xB0); //选择 第一页

//3.显示一行:

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);

Oled_Write_Data(0x08);

Oled_Write_Data(0x08);

Oled_Write_Data(0x08);

Oled_Write_Data(0x08);

Oled_Write_Cmd(0xB6);

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);

Oled_Write_Data(0x08);

Oled_Write_Data(0x08);

Oled_Write_Data(0x08);

Oled_Write_Data(0x08);

Oled_Write_Cmd(0x0f);

Oled_Write_Cmd(0x17);

Oled_Write_Data(0x08);

Oled_Write_Cmd(0xB7);

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);

Oled_Write_Data(0x08);

Oled_Write_Data(0x08);

Oled_Write_Data(0x08);

Oled_Write_Data(0x08);

while(1);

}

=============================================

case2: OLED 显示一个字符A: -- 借助字模软件 -- 生成字符序列

#include "reg52.h"

#include "intrins.h"

sbit scl = P0^1;

sbit sda = P0^3;

void IIC_Start() //开始信号

{

scl=1;

sda=1;

nop();

sda=0;

nop();

}

void IIC_Stop()

{

sda=0;

scl=1;

nop();

sda=1;

nop();

}

char IIC_ACK()

{

char flag;

sda =1; // 就在时钟脉冲 9 期间释放数据线 -- 高电平

nop();

scl=1; // 高电平状态读取

nop();

flag = sda;

nop();

scl=0; //读完后scl变成低电平

nop();

return flag;

}

void IIC_Send_Byte(char dataSend)

{

int i;

for(i=0;i<8;++i){

scl = 0; // scl 拉低,让 sda 做好数据准备

sda = dataSend & 0x80; // SDA 获得数据最高位 1000 000

nop(); // 发送数据建立准备时间

scl=1; // scl 拉高开始发送

nop(); // 数据发送时间

scl=0; // 发送完毕就拉低

nop(); //

dataSend <<= 1; //左移一位,让次高位切换为 最高位,下一次就轮到他的

}

}

void Oled_Write_Cmd(char dataCmd)

{

//1.start()

IIC_Start();

//2.写入 0x78 -- 从机地址

IIC_Send_Byte(0x78);

//3.ACK

IIC_ACK();

//4.control byte: (0)(0)000000 -- 写入命令 (0)(1)000000 -- 写入数据

IIC_Send_Byte(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();

//2.写入 0x78 -- 从机地址

IIC_Send_Byte(0x78);

//3.ACK

IIC_ACK();

//4.control byte: (0)(0)000000 -- 写入命令 (0)(1)000000 -- 写入数据

IIC_Send_Byte(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);

Oled_Write_Cmd(0x00);

Oled_Write_Cmd(0x10);

Oled_Write_Cmd(0x40);

Oled_Write_Cmd(0xb0);

Oled_Write_Cmd(0x81);

Oled_Write_Cmd(0xff);

Oled_Write_Cmd(0xa1);

Oled_Write_Cmd(0xa6);

Oled_Write_Cmd(0xa8);

Oled_Write_Cmd(0x3f);

Oled_Write_Cmd(0xc8);

Oled_Write_Cmd(0xd3);

Oled_Write_Cmd(0x00);

Oled_Write_Cmd(0xd5);

Oled_Write_Cmd(0x80);

Oled_Write_Cmd(0xd8);

Oled_Write_Cmd(0x05);

Oled_Write_Cmd(0xd9);

Oled_Write_Cmd(0xf1);

Oled_Write_Cmd(0xda);

Oled_Write_Cmd(0x12);

Oled_Write_Cmd(0xdb);

Oled_Write_Cmd(0x30);

Oled_Write_Cmd(0x8d);

Oled_Write_Cmd(0x14);

Oled_Write_Cmd(0xaf);

}

void Oled_Clear()

{

int i;

int j;

for(i-0;i<8;++i){

//行 page0 ~ page7

Oled_Write_Cmd(0xB0+i);

//每个page 从0列 开始

Oled_Write_Cmd(0x00);

Oled_Write_Cmd(0x10);

//列 0 ~ 127 ,一次写入0 -- 默认情况下,每次写入数据,列地址自动偏移

for(j=0;j<128;++j){

Oled_Write_Data(0); //遍历完所有位置,实现清零

}

}

}

/*-- 文字: A --*/

/*-- 宋体12; 此字体下对应的点阵为:宽x高=8x16 --*/

//0x00,0x00,0xC0,0x38,0xE0,0x00,0x00,0x00,0x20,0x3C,0x23,0x02,0x02,0x27,0x38,0x20,

char A1[8]={0x00,0x00,0xC0,0x38,0xE0,0x00,0x00,0x00};

char A2[8]={0x20,0x3C,0x23,0x02,0x02,0x27,0x38,0x20};

void main()

{

int i;

//1. oled 初始化

Oled_Init();

// 2. 选择一个位置

//2.1确认页寻址模式:

Oled_Write_Cmd(0x20);

Oled_Write_Cmd(0x02);

Oled_Clear();// 清屏

//2.2选择PAGEO -- 1011 0000 -- 0xB0

Oled_Write_Cmd(0xB0); //选择 第一页

// 控制在第一列输出

Oled_Write_Cmd(0x00);

Oled_Write_Cmd(0x10);

for(i=0;i<8;++i){

Oled_Write_Data(A1[i]);

}

Oled_Write_Cmd(0xB1); //选择 第一页

// 控制在第一列输出

Oled_Write_Cmd(0x00);

Oled_Write_Cmd(0x10);

for(i=0;i<8;++i){

Oled_Write_Data(A2[i]);

}

while(1);

}

=====================

case 3 输出显示一行文字:

报错too large 装不下 -- 加code 前缀

code:

code用于声明存储在只读存储器中。code关键字通常与函数或程序的定义一起使用,也可以用来修饰常量,限制其只能存储在ROM中,从而节省了宝贵的RAM资源

#include "reg52.h"

#include "intrins.h"

sbit scl = P0^1;

sbit sda = P0^3;

void IIC_Start() //开始信号

{

scl=1;

sda=1;

nop();

sda=0;

nop();

}

void IIC_Stop()

{

sda=0;

scl=1;

nop();

sda=1;

nop();

}

char IIC_ACK()

{

char flag;

sda =1; // 就在时钟脉冲 9 期间释放数据线 -- 高电平

nop();

scl=1; // 高电平状态读取

nop();

flag = sda;

nop();

scl=0; //读完后scl变成低电平

nop();

return flag;

}

void IIC_Send_Byte(char dataSend)

{

int i;

for(i=0;i<8;++i){

scl = 0; // scl 拉低,让 sda 做好数据准备

sda = dataSend & 0x80; // SDA 获得数据最高位 1000 000

nop(); // 发送数据建立准备时间

scl=1; // scl 拉高开始发送

nop(); // 数据发送时间

scl=0; // 发送完毕就拉低

nop(); //

dataSend <<= 1; //左移一位,让次高位切换为 最高位,下一次就轮到他的

}

}

void Oled_Write_Cmd(char dataCmd)

{

//1.start()

IIC_Start();

//2.写入 0x78 -- 从机地址

IIC_Send_Byte(0x78);

//3.ACK

IIC_ACK();

//4.control byte: (0)(0)000000 -- 写入命令 (0)(1)000000 -- 写入数据

IIC_Send_Byte(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();

//2.写入 0x78 -- 从机地址

IIC_Send_Byte(0x78);

//3.ACK

IIC_ACK();

//4.control byte: (0)(0)000000 -- 写入命令 (0)(1)000000 -- 写入数据

IIC_Send_Byte(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);

Oled_Write_Cmd(0x00);

Oled_Write_Cmd(0x10);

Oled_Write_Cmd(0x40);

Oled_Write_Cmd(0xb0);

Oled_Write_Cmd(0x81);

Oled_Write_Cmd(0xff);

Oled_Write_Cmd(0xa1);

Oled_Write_Cmd(0xa6);

Oled_Write_Cmd(0xa8);

Oled_Write_Cmd(0x3f);

Oled_Write_Cmd(0xc8);

Oled_Write_Cmd(0xd3);

Oled_Write_Cmd(0x00);

Oled_Write_Cmd(0xd5);

Oled_Write_Cmd(0x80);

Oled_Write_Cmd(0xd8);

Oled_Write_Cmd(0x05);

Oled_Write_Cmd(0xd9);

Oled_Write_Cmd(0xf1);

Oled_Write_Cmd(0xda);

Oled_Write_Cmd(0x12);

Oled_Write_Cmd(0xdb);

Oled_Write_Cmd(0x30);

Oled_Write_Cmd(0x8d);

Oled_Write_Cmd(0x14);

Oled_Write_Cmd(0xaf);

}

void Oled_Clear()

{

int i;

int j;

for(i-0;i<8;++i){

//行 page0 ~ page7

Oled_Write_Cmd(0xB0+i);

//每个page 从0列 开始

Oled_Write_Cmd(0x00);

Oled_Write_Cmd(0x10);

//列 0 ~ 127 ,一次写入0 -- 默认情况下,每次写入数据,列地址自动偏移

for(j=0;j<128;++j){

Oled_Write_Data(0); //遍历完所有位置,实现清零

}

}

}

/*-- 文字: 梦 --*/

/*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/

code char m1[16]={0x40,0x44,0x24,0x14,0x7F,0x94,0x24,0x00,0x24,0x14,0x7F,0x14,0x24,0x44,0x40,0x00};

code char m2[16]={0x00,0x80,0x88,0x84,0x42,0x45,0x29,0x11,0x11,0x09,0x05,0x03,0x00,0x00,0x00,0x00};

/*-- 文字: 想 --*/

/*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/

code char x1[16]={0x00,0x08,0x88,0x68,0xFF,0x48,0x88,0x00,0xFE,0x52,0x52,0x52,0xFE,0x00,0x00,0x00};

code char x2[16]={0x40,0x31,0x00,0x00,0x3B,0x40,0x40,0x44,0x5B,0x42,0x42,0x72,0x03,0x08,0x30,0x00};

/*-- 文字: 菌 --*/

/*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/

code char j1[16]= {0x02,0x02,0xF2,0x12,0x17,0x92,0x92,0x92,0x52,0x52,0x17,0x12,0xF2,0x02,0x02,0x00};

code char j2[16] ={0x00,0x00,0xFF,0x40,0x52,0x4A,0x46,0x7F,0x46,0x4A,0x52,0x40,0xFF,0x00,0x00,0x00};

/*-- 文字: 加 --*/

/*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/

code char jia1[16] ={0x10,0x10,0x10,0xFF,0x10,0x10,0xF0,0x00,0x00,0xF8,0x08,0x08,0x08,0xF8,0x00,0x00};

code char jia2[16]={0x80,0x40,0x30,0x0F,0x40,0x80,0x7F,0x00,0x00,0x7F,0x20,0x20,0x20,0x7F,0x00,0x00};

/*-- 文字: 油 --*/

/*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/

code char y1[16]={0x10,0x60,0x02,0x8C,0x00,0xF0,0x10,0x10,0x10,0xFF,0x10,0x10,0x10,0xF0,0x00,0x00};

code char y2[16]={0x04,0x04,0x7E,0x01,0x00,0xFF,0x42,0x42,0x42,0x7F,0x42,0x42,0x42,0xFF,0x00,0x00};

void main()

{

unsigned int i;

//1. oled 初始化

Oled_Init();

// 2. 选择一个位置

//2.1确认页寻址模式:

Oled_Write_Cmd(0x20);

Oled_Write_Cmd(0x02);

Oled_Clear();// 清屏

//2.2选择PAGEO -- 1011 0000 -- 0xB0

Oled_Write_Cmd(0xB0); //选择 第一页

// 控制在第一列输出

Oled_Write_Cmd(0x00);

Oled_Write_Cmd(0x10);

for(i=0;i<16;++i){

Oled_Write_Data(m1[i]);

}

for(i=0;i<16;++i){

Oled_Write_Data(x1[i]);

}

for(i=0;i<16;++i){

Oled_Write_Data(j1[i]);

}

for(i=0;i<16;++i){

Oled_Write_Data(jia1[i]);

}

for(i=0;i<16;++i){

Oled_Write_Data(y1[i]);

}

Oled_Write_Cmd(0xB1); //选择 第一页

// 控制在第一列输出

Oled_Write_Cmd(0x00);

Oled_Write_Cmd(0x10);

for(i=0;i<16;++i){

Oled_Write_Data(m2[i]);

}

for(i=0;i<16;++i){

Oled_Write_Data(x2[i]);

}

for(i=0;i<16;++i){

Oled_Write_Data(j2[i]);

}

for(i=0;i<16;++i){

Oled_Write_Data(jia2[i]);

}

for(i=0;i<16;++i){

Oled_Write_Data(y2[i]);

}

while(1);

}

===========================================

case4 oled 显示图片: 128 × 64

=============

#include "reg52.h"

#include "intrins.h"

sbit scl = P0^1;

sbit sda = P0^3;

void IIC_Start() //开始信号

{

scl=1;

sda=1;

nop();

sda=0;

nop();

}

void IIC_Stop()

{

sda=0;

scl=1;

nop();

sda=1;

nop();

}

char IIC_ACK()

{

char flag;

sda =1; // 就在时钟脉冲 9 期间释放数据线 -- 高电平

nop();

scl=1; // 高电平状态读取

nop();

flag = sda;

nop();

scl=0; //读完后scl变成低电平

nop();

return flag;

}

void IIC_Send_Byte(char dataSend)

{

int i;

for(i=0;i<8;++i){

scl = 0; // scl 拉低,让 sda 做好数据准备

sda = dataSend & 0x80; // SDA 获得数据最高位 1000 000

nop(); // 发送数据建立准备时间

scl=1; // scl 拉高开始发送

nop(); // 数据发送时间

scl=0; // 发送完毕就拉低

nop(); //

dataSend <<= 1; //左移一位,让次高位切换为 最高位,下一次就轮到他的

}

}

void Oled_Write_Cmd(char dataCmd)

{

//1.start()

IIC_Start();

//2.写入 0x78 -- 从机地址

IIC_Send_Byte(0x78);

//3.ACK

IIC_ACK();

//4.control byte: (0)(0)000000 -- 写入命令 (0)(1)000000 -- 写入数据

IIC_Send_Byte(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();

//2.写入 0x78 -- 从机地址

IIC_Send_Byte(0x78);

//3.ACK

IIC_ACK();

//4.control byte: (0)(0)000000 -- 写入命令 (0)(1)000000 -- 写入数据

IIC_Send_Byte(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);

Oled_Write_Cmd(0x00);

Oled_Write_Cmd(0x10);

Oled_Write_Cmd(0x40);

Oled_Write_Cmd(0xb0);

Oled_Write_Cmd(0x81);

Oled_Write_Cmd(0xff);

Oled_Write_Cmd(0xa1);

Oled_Write_Cmd(0xa6);

Oled_Write_Cmd(0xa8);

Oled_Write_Cmd(0x3f);

Oled_Write_Cmd(0xc8);

Oled_Write_Cmd(0xd3);

Oled_Write_Cmd(0x00);

Oled_Write_Cmd(0xd5);

Oled_Write_Cmd(0x80);

Oled_Write_Cmd(0xd8);

Oled_Write_Cmd(0x05);

Oled_Write_Cmd(0xd9);

Oled_Write_Cmd(0xf1);

Oled_Write_Cmd(0xda);

Oled_Write_Cmd(0x12);

Oled_Write_Cmd(0xdb);

Oled_Write_Cmd(0x30);

Oled_Write_Cmd(0x8d);

Oled_Write_Cmd(0x14);

Oled_Write_Cmd(0xaf);

}

code unsigned char bmpImager[]={

/*-- µ÷ÈëÁËÒ>>·ùͼÏñ£ºC:\Users\31472\Desktop\mxjspng.bmp --*/

/*-- ¿í¶Èx¸ß¶È=128x64 --*/

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,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,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,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,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,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xE0,0xE0,0xE0,0xC0,0x80,0x00,0x00,0x00,

0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xC0,0xC0,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,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,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,0x00,0x00,0x00,0x00,0x00,0x00,

0x00,0x00,0x00,0x00,0x80,0xFC,0xFF,0x7F,0x07,0x01,0x03,0x0F,0x3F,0xFE,0xF8,0xE0,

0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xE0,0xF8,0xFF,0x3F,0x0F,0x0F,0x7F,0xFE,

0xF8,0xC0,0x00,0x80,0x80,0xC0,0xE0,0xE0,0xF0,0x78,0x38,0x3E,0x1F,0x0F,0x07,0x07,

0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x1F,0xFF,0xFF,0xF3,0x03,

0x01,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,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,0x00,0x00,0x00,0x00,0x00,

0x00,0x80,0xE0,0xF8,0xFF,0x3F,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x0F,0xFF,

0xFF,0xF8,0x80,0xE0,0xF0,0xFC,0x3E,0x1F,0x07,0x03,0x80,0xC0,0xC0,0xE0,0xF8,0x7D,

0x3F,0x1F,0x3F,0xFF,0xF3,0xE3,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0xFF,0xFF,0xC0,

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,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,0x00,0x00,0x00,0x00,0x00,0x78,

0xFE,0x7F,0x0F,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

0x07,0x0F,0x1F,0x0F,0x01,0x00,0x00,0x00,0x00,0x03,0x07,0x07,0x07,0x03,0x00,0x00,

0x00,0x00,0x00,0x03,0x07,0x07,0x07,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0xFF,0xFF,0x03,

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,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,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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xFC,0xFF,0x3F,0x07,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,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,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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x07,0x0F,0x1E,0x3C,0x78,0xF0,0xE0,0xC0,

0xC0,0x80,0x80,0xC0,0xC0,0xE0,0xF0,0x70,0x3C,0x3E,0x1F,0x07,0x01,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,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,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,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,0x01,0x01,

0x03,0x03,0x03,0x03,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,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,0x00,0x00,0x00,0x00,0x00,0x00,

};

void Oled_Show_Image(unsigned char *image)

{

unsigned char i;

unsigned int j;

for(i-0;i<8;++i){

//行 page0 ~ page7

Oled_Write_Cmd(0xB0+i);

//每个page 从0列 开始

Oled_Write_Cmd(0x00);

Oled_Write_Cmd(0x10);

//列 0 ~ 127 ,一次写入0 -- 默认情况下,每次写入数据,列地址自动偏移

for(j=128*i;j<(128*(i+1));++j){

Oled_Write_Data(image[j]); //遍历完所有位置,实现清零

}

}

}

void main()

{

//1. oled 初始化

Oled_Init();

// 2. 选择一个位置

//2.1确认页寻址模式:

Oled_Write_Cmd(0x20);

Oled_Write_Cmd(0x02);

Oled_Show_Image(bmpImager);

while(1);

}

相关推荐
代码游侠15 小时前
学习笔记——设备树基础
linux·运维·开发语言·单片机·算法
CODECOLLECT18 小时前
京元 I62D Windows PDA 技术拆解:Windows 10 IoT 兼容 + 硬解码模块,如何降低工业软件迁移成本?
stm32·单片机·嵌入式硬件
BackCatK Chen19 小时前
STM32+FreeRTOS:嵌入式开发的黄金搭档,未来十年就靠它了!
stm32·单片机·嵌入式硬件·freertos·低功耗·rtdbs·工业控制
全栈游侠1 天前
STM32F103XX 02-电源与备份寄存器
stm32·单片机·嵌入式硬件
Lsir10110_1 天前
【Linux】中断 —— 操作系统的运行基石
linux·运维·嵌入式硬件
深圳市九鼎创展科技1 天前
瑞芯微 RK3399 开发板 X3399 评测:高性能 ARM 平台的多面手
linux·arm开发·人工智能·单片机·嵌入式硬件·边缘计算
辰哥单片机设计1 天前
STM32项目分享:车辆防盗报警系统
stm32·单片机·嵌入式硬件
小龙报1 天前
【51单片机】从 0 到 1 玩转 51 蜂鸣器:分清有源无源,轻松驱动它奏响新年旋律
c语言·数据结构·c++·stm32·单片机·嵌入式硬件·51单片机
范纹杉想快点毕业1 天前
嵌入式与单片机开发核心学习指南——从思维转变到第一性原理的深度实践
单片机·嵌入式硬件
Industio_触觉智能1 天前
瑞芯微RK3566开发板规格书,详细参数配置,型号EVB3566-V1,基于RK3566核心板SOM3566邮票孔封装
嵌入式硬件·开发板·rk3568·rk3566·核心板·瑞芯微