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

}

相关推荐
楼台的春风1 小时前
【MCU驱动开发概述】
c语言·驱动开发·单片机·嵌入式硬件·mcu·自动驾驶·嵌入式
Moonnnn.1 小时前
51单片机学习——动态数码管显示
笔记·嵌入式硬件·学习·51单片机
LS_learner2 小时前
小智机器人CMakeLists编译文件解析
嵌入式硬件·机器人
暗碳3 小时前
stm32 74hc238流水灯
stm32·单片机·嵌入式硬件
1101 11013 小时前
STM32-温湿度上传OneNET项目
stm32·单片机·嵌入式硬件
余衫马4 小时前
ESP32-S3 实战指南:BOOT-KEY 按键驱动开发全解析
驱动开发·单片机·嵌入式硬件
文军的烹饪实验室7 小时前
处理器架构、单片机、芯片、光刻机之间的关系
单片机·嵌入式硬件·架构
Leiditech__8 小时前
人工智能时代电子机器人静电问题及电路设计防范措施
人工智能·嵌入式硬件·机器人·硬件工程
jmlinux8 小时前
STM32 HAL库USART串口DMA IDLE中断编程:避坑指南
stm32·单片机·嵌入式硬件
沐欣工作室_lvyiyi10 小时前
基于单片机的智能电表设计(论文+源码)
单片机·嵌入式硬件·电能表·数字电能表