Oled显示一个字符(用IIC协议)

一.了解IIC协议

1.IIC的了解
IIC 总线在传输数据的过程中一共有三种类型信号,分别为:开始信号、结束信号和应答信号。
开始信号                                                                                        结束信号
应答信号
发送器每发送一个字节(8 bit ),就在时钟脉冲 9 期间释放数据线,由接收器反馈一个应答信号。
应答信号为低电平时,规定为有效应答位( ACK ,简称应答位),表示接收器已经成功地接收了该字
节;
应答信号为高电平时,规定为非应答位( NACK ),一般表示接收器接收该字节没有成功。
更多关于IIC内容,可以查看相应的资料.
2.代码初成
先根据上面的开始信号,结束信号,应答信号的时序图写代码,如下:

#include <reg52.h>
#include <intrins.h>

sbit sda=P0^3;
sbit scl=P0^1;

void IIC_Start()
{
  scl=0;
  sda=1;
  scl=1;
  _nop_();
  sda=0;
  _nop_();
}

void IIC_Stop()
{
  scl=0;
  sda=0;
  scl=1;
  _nop_();
  sda=1;
  _nop_();

}

//数据翻转是在SCL为低电平的时候,可以观察上面的时序图

char IIC_ACK()
{
  char flag;
  sda=1;
  _nop_();
  scl=1;
  _nop_();
  flag=sda;
  _nop_();
  scl=0;
  _nop_();
  return flag;
}

void IIC_Send_Byte(char datas)
{
  int i;
  for(i=0;i<8;i++) {
  scl=0;//scl拉低,让sda做好数据准备
  sda=datas & 0x80;//1000 0000 让sda等于datas的高位
  _nop_(); //发送数据建立时间
  scl=1;   //scl拉高开始发送
  _nop_(); //数据发送时间
  scl=0;   //发送完毕,scl拉低
  _nop_();
  datas= datas <<1;     //左移一位,
  }
}

二.OLED写命令

下面是IIC总线数据格式

从图中的s开始写,步骤如下:

a.start()

b.写入slave Adress(通过查询手册,可知地址为b0111 1000  ==0x78)

c.ACK(有效应答位)

d.写Control Byte:(0)(0)00 0000写入命令,(0)(1)00 0000写入数据

如果Co位被设置为逻辑“0”,则以下信息的传输将只包含数据字节。

如果D/C#位设置为逻辑“0”,则会将以下数据字节定义为命令。如果D/C#位被设置为逻辑“1”,那么它会将以下数据字节定义为将存储在GDDRAM中的数据。每次写入数据后,GDDRAM列地址指针将自动增加一个。

e.ACK

f.stop

例如下面的代码:

//这是写入命令的代码
void Oled_Write_Cmd(char dataCmd)
{
// 1. start()
IIC_Start();
//
// 2. 写入从机地址 b0111 1000 0x78
IIC_Send_Byte(0x78);
// 3. ACK
IIC_ACK();
// 4. cotrol 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. 写入从机地址 b0111 1000 0x78
IIC_Send_Byte(0x78);
// 3. ACK
IIC_ACK();
// 4. cotrol byte: (0)(0)000000 写入命令 (0)(1)000000写入数据
IIC_Send_Byte(0x00);
// 5. ACK
IIC_ACK();
///6. 写入指令/数据
IIC_Send_Byte(dataData);
//7. ACK
IIC_ACK();
//8. STOP
IIC_Stop();
}

做好了上面关于oled的iic协议的代码之后,就可以着手OLED的寻址模式,行地址选择,列地址选择,之后可以用oled发送一个点,一个字符,一行字符以及一个图片。

3.OLED的寻址模式

寻址模式有三种:页地址模式,水平地址模式和垂直地址模式。

这里用的是页地址模式。

页地址模式

在页寻址模式下,读写显示RAM后,列地址指针自动增加1。如果列地址指针到达列结束地址,则列地址指针将被重置为列起始地址,而页地址指针将不会被更改。用户必须设置新的页面和列地址,才能访问下一页的RAM内容。页寻址模式的PAGE和列地址点的移动顺序如下图。

此OLED为8行,128列。

水平地址模式

垂直地址模式

在OLED电子说明书中查找Page Adressing,找到这个图,看到页地址模式(红色部分为页地址模式,得到后两位为10,即0x20,0x02为页地址模式)

在这里找到PAGE0的命令表,看图得PAGE0为0xB0。

下面是OLED的行和列的布局。一个PAGE有8位,有8个PAGE,然后有128列。

行做好之后,开始做列的。有128列,分高8位和低8位。从图中可知第0列为0x10和0x00。

一个字节(8bit)负责一个Page的一列显示。

发送0x08,显示一个点。即Oled_Write_Cmd(0x08);

清屏函数(防止雪花)

因为在使用OLED显示屏时,由于其像素点数量较多,如果不及时清除屏幕上的内容,会导致显示效果不佳,影响用户体验。因此,OLED清屏函数就成为了必不可少的部分。

void Oled_Clear()
{
 int i,j;
 for(i=0;i<8;i++) {
  Oled_Write_Cmd(0xB0+i);
  Oled_Write_Cmd(0x00);
  Oled_Write_Cmd(0x10);
  for(j=0;j<128;j++) {
  Oled_Write_data(0);

   }
 }
}

三.用OLED显示一个点,一个字符以及一个图片的代码

1.下面是显示一个点的代码

#include <reg52.h>
#include <intrins.h>

sbit sda=P0^3;
sbit scl=P0^1;

void IIC_Start()
{
  scl=0;
  sda=1;
  scl=1;
  _nop_();
  sda=0;
  _nop_();
}

void IIC_Stop()
{
  scl=0;
  sda=0;
  scl=1;
  _nop_();
  sda=1;
  _nop_();

}

void IIC_Send_Byte(char datas)
{
  int i;
  for(i=0;i<8;i++) {
  scl=0;//scl拉低,让sda做好数据准备
  sda=datas & 0x80;//1000 0000 让sda等于datas的高位
  _nop_(); //发送数据建立时间
  scl=1;   //scl拉高开始发送
  _nop_(); //数据发送时间
  scl=0;   //发送完毕,scl拉低
  _nop_();
  datas= datas <<1;	 //左移一位,
  }
}

char IIC_ACK()
{
  char flag;
  sda=1;
  _nop_();
  scl=1;
  _nop_();
  flag=sda;
  _nop_();
  scl=0;
  _nop_();
  return flag;
}

void  Oled_Write_data(char dataDATA)
{
  //1.起始
  IIC_Start();
  //2.写入从机地址,b0111 1000 亦0x78;
  IIC_Send_Byte(0x78);
  //3.ACK
  IIC_ACK();
  //4.control Byte    写入命令是(0)(0)00 0000 ,写入数据是(0)(1)00 0000
  IIC_Send_Byte(0x40);
  //5.ACK
  IIC_ACK();
  //6.data Byte
  IIC_Send_Byte(dataDATA);
  //7.ACK
  IIC_ACK();
  //8.终止
  IIC_Stop();
}

void  Oled_Write_Cmd(char dataCMD)
{
  //1.起始
  IIC_Start();
  //2.写入从机地址,b0111 1000 亦0x78;
  IIC_Send_Byte(0x78);
  //3.ACK
  IIC_ACK();
  //4.control Byte    写入命令是(0)(0)00 0000 ,写入数据是(0)(1)00 0000
  IIC_Send_Byte(0x00);
  //5.ACK
  IIC_ACK();
  //6.data Byte
  IIC_Send_Byte(dataCMD);
  //7.ACK
  IIC_ACK();
  //8.终止
  IIC_Stop();
}

void init_OLED(void)
{
//01.display off (0xae)
Oled_Write_Cmd(0xAE);
//02.set low column address (0x00)
Oled_Write_Cmd(0x00);
//03.set high column address (0x10)
Oled_Write_Cmd(0x10);
//04.set start line address (0x40)
Oled_Write_Cmd(0x40);
//05.set page address (0xb0)
Oled_Write_Cmd(0xB0);
//06.contract control (0x81)
Oled_Write_Cmd(0x81);
//07.send 0xff (多字节指令)
Oled_Write_Cmd(0xFF);
//08.set segment remap (0xa1)
Oled_Write_Cmd(0xA1);
//09.set normal/reverse (0xa6)
Oled_Write_Cmd(0xA6);
//10.set multiplex ratio (1 to 64) (0xa8 )
Oled_Write_Cmd(0xA8);
//11.set duty 1/32 (0x3f)
Oled_Write_Cmd(0x3F);
//12.com scan direction (0xc8)
Oled_Write_Cmd(0xC8);
//13.set display offset (0xd3)
Oled_Write_Cmd(0xD3);
//14.send 0x00 
Oled_Write_Cmd(0x00);
//15.set osc division (0xd5)
Oled_Write_Cmd(0xD5);
//16.send 0x80
Oled_Write_Cmd(0x80);
//17.set area color mode off (0xd8)
Oled_Write_Cmd(0xD8);
//18.send 0x05
Oled_Write_Cmd(0x05);
//19.set pre-charge period (0xd9)
Oled_Write_Cmd(0xD9);
//20.send 0xf1
Oled_Write_Cmd(0xF1);
//21.set com pin configuration (0xda)
Oled_Write_Cmd(0xDA);
//22.send 0x12
Oled_Write_Cmd(0x12);
//23.set Vcomh (0xdb)
Oled_Write_Cmd(0xDB);
//24.send 0x30
Oled_Write_Cmd(0x30);
//25.set charge pump enable (0x8d)
Oled_Write_Cmd(0x8D);
//26.send 0x14
Oled_Write_Cmd(0x14);
//27.turn on oled panel(0xaf)
Oled_Write_Cmd(0xAF);
}

void Oled_Clear()
{
 int i,j;
 for(i=0;i<8;i++) {
  Oled_Write_Cmd(0xB0+i);
  Oled_Write_Cmd(0x00);
  Oled_Write_Cmd(0x10);
  for(j=0;j<128;j++) {
  Oled_Write_data(0);

   }
 }
}

void main()
{
  //1.OLED初始化
  init_OLED();
  //清屏函数(防止上一次数据遗留下来,造成显示错误)
  Oled_Clear();
  //2.1选择页寻址模式
  Oled_Write_Cmd(0x20);
  Oled_Write_Cmd(0x02);
  //2.2 选择PAGE0  1011 0000 亦0xB0,在手册上找page0~7的寻址设置命令表,如1011 0xxx
  Oled_Write_Cmd(0xB0);
  Oled_Write_Cmd(0x00);
  Oled_Write_Cmd(0x10);
  //3.显示一个点
  Oled_Write_data(0x08);

  while(1);  //防止程序退出
}

2.显示一个字符

#include <reg52.h>
#include <intrins.h>

sbit sda=P0^3;
sbit scl=P0^1;

void IIC_Start()
{
  scl=0;
  sda=1;
  scl=1;
  _nop_();
  sda=0;
  _nop_();
}

void IIC_Stop()
{
  scl=0;
  sda=0;
  scl=1;
  _nop_();
  sda=1;
  _nop_();

}

void IIC_Send_Byte(char datas)
{
  int i;
  for(i=0;i<8;i++) {
  scl=0;//scl拉低,让sda做好数据准备
  sda=datas & 0x80;//1000 0000 让sda等于datas的高位
  _nop_(); //发送数据建立时间
  scl=1;   //scl拉高开始发送
  _nop_(); //数据发送时间
  scl=0;   //发送完毕,scl拉低
  _nop_();
  datas= datas <<1;	 //左移一位,
  }
}

char IIC_ACK()
{
  char flag;
  sda=1;
  _nop_();
  scl=1;
  _nop_();
  flag=sda;
  _nop_();
  scl=0;
  _nop_();
  return flag;
}

void  Oled_Write_data(char dataDATA)
{
  //1.起始
  IIC_Start();
  //2.写入从机地址,b0111 1000 亦0x78;
  IIC_Send_Byte(0x78);
  //3.ACK
  IIC_ACK();
  //4.control Byte    写入命令是(0)(0)00 0000 ,写入数据是(0)(1)00 0000
  IIC_Send_Byte(0x40);
  //5.ACK
  IIC_ACK();
  //6.data Byte
  IIC_Send_Byte(dataDATA);
  //7.ACK
  IIC_ACK();
  //8.终止
  IIC_Stop();
}

void  Oled_Write_Cmd(char dataCMD)
{
  //1.起始
  IIC_Start();
  //2.写入从机地址,b0111 1000 亦0x78;
  IIC_Send_Byte(0x78);
  //3.ACK
  IIC_ACK();
  //4.control Byte    写入命令是(0)(0)00 0000 ,写入数据是(0)(1)00 0000
  IIC_Send_Byte(0x00);
  //5.ACK
  IIC_ACK();
  //6.data Byte
  IIC_Send_Byte(dataCMD);
  //7.ACK
  IIC_ACK();
  //8.终止
  IIC_Stop();
}

void init_OLED(void)
{
//01.display off (0xae)
Oled_Write_Cmd(0xAE);
//02.set low column address (0x00)
Oled_Write_Cmd(0x00);
//03.set high column address (0x10)
Oled_Write_Cmd(0x10);
//04.set start line address (0x40)
Oled_Write_Cmd(0x40);
//05.set page address (0xb0)
Oled_Write_Cmd(0xB0);
//06.contract control (0x81)
Oled_Write_Cmd(0x81);
//07.send 0xff (多字节指令)
Oled_Write_Cmd(0xFF);
//08.set segment remap (0xa1)
Oled_Write_Cmd(0xA1);
//09.set normal/reverse (0xa6)
Oled_Write_Cmd(0xA6);
//10.set multiplex ratio (1 to 64) (0xa8 )
Oled_Write_Cmd(0xA8);
//11.set duty 1/32 (0x3f)
Oled_Write_Cmd(0x3F);
//12.com scan direction (0xc8)
Oled_Write_Cmd(0xC8);
//13.set display offset (0xd3)
Oled_Write_Cmd(0xD3);
//14.send 0x00 
Oled_Write_Cmd(0x00);
//15.set osc division (0xd5)
Oled_Write_Cmd(0xD5);
//16.send 0x80
Oled_Write_Cmd(0x80);
//17.set area color mode off (0xd8)
Oled_Write_Cmd(0xD8);
//18.send 0x05
Oled_Write_Cmd(0x05);
//19.set pre-charge period (0xd9)
Oled_Write_Cmd(0xD9);
//20.send 0xf1
Oled_Write_Cmd(0xF1);
//21.set com pin configuration (0xda)
Oled_Write_Cmd(0xDA);
//22.send 0x12
Oled_Write_Cmd(0x12);
//23.set Vcomh (0xdb)
Oled_Write_Cmd(0xDB);
//24.send 0x30
Oled_Write_Cmd(0x30);
//25.set charge pump enable (0x8d)
Oled_Write_Cmd(0x8D);
//26.send 0x14
Oled_Write_Cmd(0x14);
//27.turn on oled panel(0xaf)
Oled_Write_Cmd(0xAF);
}

void Oled_Clear()
{
 int i,j;
 for(i=0;i<8;i++) {
  Oled_Write_Cmd(0xB0+i);
  Oled_Write_Cmd(0x00);
  Oled_Write_Cmd(0x10);
  for(j=0;j<128;j++) {
  Oled_Write_data(0);

   }
 }
}

/*--  文字:  H  --*/
/*--  宋体12;  此字体下对应的点阵为:宽x高=8x16   --*/
/*0x08,0xF8,0x08,0x00,0x00,0x08,0xF8,0x08
  0x20,0x3F,0x21,0x01,0x01,0x21,0x3F,0x20*/

void main()
{
   int i;
   char A1[8]={0x08,0xF8,0x08,0x00,0x00,0x08,0xF8,0x08};
   char A2[8]={0x20,0x3F,0x21,0x01,0x01,0x21,0x3F,0x20};	
  //1.OLED初始化
  init_OLED();
  Oled_Clear();
  //2.选择一个位置
  //2.1选择页寻址模式
  Oled_Write_Cmd(0x20);
  Oled_Write_Cmd(0x02);
  //2.2 选择PAGE0  1011 0000 亦0xB0,在手册上找page0~7的寻址设置命令表,如1011 0xxx
  //3.显示一个字符
  //上半部分
  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);  //防止程序退出
}

3.显示一个图片

#include <reg52.h>
#include <intrins.h>

sbit sda=P0^3;
sbit scl=P0^1;

void IIC_Start()
{
  scl=0;
  sda=1;
  scl=1;
  _nop_();
  sda=0;
  _nop_();
}

void IIC_Stop()
{
  scl=0;
  sda=0;
  scl=1;
  _nop_();
  sda=1;
  _nop_();

}

void IIC_Send_Byte(char datas)
{
  int i;
  for(i=0;i<8;i++) {
  scl=0;//scl拉低,让sda做好数据准备
  sda=datas & 0x80;//1000 0000 让sda等于datas的高位
  _nop_(); //发送数据建立时间
  scl=1;   //scl拉高开始发送
  _nop_(); //数据发送时间
  scl=0;   //发送完毕,scl拉低
  _nop_();
  datas= datas <<1;	 //左移一位,
  }
}

char IIC_ACK()
{
  char flag;
  sda=1;
  _nop_();
  scl=1;
  _nop_();
  flag=sda;
  _nop_();
  scl=0;
  _nop_();
  return flag;
}

void  Oled_Write_data(char dataDATA)
{
  //1.起始
  IIC_Start();
  //2.写入从机地址,b0111 1000 亦0x78;
  IIC_Send_Byte(0x78);
  //3.ACK
  IIC_ACK();
  //4.control Byte    写入命令是(0)(0)00 0000 ,写入数据是(0)(1)00 0000
  IIC_Send_Byte(0x40);
  //5.ACK
  IIC_ACK();
  //6.data Byte
  IIC_Send_Byte(dataDATA);
  //7.ACK
  IIC_ACK();
  //8.终止
  IIC_Stop();
}

void  Oled_Write_Cmd(char dataCMD)
{
  //1.起始
  IIC_Start();
  //2.写入从机地址,b0111 1000 亦0x78;
  IIC_Send_Byte(0x78);
  //3.ACK
  IIC_ACK();
  //4.control Byte    写入命令是(0)(0)00 0000 ,写入数据是(0)(1)00 0000
  IIC_Send_Byte(0x00);
  //5.ACK
  IIC_ACK();
  //6.data Byte
  IIC_Send_Byte(dataCMD);
  //7.ACK
  IIC_ACK();
  //8.终止
  IIC_Stop();
}

void init_OLED(void)
{
//01.display off (0xae)
Oled_Write_Cmd(0xAE);
//02.set low column address (0x00)
Oled_Write_Cmd(0x00);
//03.set high column address (0x10)
Oled_Write_Cmd(0x10);
//04.set start line address (0x40)
Oled_Write_Cmd(0x40);
//05.set page address (0xb0)
Oled_Write_Cmd(0xB0);
//06.contract control (0x81)
Oled_Write_Cmd(0x81);
//07.send 0xff (多字节指令)
Oled_Write_Cmd(0xFF);
//08.set segment remap (0xa1)
Oled_Write_Cmd(0xA1);
//09.set normal/reverse (0xa6)
Oled_Write_Cmd(0xA6);
//10.set multiplex ratio (1 to 64) (0xa8 )
Oled_Write_Cmd(0xA8);
//11.set duty 1/32 (0x3f)
Oled_Write_Cmd(0x3F);
//12.com scan direction (0xc8)
Oled_Write_Cmd(0xC8);
//13.set display offset (0xd3)
Oled_Write_Cmd(0xD3);
//14.send 0x00 
Oled_Write_Cmd(0x00);
//15.set osc division (0xd5)
Oled_Write_Cmd(0xD5);
//16.send 0x80
Oled_Write_Cmd(0x80);
//17.set area color mode off (0xd8)
Oled_Write_Cmd(0xD8);
//18.send 0x05
Oled_Write_Cmd(0x05);
//19.set pre-charge period (0xd9)
Oled_Write_Cmd(0xD9);
//20.send 0xf1
Oled_Write_Cmd(0xF1);
//21.set com pin configuration (0xda)
Oled_Write_Cmd(0xDA);
//22.send 0x12
Oled_Write_Cmd(0x12);
//23.set Vcomh (0xdb)
Oled_Write_Cmd(0xDB);
//24.send 0x30
Oled_Write_Cmd(0x30);
//25.set charge pump enable (0x8d)
Oled_Write_Cmd(0x8D);
//26.send 0x14
Oled_Write_Cmd(0x14);
//27.turn on oled panel(0xaf)
Oled_Write_Cmd(0xAF);
}

void Oled_Clear()
{
 int i,j;
 for(i=0;i<8;i++) {
  Oled_Write_Cmd(0xB0+i);
  Oled_Write_Cmd(0x00);
  Oled_Write_Cmd(0x10);
  for(j=0;j<128;j++) {
  Oled_Write_data(0);

   }
 }
}
//这里是图片经过取模之后的参数
code unsigned char Bmp_Image[]={
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0xC0,0x60,0x30,0x18,0x0C,0xC4,0x44,0x44,0x44,0xC4,
0x04,0x84,0xC4,0x44,0xCC,0x08,0x08,0x18,0x10,0x10,0x30,0x20,0xA0,0xE0,0x60,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x40,0xC0,0xC0,0x00,0x00,0x70,0x40,0x68,0x38,0x00,0x00,0x18,0x3C,0x24,0x27,
0x33,0x1A,0x0E,0x00,0x00,0x0F,0x08,0x18,0x10,0x10,0x30,0x23,0x26,0x24,0x24,0x25,
0x27,0x33,0x12,0x1A,0x0F,0x04,0x06,0x02,0x02,0x03,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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x84,0xFE,0xFE,0xFC,0x70,0x70,0xFC,0xFE,0xFE,0x8C,0x00,
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,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x07,0x0F,0x1F,0x1D,0x1C,0x1C,0x1C,0x1F,0x1F,0x0F,0x0E,
0xCE,0xFE,0xFE,0xFE,0xFE,0x0E,0x0E,0x0E,0x0E,0x1E,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,
0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1E,0x1E,0x0E,0x1E,0x3C,0xFC,0xF8,0xE0,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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,
0x3F,0x7F,0x73,0x70,0x70,0xF0,0xF0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,
0xE0,0xF0,0xF0,0xF0,0xF0,0x70,0x70,0x70,0x70,0x70,0x78,0x7F,0x3F,0x1F,0x07,0x03,
0x47,0xFF,0xFE,0xFC,0xF0,0xF0,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0xC0,0xF0,0xFC,0xFE,0xFF,0x8F,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,
0xFC,0xFF,0xFF,0xCF,0x81,0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x36,0x77,0x77,0x36,
0x1C,0x00,0x80,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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x03,0x03,0x01,0x03,0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x03,
0x03,0x03,0x01,0x03,0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x07,0x0D,0x1D,0x1D,0x0D,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,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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++) {
  Oled_Write_Cmd(0xB0+i);
  Oled_Write_Cmd(0x00);
  Oled_Write_Cmd(0x10);
  for(j=128*i;j<128*(i+1);j++) {
  Oled_Write_data(image[j]);

   }
 }
}
void main()
{
  //1.OLED初始化
  init_OLED();
  //清屏函数
  Oled_Clear();
  //2.1选择页寻址模式
  Oled_Write_Cmd(0x20);
  Oled_Write_Cmd(0x02);

  Oled_Show_image(Bmp_Image);

  while(1);  //防止程序退出
}

这是要显示的图片,注意一定是像素为128*64的图片。

最终烧录出来的结果是:

四.点,字符与图片的代码区别及注意事项

1.显示一个字符的代码,要在取模软件中将想显示的字符取模,例如:H

是/*--  文字:  H  --*/
/*--  宋体12;  此字体下对应的点阵为:宽x高=8x16 --*/
0x08,0xF8,0x08,0x00,0x00,0x08,0xF8,0x08,  0x20,0x3F,0x21,0x01,0x01,0x21,0x3F,0x20,

高为16,而一个page为8位,所以要用到两行,将其分为上下两部分,上面为0xB0(page0),下面为0xB1(page1)。主要区别的代码如下:

   char A1[8]={0x08,0xF8,0x08,0x00,0x00,0x08,0xF8,0x08};
   char A2[8]={0x20,0x3F,0x21,0x01,0x01,0x21,0x3F,0x20};
//上半部分
  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]);
   }

2.显示一个图片的代码剖析

a.首先要用到像素为128*64的图片,不然oled用不了。然后进行取模,同样是在取模软件中将其得到的参数搞出来,如:128*64,可看成128*8*8,下面的数据刚好是128*64个。

/*--  宽度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,0x80,0xC0,0x60,0x30,0x18,0x0C,0xC4,0x44,0x44,0x44,0xC4,
0x04,0x84,0xC4,0x44,0xCC,0x08,0x08,0x18,0x10,0x10,0x30,0x20,0xA0,0xE0,0x60,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x40,0xC0,0xC0,0x00,0x00,0x70,0x40,0x68,0x38,0x00,0x00,0x18,0x3C,0x24,0x27,
0x33,0x1A,0x0E,0x00,0x00,0x0F,0x08,0x18,0x10,0x10,0x30,0x23,0x26,0x24,0x24,0x25,
0x27,0x33,0x12,0x1A,0x0F,0x04,0x06,0x02,0x02,0x03,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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x84,0xFE,0xFE,0xFC,0x70,0x70,0xFC,0xFE,0xFE,0x8C,0x00,
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,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x07,0x0F,0x1F,0x1D,0x1C,0x1C,0x1C,0x1F,0x1F,0x0F,0x0E,
0xCE,0xFE,0xFE,0xFE,0xFE,0x0E,0x0E,0x0E,0x0E,0x1E,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,
0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1E,0x1E,0x0E,0x1E,0x3C,0xFC,0xF8,0xE0,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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,
0x3F,0x7F,0x73,0x70,0x70,0xF0,0xF0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,
0xE0,0xF0,0xF0,0xF0,0xF0,0x70,0x70,0x70,0x70,0x70,0x78,0x7F,0x3F,0x1F,0x07,0x03,
0x47,0xFF,0xFE,0xFC,0xF0,0xF0,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0xC0,0xF0,0xFC,0xFE,0xFF,0x8F,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,
0xFC,0xFF,0xFF,0xCF,0x81,0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x36,0x77,0x77,0x36,
0x1C,0x00,0x80,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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x03,0x03,0x01,0x03,0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x03,
0x03,0x03,0x01,0x03,0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x07,0x0D,0x1D,0x1D,0x0D,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,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

然后对其放入一个数组。

b.封装一个函数,该函数和清屏函数相似,如:

void Oled_Show_image(unsigned char *image)
{
 unsigned char i;
 unsigned int j;
 for(i=0;i<8;i++) {
  Oled_Write_Cmd(0xB0+i);
  Oled_Write_Cmd(0x00);
  Oled_Write_Cmd(0x10);
  for(j=128*i;j<128*(i+1);j++) {
  Oled_Write_data(image[j]);

   }
 }
}

需要注意的是这里的j,不能用char,会出现数据溢出。第二个for中的,j要全部读取参数,就得设置成代码中的样子,不能是j=0;j<128;j++ 这种。因为要先数完第一行128个数据,接着数第二行...所以是128*i。

以上是个人学习的思路,第一次写文章,思路有点乱,望谅解。有什么补充的地方,希望大家可以提出。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值