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


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值