"OLED屏幕,色彩绚丽,画面清晰,让每一帧都生动无比。"#IIC协议【下】
- 前言
- 预备知识
- 1. OLED显示一个点代码实现
- 1.1 OLED显示一个点代码实现核心思路
- 1.2和LCD1602一样需要初始化,看手册,写初识化函数
- 1.3选择Page 0位置显示
- 1.4**发送0x08显示一个点**
- 1.5完整程序代码
- 2. OLED列地址
- 2.1 OLED列地址手册介绍
- 2.2代码体现
- 2.3完整程序代码(显示两条线)
- 2.4补充说明
- 3. OLED清屏添加清屏函数
- 3.1为什么需要清屏函数
- 3.2 OLED清屏添加清屏函数核心思想
- 3.3清屏函数代码
- 3.4完整程序代码
- 3.5补充说明
- 4. OLED显示字母A
- 4.1 OLED显示字母A核心思路
- 4.2使用液晶显示模块字模工具生成字符A的数据
- 4.3根据生成的字符A的数据建立字符数组
- 4.4使用for循环发送字符数据使OLED显示字符A
- 4.5完整程序代码
- 5. OLED显示中文
- 5.1 OLED显示中文核心思路
- 5.2使用液晶显示模块字模工具生成字符的数据
- 5.3根据生成字符的数据建立字符数组
- 5.4构造发送字符数据函数
- 5.4完整程序代码
- 6. OLED显示图片
- 6.1 OLED显示图片核心思路
- 6.2百度搜索简笔图片
- 6.3 FastStone Capture软件进行截图修改图片尺寸并保存为bmp格式
- 6.4使用液晶显示模块字模工具生成图片的数据
- 6.5根据生成图片的数据建立图片数组
- 6.6构造发送图片数据函数
- 6.7补充知识
- 6.8完整程序代码
- 结束语
前言
本篇博文介绍的是用51单片机的 IIC 协议【下】(OLED屏幕),包含OLED显示一个点代码实现,OLED列地址,OLED清屏添加清屏函数, OLED显示字母A,OLED显示中文,OLED显示图片。看到这篇博文的朋友,可以先赞再看吗?
预备知识
一、基本电路标识识别和接线,例如VCC,GND。
二、电脑基本操作复制粘贴
三、准备软件FastStone Capture,会简单操作(此软件需要的评论区评论)
四、数字电子时序图的识别
五、一点点专业英语积累
六、C变量
七、基本输入输出
八、流程控制
九、函数
十、指针
十一、字符串
如果以上知识不清楚,请自行学习后再来浏览。如果我有没例出的,请在评论区写一下。谢谢啦!
1. OLED显示一个点代码实现
1.1 OLED显示一个点代码实现核心思路
- 和LCD1602一样需要初始化,看手册,写初识化函数
- 选择Page 0位置显示
- 发送0x08显示一个点
注:本程序建立在OLED写入指令和数据
工程上
1.2和LCD1602一样需要初始化,看手册,写初识化函数
- 手册内容
OLED Initial
( 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)
- 初始化OLED屏幕函数代码
建立思路:根据手册内容调用OLED写指令函数发送对应指令
void initOLED()
{
//( 01) display off (0xae)
OledWriteCmd(0xae);
//( 02) set low column address (0x00)
OledWriteCmd(0x00);
//( 03) set high column address (0x10)
OledWriteCmd(0x10);
//( 04) set start line address (0x40)
OledWriteCmd(0x40);
//( 05) set page address (0xb0)
OledWriteCmd(0xb0);
//( 06) contract control (0x81)
OledWriteCmd(0x81);
//( 07) send 0xff (多字节指令)
OledWriteCmd(0xff);
//( 08) set segment remap (0xa1)
OledWriteCmd(0xa1);
//( 09) set normal/reverse (0xa6)
OledWriteCmd(0xa6);
//( 10) set multiplex ratio (1 to 64) (0xa8 )
OledWriteCmd(0xa8);
//( 11) set duty 1/32 (0x3f)
OledWriteCmd(0x3f);
//( 12) com scan direction (0xc8)
OledWriteCmd(0xc8);
//( 13) set display offset (0xd3)
OledWriteCmd(0xd3);
//( 14) send 0x00
OledWriteCmd(0x00);
//( 15) set osc division (0xd5)
OledWriteCmd(0xd5);
//( 16) send 0x80
OledWriteCmd(0x80);
//( 17) set area color mode off (0xd8)
OledWriteCmd(0xd8);
//( 18) send 0x05
OledWriteCmd(0x05);
//( 19) set pre-charge period (0xd9)
OledWriteCmd(0xd9);
//( 20) send 0xf1
OledWriteCmd(0xf1);
//( 21) set com pin configuration (0xda)
OledWriteCmd(0xda);
//( 22) send 0x12
OledWriteCmd(0x12);
//( 23) set Vcomh (0xdb)
OledWriteCmd(0xdb);
//( 24) send 0x30
OledWriteCmd(0x30);
//( 25) set charge pump enable (0x8d)
OledWriteCmd(0x8d);
//( 26) send 0x14
OledWriteCmd(0x14);
//( 27) turn on oled panel(0xaf)
OledWriteCmd(0xaf);
}
1.3选择Page 0位置显示
- 确认页寻址模式
向OLED发送指令0x20
和0x02
即可
OledWriteCmd(0x20);
OledWriteCmd(0x02);
- 确认哪个Page显示,Page 0
一、手册内容
X2,X1,X0,可以选择0到7Page。也就是2的3次方。
二、代码体现
OledWriteCmd(0xB0);
1.4发送0x08显示一个点
- 代码体现
OledWriteData(0x08);
1.5完整程序代码
#include "reg52.h"
#include "intrins.h"
sbit SCL = P0^1; //把SCL接单片机P0.1口
sbit SDA = P0^3; //把SDA接单片机P0.3口
void IICStart() //IIC起始信号函数
{
SCL = 0; //防止雪花
SDA = 1; //根据起始信号时序图阴影部分,SDA先是高电平
SCL = 1; //根据起始信号时序图,SCL一直为高电平
_nop_(); //_nop_()寒素执行时间为5微秒,并不是1微秒,原因是调用函数时有进出栈操作
//此时在这里,根据起始信号时序图可知需要延时》4.7微秒
SDA = 0; //根据起始信号时序图阴影部分,SDA此时为低电平
_nop_(); //延时5微秒
}
void IICStop() //IIC终止信号函数
{
SCL = 0; //防止雪花
SDA = 0; //根据起始信号时序图阴影部分,SDA先是低电平
SCL = 1; //根据起始信号时序图,SCL一直为高电平
_nop_(); //延时5微秒
SDA = 1; //根据起始信号时序图阴影部分,SDA此时为高电平
_nop_(); //延时5微秒
}
char IIC_ACK()
{
char flag;
SDA = 1; //释放数据线
_nop_();
SCL = 1;
_nop_();
flag = SDA;
_nop_();
SCL = 0;
_nop_();
return flag;
}
void IICSendByte(char cdata)
{
char i;
for(i=0; i<8; i++ )
{
SCL = 0; //scl拉低,让sda做好数据准备
SDA = cdata & 0x80; //0x80 = 1000 0000获得cdata的最高位,给sda
_nop_(); //发送建立数据时间
SCL = 1; //SCL被拉高开始发送数据
_nop_(); //数据发送时间
SCL = 0; //发送完数据被拉低
_nop_();
cdata = cdata << 1;
}
}
void OledWriteCmd(char Cmd)
{
//1.start
IICStart();
//2.写入从机地址 b0111 1000 0x78
IICSendByte(0x78);
//3.ACK
IIC_ACK();
//4.cotrol byte: (0)(0)000000 写入命令 (0)(1)000000写入数据
IICSendByte(0x00);
//5.ACK
IIC_ACK();
//6. 写入指令/数据
IICSendByte(Cmd);
//7.ACK
IIC_ACK();
//8.STOP
IICStop();
}
void OledWriteData(char Data)
{
//1.start
IICStart();
//2.写入从机地址 b0111 1000 0x78
IICSendByte(0x78);
//3.ACK
IIC_ACK();
//4.cotrol byte: (0)(0)000000 写入命令 (0)(1)000000写入数据
IICSendByte(0x40);
//5.ACK
IIC_ACK();
//6. 写入指令/数据
IICSendByte(Data);
//7.ACK
IIC_ACK();
//8.STOP
IICStop();
}
void initOLED()
{
//( 01) display off (0xae)
OledWriteCmd(0xae);
//( 02) set low column address (0x00)
OledWriteCmd(0x00);
//( 03) set high column address (0x10)
OledWriteCmd(0x10);
//( 04) set start line address (0x40)
OledWriteCmd(0x40);
//( 05) set page address (0xb0)
OledWriteCmd(0xb0);
//( 06) contract control (0x81)
OledWriteCmd(0x81);
//( 07) send 0xff (多字节指令)
OledWriteCmd(0xff);
//( 08) set segment remap (0xa1)
OledWriteCmd(0xa1);
//( 09) set normal/reverse (0xa6)
OledWriteCmd(0xa6);
//( 10) set multiplex ratio (1 to 64) (0xa8 )
OledWriteCmd(0xa8);
//( 11) set duty 1/32 (0x3f)
OledWriteCmd(0x3f);
//( 12) com scan direction (0xc8)
OledWriteCmd(0xc8);
//( 13) set display offset (0xd3)
OledWriteCmd(0xd3);
//( 14) send 0x00
OledWriteCmd(0x00);
//( 15) set osc division (0xd5)
OledWriteCmd(0xd5);
//( 16) send 0x80
OledWriteCmd(0x80);
//( 17) set area color mode off (0xd8)
OledWriteCmd(0xd8);
//( 18) send 0x05
OledWriteCmd(0x05);
//( 19) set pre-charge period (0xd9)
OledWriteCmd(0xd9);
//( 20) send 0xf1
OledWriteCmd(0xf1);
//( 21) set com pin configuration (0xda)
OledWriteCmd(0xda);
//( 22) send 0x12
OledWriteCmd(0x12);
//( 23) set Vcomh (0xdb)
OledWriteCmd(0xdb);
//( 24) send 0x30
OledWriteCmd(0x30);
//( 25) set charge pump enable (0x8d)
OledWriteCmd(0x8d);
//( 26) send 0x14
OledWriteCmd(0x14);
//( 27) turn on oled panel(0xaf)
OledWriteCmd(0xaf);
}
void main()
{
//1.初始化OLED
initOLED();
//2.选择一个位置
//2.1确认页寻址模式
OledWriteCmd(0x20);
OledWriteCmd(0x02);
//2.2确认那个page显示,page 0
OledWriteCmd(0xB0);
//3.发送0x08显示一个点
OledWriteData(0x08);
//防止主函数退出
while(1);
}
2. OLED列地址
2.1 OLED列地址手册介绍
从手册中可以看出,列地址由两个8位数据控制。一个高8位
,一个低8位
。低8位默认前4位为0
,高8为默认前四位为0001
,也就是0x1\*
。通过这两个8位数据的后四位的值来控制128列的列数据。
要让显示图像左对齐,就可以通过列地址设置成为第一列。
2.2代码体现
OledWriteCmd(0xB2);
OledWriteCmd(0x00); //使图像从左边第一列开始显示
OledWriteCmd(0x10);
2.3完整程序代码(显示两条线)
#include "reg52.h"
#include "intrins.h"
sbit SCL = P0^1; //把SCL接单片机P0.1口
sbit SDA = P0^3; //把SDA接单片机P0.3口
void IICStart() //IIC起始信号函数
{
SCL = 0; //防止雪花
SDA = 1; //根据起始信号时序图阴影部分,SDA先是高电平
SCL = 1; //根据起始信号时序图,SCL一直为高电平
_nop_(); //_nop_()寒素执行时间为5微秒,并不是1微秒,原因是调用函数时有进出栈操作
//此时在这里,根据起始信号时序图可知需要延时》4.7微秒
SDA = 0; //根据起始信号时序图阴影部分,SDA此时为低电平
_nop_(); //延时5微秒
}
void IICStop() //IIC终止信号函数
{
SCL = 0; //防止雪花
SDA = 0; //根据起始信号时序图阴影部分,SDA先是低电平
SCL = 1; //根据起始信号时序图,SCL一直为高电平
_nop_(); //延时5微秒
SDA = 1; //根据起始信号时序图阴影部分,SDA此时为高电平
_nop_(); //延时5微秒
}
char IIC_ACK()
{
char flag;
SDA = 1; //释放数据线
_nop_();
SCL = 1;
_nop_();
flag = SDA;
_nop_();
SCL = 0;
_nop_();
return flag;
}
void IICSendByte(char cdata)
{
char i;
for(i=0; i<8; i++ )
{
SCL = 0; //scl拉低,让sda做好数据准备
SDA = cdata & 0x80; //0x80 = 1000 0000获得cdata的最高位,给sda
_nop_(); //发送建立数据时间
SCL = 1; //SCL被拉高开始发送数据
_nop_(); //数据发送时间
SCL = 0; //发送完数据被拉低
_nop_();
cdata = cdata << 1;
}
}
void OledWriteCmd(char Cmd)
{
//1.start
IICStart();
//2.写入从机地址 b0111 1000 0x78
IICSendByte(0x78);
//3.ACK
IIC_ACK();
//4.cotrol byte: (0)(0)000000 写入命令 (0)(1)000000写入数据
IICSendByte(0x00);
//5.ACK
IIC_ACK();
//6. 写入指令/数据
IICSendByte(Cmd);
//7.ACK
IIC_ACK();
//8.STOP
IICStop();
}
void OledWriteData(char Data)
{
//1.start
IICStart();
//2.写入从机地址 b0111 1000 0x78
IICSendByte(0x78);
//3.ACK
IIC_ACK();
//4.cotrol byte: (0)(0)000000 写入命令 (0)(1)000000写入数据
IICSendByte(0x40);
//5.ACK
IIC_ACK();
//6. 写入指令/数据
IICSendByte(Data);
//7.ACK
IIC_ACK();
//8.STOP
IICStop();
}
void initOLED()
{
//( 01) display off (0xae)
OledWriteCmd(0xae);
//( 02) set low column address (0x00)
OledWriteCmd(0x00);
//( 03) set high column address (0x10)
OledWriteCmd(0x10);
//( 04) set start line address (0x40)
OledWriteCmd(0x40);
//( 05) set page address (0xb0)
OledWriteCmd(0xb0);
//( 06) contract control (0x81)
OledWriteCmd(0x81);
//( 07) send 0xff (多字节指令)
OledWriteCmd(0xff);
//( 08) set segment remap (0xa1)
OledWriteCmd(0xa1);
//( 09) set normal/reverse (0xa6)
OledWriteCmd(0xa6);
//( 10) set multiplex ratio (1 to 64) (0xa8 )
OledWriteCmd(0xa8);
//( 11) set duty 1/32 (0x3f)
OledWriteCmd(0x3f);
//( 12) com scan direction (0xc8)
OledWriteCmd(0xc8);
//( 13) set display offset (0xd3)
OledWriteCmd(0xd3);
//( 14) send 0x00
OledWriteCmd(0x00);
//( 15) set osc division (0xd5)
OledWriteCmd(0xd5);
//( 16) send 0x80
OledWriteCmd(0x80);
//( 17) set area color mode off (0xd8)
OledWriteCmd(0xd8);
//( 18) send 0x05
OledWriteCmd(0x05);
//( 19) set pre-charge period (0xd9)
OledWriteCmd(0xd9);
//( 20) send 0xf1
OledWriteCmd(0xf1);
//( 21) set com pin configuration (0xda)
OledWriteCmd(0xda);
//( 22) send 0x12
OledWriteCmd(0x12);
//( 23) set Vcomh (0xdb)
OledWriteCmd(0xdb);
//( 24) send 0x30
OledWriteCmd(0x30);
//( 25) set charge pump enable (0x8d)
OledWriteCmd(0x8d);
//( 26) send 0x14
OledWriteCmd(0x14);
//( 27) turn on oled panel(0xaf)
OledWriteCmd(0xaf);
}
void main()
{
char i;
//1.初始化OLED
initOLED();
//2.选择一个位置
//2.1确认页寻址模式
OledWriteCmd(0x20);
OledWriteCmd(0x02);
//2.2确认那个page显示,page 0
OledWriteCmd(0xB0);
//3.发送0x08显示一个点
OledWriteData(0x08);
//4.显示一条线
for(i=0; i<60; i++)
{
OledWriteData(0x08);
}
//5.复制这条线到其他Page
OledWriteCmd(0xB2);
OledWriteCmd(0x00);
OledWriteCmd(0x10);
for(i=0; i<60; i++)
{
OledWriteData(0x08);
}
//6.让第三根线都在左边开始显示
//防止主函数退出
while(1);
}
2.4补充说明
此程序基于OLED显示一个点代码实现
工程修改
3. OLED清屏添加清屏函数
3.1为什么需要清屏函数
- 清屏函数可以清理上次OLED寄存器中的数据,使这次显示的内容不会和上次显示的内容混合在一起。
- 清屏函数可以防止OLED出现雪花,因为多次像OLED中写入数据,没有清除上一次的数据,会是OLED出现雪花。
3.2 OLED清屏添加清屏函数核心思想
向128*64个像素点内写入0,使像素点都熄灭。就可以达到清屏的作用。
3.3清屏函数代码
void OLEDClearScreen()
{
unsigned char i; //使用无符号的字符型变量i,j的作用是防止内存越界。因为
unsigned char j; //有符号的字符型数据只能表示 -128~127,会在内层for中越界
for(i=0; i<8; i++)
{
OledWriteCmd(0xB0 + i); //偏移Page
OledWriteCmd(0x00); //从第一列开始清屏
OledWriteCmd(0x10);
for(j=0; j<128; j++) //列地址自动偏移
{
OledWriteData(0); //写入清屏数据0
}
}
}
3.4完整程序代码
#include "reg52.h"
#include "intrins.h"
sbit SCL = P0^1; //把SCL接单片机P0.1口
sbit SDA = P0^3; //把SDA接单片机P0.3口
void IICStart() //IIC起始信号函数
{
SCL = 0; //防止雪花
SDA = 1; //根据起始信号时序图阴影部分,SDA先是高电平
SCL = 1; //根据起始信号时序图,SCL一直为高电平
_nop_(); //_nop_()寒素执行时间为5微秒,并不是1微秒,原因是调用函数时有进出栈操作
//此时在这里,根据起始信号时序图可知需要延时》4.7微秒
SDA = 0; //根据起始信号时序图阴影部分,SDA此时为低电平
_nop_(); //延时5微秒
}
void IICStop() //IIC终止信号函数
{
SCL = 0; //防止雪花
SDA = 0; //根据起始信号时序图阴影部分,SDA先是低电平
SCL = 1; //根据起始信号时序图,SCL一直为高电平
_nop_(); //延时5微秒
SDA = 1; //根据起始信号时序图阴影部分,SDA此时为高电平
_nop_(); //延时5微秒
}
char IIC_ACK()
{
char flag;
SDA = 1; //释放数据线
_nop_();
SCL = 1;
_nop_();
flag = SDA;
_nop_();
SCL = 0;
_nop_();
return flag;
}
void IICSendByte(char cdata)
{
char i;
for(i=0; i<8; i++ )
{
SCL = 0; //scl拉低,让sda做好数据准备
SDA = cdata & 0x80; //0x80 = 1000 0000获得cdata的最高位,给sda
_nop_(); //发送建立数据时间
SCL = 1; //SCL被拉高开始发送数据
_nop_(); //数据发送时间
SCL = 0; //发送完数据被拉低
_nop_();
cdata = cdata << 1;
}
}
void OledWriteCmd(char Cmd)
{
//1.start
IICStart();
//2.写入从机地址 b0111 1000 0x78
IICSendByte(0x78);
//3.ACK
IIC_ACK();
//4.cotrol byte: (0)(0)000000 写入命令 (0)(1)000000写入数据
IICSendByte(0x00);
//5.ACK
IIC_ACK();
//6. 写入指令/数据
IICSendByte(Cmd);
//7.ACK
IIC_ACK();
//8.STOP
IICStop();
}
void OledWriteData(char Data)
{
//1.start
IICStart();
//2.写入从机地址 b0111 1000 0x78
IICSendByte(0x78);
//3.ACK
IIC_ACK();
//4.cotrol byte: (0)(0)000000 写入命令 (0)(1)000000写入数据
IICSendByte(0x40);
//5.ACK
IIC_ACK();
//6. 写入指令/数据
IICSendByte(Data);
//7.ACK
IIC_ACK();
//8.STOP
IICStop();
}
void initOLED()
{
//( 01) display off (0xae)
OledWriteCmd(0xae);
//( 02) set low column address (0x00)
OledWriteCmd(0x00);
//( 03) set high column address (0x10)
OledWriteCmd(0x10);
//( 04) set start line address (0x40)
OledWriteCmd(0x40);
//( 05) set page address (0xb0)
OledWriteCmd(0xb0);
//( 06) contract control (0x81)
OledWriteCmd(0x81);
//( 07) send 0xff (多字节指令)
OledWriteCmd(0xff);
//( 08) set segment remap (0xa1)
OledWriteCmd(0xa1);
//( 09) set normal/reverse (0xa6)
OledWriteCmd(0xa6);
//( 10) set multiplex ratio (1 to 64) (0xa8 )
OledWriteCmd(0xa8);
//( 11) set duty 1/32 (0x3f)
OledWriteCmd(0x3f);
//( 12) com scan direction (0xc8)
OledWriteCmd(0xc8);
//( 13) set display offset (0xd3)
OledWriteCmd(0xd3);
//( 14) send 0x00
OledWriteCmd(0x00);
//( 15) set osc division (0xd5)
OledWriteCmd(0xd5);
//( 16) send 0x80
OledWriteCmd(0x80);
//( 17) set area color mode off (0xd8)
OledWriteCmd(0xd8);
//( 18) send 0x05
OledWriteCmd(0x05);
//( 19) set pre-charge period (0xd9)
OledWriteCmd(0xd9);
//( 20) send 0xf1
OledWriteCmd(0xf1);
//( 21) set com pin configuration (0xda)
OledWriteCmd(0xda);
//( 22) send 0x12
OledWriteCmd(0x12);
//( 23) set Vcomh (0xdb)
OledWriteCmd(0xdb);
//( 24) send 0x30
OledWriteCmd(0x30);
//( 25) set charge pump enable (0x8d)
OledWriteCmd(0x8d);
//( 26) send 0x14
OledWriteCmd(0x14);
//( 27) turn on oled panel(0xaf)
OledWriteCmd(0xaf);
}
void OLEDClearScreen()
{
unsigned char i; //使用无符号的字符型变量i,j的作用是防止内存越界。因为
unsigned char j; //有符号的字符型数据只能表示 -128~127,会在内层for中越界
for(i=0; i<8; i++)
{
OledWriteCmd(0xB0 + i); //偏移Page
OledWriteCmd(0x00); //从第一列开始清屏
OledWriteCmd(0x10);
for(j=0; j<128; j++) //列地址自动偏移
{
OledWriteData(0); //写入清屏数据0
}
}
}
void main()
{
char i;
//1.初始化OLED
initOLED();
//2.选择一个位置
//2.1确认页寻址模式
OledWriteCmd(0x20);
OledWriteCmd(0x02);
OLEDClearScreen();
//2.2确认那个page显示,page 0
OledWriteCmd(0xB0);
//3.发送0x08显示一个点
OledWriteData(0x08);
//4.显示一条线
for(i=0; i<59; i++)
{
OledWriteData(0x08);
}
//5.复制这条线到另外的Page
OledWriteCmd(0xB2);
OledWriteCmd(0x00);
OledWriteCmd(0x10);
for(i=0; i<60; i++)
{
OledWriteData(0x08);
}
//防止主函数退出
while(1);
}
3.5补充说明
此程序基于OLED列地址
工程修改
4. OLED显示字母A
4.1 OLED显示字母A核心思路
- 使用
液晶显示模块字模工具
生成字符A
的数据 - 根据生成的字符A的数据
建立字符数组
- 使用
for
循环发送字符数据使OLED显示字符A
注:此程序基于OLED清屏添加清屏函数
工程修改
4.2使用液晶显示模块字模工具生成字符A的数据
1.打开液晶显示模块字模工具
2.点击参数设置
3.点击文字输入区字体选择
4.设置字体为宋体,字形常规,大小为12号,点击确定
5.点击其他选项
6.取模方式选纵向取模,选择字节倒序,选择保留,A51数据位数选择任何时候都加0,点击确定。
7.在文本输入区输入字符A并按Ctrl+Enter。
8.点击取模方式,选择C51即可完成取模
4.3根据生成的字符A的数据建立字符数组
- 生成数据分析
生成数据为宽×高
= 8×16
,一个Page高8
,所以字符A占两个Page
。每个Page占8列
。所以可以构建两个大小为8
的字符数组A1、A2。
- 建立字符数组
/*-- 文字: A --*/
/*-- 宋体12; 此字体下对应的点阵为:宽x高=8x16 --*/
char A1[8] = {0x00,0x00,0xC0,0x38,0xE0,0x00,0x00,0x00};
char A2[8] = {0x20,0x3C,0x23,0x02,0x02,0x27,0x38,0x20};
4.4使用for循环发送字符数据使OLED显示字符A
- for循环代码
//写A字符的上半部分
OledWriteCmd(0xB0);
OledWriteCmd(0x00);
OledWriteCmd(0x10);
for(i=0; i<8; i++)
{
OledWriteData(A1[i]);
}
//写A字符的下半部分
OledWriteCmd(0xB1);
OledWriteCmd(0x00);
OledWriteCmd(0x10);
for(i=0; i<8; i++)
{
OledWriteData(A2[i]);
}
4.5完整程序代码
#include "reg52.h"
#include "intrins.h"
sbit SCL = P0^1; //把SCL接单片机P0.1口
sbit SDA = P0^3; //把SDA接单片机P0.3口
/*-- 文字: A --*/
/*-- 宋体12; 此字体下对应的点阵为:宽x高=8x16 --*/
char A1[8] = {0x00,0x00,0xC0,0x38,0xE0,0x00,0x00,0x00};
char A2[8] = {0x20,0x3C,0x23,0x02,0x02,0x27,0x38,0x20};
void IICStart() //IIC起始信号函数
{
SCL = 0; //防止雪花
SDA = 1; //根据起始信号时序图阴影部分,SDA先是高电平
SCL = 1; //根据起始信号时序图,SCL一直为高电平
_nop_(); //_nop_()寒素执行时间为5微秒,并不是1微秒,原因是调用函数时有进出栈操作
//此时在这里,根据起始信号时序图可知需要延时》4.7微秒
SDA = 0; //根据起始信号时序图阴影部分,SDA此时为低电平
_nop_(); //延时5微秒
}
void IICStop() //IIC终止信号函数
{
SCL = 0; //防止雪花
SDA = 0; //根据起始信号时序图阴影部分,SDA先是低电平
SCL = 1; //根据起始信号时序图,SCL一直为高电平
_nop_(); //延时5微秒
SDA = 1; //根据起始信号时序图阴影部分,SDA此时为高电平
_nop_(); //延时5微秒
}
char IIC_ACK()
{
char flag;
SDA = 1; //释放数据线
_nop_();
SCL = 1;
_nop_();
flag = SDA;
_nop_();
SCL = 0;
_nop_();
return flag;
}
void IICSendByte(char cdata)
{
char i;
for(i=0; i<8; i++ )
{
SCL = 0; //scl拉低,让sda做好数据准备
SDA = cdata & 0x80; //0x80 = 1000 0000获得cdata的最高位,给sda
_nop_(); //发送建立数据时间
SCL = 1; //SCL被拉高开始发送数据
_nop_(); //数据发送时间
SCL = 0; //发送完数据被拉低
_nop_();
cdata = cdata << 1;
}
}
void OledWriteCmd(char Cmd)
{
//1.start
IICStart();
//2.写入从机地址 b0111 1000 0x78
IICSendByte(0x78);
//3.ACK
IIC_ACK();
//4.cotrol byte: (0)(0)000000 写入命令 (0)(1)000000写入数据
IICSendByte(0x00);
//5.ACK
IIC_ACK();
//6. 写入指令/数据
IICSendByte(Cmd);
//7.ACK
IIC_ACK();
//8.STOP
IICStop();
}
void OledWriteData(char Data)
{
//1.start
IICStart();
//2.写入从机地址 b0111 1000 0x78
IICSendByte(0x78);
//3.ACK
IIC_ACK();
//4.cotrol byte: (0)(0)000000 写入命令 (0)(1)000000写入数据
IICSendByte(0x40);
//5.ACK
IIC_ACK();
//6. 写入指令/数据
IICSendByte(Data);
//7.ACK
IIC_ACK();
//8.STOP
IICStop();
}
void initOLED()
{
//( 01) display off (0xae)
OledWriteCmd(0xae);
//( 02) set low column address (0x00)
OledWriteCmd(0x00);
//( 03) set high column address (0x10)
OledWriteCmd(0x10);
//( 04) set start line address (0x40)
OledWriteCmd(0x40);
//( 05) set page address (0xb0)
OledWriteCmd(0xb0);
//( 06) contract control (0x81)
OledWriteCmd(0x81);
//( 07) send 0xff (多字节指令)
OledWriteCmd(0xff);
//( 08) set segment remap (0xa1)
OledWriteCmd(0xa1);
//( 09) set normal/reverse (0xa6)
OledWriteCmd(0xa6);
//( 10) set multiplex ratio (1 to 64) (0xa8 )
OledWriteCmd(0xa8);
//( 11) set duty 1/32 (0x3f)
OledWriteCmd(0x3f);
//( 12) com scan direction (0xc8)
OledWriteCmd(0xc8);
//( 13) set display offset (0xd3)
OledWriteCmd(0xd3);
//( 14) send 0x00
OledWriteCmd(0x00);
//( 15) set osc division (0xd5)
OledWriteCmd(0xd5);
//( 16) send 0x80
OledWriteCmd(0x80);
//( 17) set area color mode off (0xd8)
OledWriteCmd(0xd8);
//( 18) send 0x05
OledWriteCmd(0x05);
//( 19) set pre-charge period (0xd9)
OledWriteCmd(0xd9);
//( 20) send 0xf1
OledWriteCmd(0xf1);
//( 21) set com pin configuration (0xda)
OledWriteCmd(0xda);
//( 22) send 0x12
OledWriteCmd(0x12);
//( 23) set Vcomh (0xdb)
OledWriteCmd(0xdb);
//( 24) send 0x30
OledWriteCmd(0x30);
//( 25) set charge pump enable (0x8d)
OledWriteCmd(0x8d);
//( 26) send 0x14
OledWriteCmd(0x14);
//( 27) turn on oled panel(0xaf)
OledWriteCmd(0xaf);
}
void OLEDClearScreen()
{
unsigned char i; //使用无符号的字符型变量i,j的作用是防止内存越界。因为
unsigned char j; //有符号的字符型数据只能表示 -128~127,会在内层for中越界
for(i=0; i<8; i++)
{
OledWriteCmd(0xB0 + i); //偏移Page
OledWriteCmd(0x00); //从第一列开始清屏
OledWriteCmd(0x10);
for(j=0; j<128; j++) //列地址自动偏移
{
OledWriteData(0); //写入清屏数据0
}
}
}
void main()
{
char i;
//1.初始化OLED
initOLED();
//2.选择一个位置
//2.1确认页寻址模式
OledWriteCmd(0x20);
OledWriteCmd(0x02);
OLEDClearScreen();
//2.2确认那个page显示,page 0
//写A字符的上半部分
OledWriteCmd(0xB0);
OledWriteCmd(0x00);
OledWriteCmd(0x10);
for(i=0; i<8; i++)
{
OledWriteData(A1[i]);
}
//写A字符的下半部分
OledWriteCmd(0xB1);
OledWriteCmd(0x00);
OledWriteCmd(0x10);
for(i=0; i<8; i++)
{
OledWriteData(A2[i]);
}
//防止主函数退出
while(1);
}
5. OLED显示中文
5.1 OLED显示中文核心思路
- 使用
液晶显示模块字模工具
生成字符的数据 - 根据生成字符的数据
建立字符数组
- 构造发送
字符数据函数
注:此程序基于OLED显示字符A
工程修改
5.2使用液晶显示模块字模工具生成字符的数据
- 使用方法和4.2一样
5.3根据生成字符的数据建立字符数组
- 生成数据分析
生成数据为宽×高
= 16×16
,一个Page高8
,所以字符A占两个Page
。每个Page占16列
。所以可以构建的字符数组
大小为16
- 建立字符数组注意事项
需要使用code关键字,因为单纯的char 型是将数据存放在数据存储器RAM中,RAM容量小,无法存入16个数据。所以使用code关键字可以使这16个数据存入程序储存器ROM中,保障了16个数据的存储以及提高程序的执行效率和速度。
- 建立字符数组
/*-- 文字: 马 --*/
/*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/
code char M1[16] = {0x00,0x02,0x02,0xF2,0x82,0x82,0x82,0x82,0x82,0x82,0xFE,0x80,0x80,0x80,0x00,0x00};
code char M2[16] = {0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x48,0x80,0x40,0x3F,0x00,0x00};
/*-- 文字: 哥 --*/
/*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/
code char G1[16] = {0x00,0x02,0x02,0x7A,0x4A,0x4A,0x4A,0x4A,0x7A,0x02,0x02,0x7E,0x02,0x02,0x00,0x00};
code char G2[16] = {0x01,0x01,0x01,0x3D,0x25,0x25,0x25,0x25,0x3D,0x41,0x81,0x7F,0x01,0x01,0x01,0x00};
/*-- 文字: 成 --*/
/*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/
code char C1[16] = {0x00,0x00,0xF8,0x88,0x88,0x88,0x88,0x08,0x08,0xFF,0x08,0x09,0x0A,0xC8,0x08,0x00};
code char C2[16] = {0x80,0x60,0x1F,0x00,0x10,0x20,0x1F,0x80,0x40,0x21,0x16,0x18,0x26,0x41,0xF8,0x00};
/*-- 文字: 长 --*/
/*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/
code char Z1[16] = {0x80,0x80,0x80,0x80,0xFF,0x80,0x80,0xA0,0x90,0x88,0x84,0x82,0x80,0x80,0x80,0x00};
code char Z2[16] = {0x00,0x00,0x00,0x00,0xFF,0x40,0x21,0x12,0x04,0x08,0x10,0x20,0x20,0x40,0x40,0x00};
/*-- 文字: 记 --*/
/*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/
code char J1[16] = {0x40,0x40,0x42,0xCC,0x00,0x00,0x00,0x84,0x84,0x84,0x84,0x84,0xFC,0x00,0x00,0x00};
code char J2[16] = {0x00,0x00,0x00,0x7F,0x20,0x10,0x00,0x3F,0x40,0x40,0x40,0x40,0x41,0x40,0x70,0x00};
5.4构造发送字符数据函数
- 构造函数思路
在OLED中,列地址会自动偏移。所以只需要一次性发送一个字符的上半部分。然而一个字符的上半份宽16,所以需要用for循环16次发送。
- 函数代码
void OLEDShowChineseChar(char CCdata[])
{
unsigned char i;
for(i=0; i<16; i++)
{
OledWriteData(CCdata[i]);
}
}
5.4完整程序代码
#include "reg52.h"
#include "intrins.h"
sbit SCL = P0^1; //把SCL接单片机P0.1口
sbit SDA = P0^3; //把SDA接单片机P0.3口
/*-- 文字: 马 --*/
/*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/
code char M1[16] = {0x00,0x02,0x02,0xF2,0x82,0x82,0x82,0x82,0x82,0x82,0xFE,0x80,0x80,0x80,0x00,0x00};
code char M2[16] = {0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x48,0x80,0x40,0x3F,0x00,0x00};
/*-- 文字: 哥 --*/
/*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/
code char G1[16] = {0x00,0x02,0x02,0x7A,0x4A,0x4A,0x4A,0x4A,0x7A,0x02,0x02,0x7E,0x02,0x02,0x00,0x00};
code char G2[16] = {0x01,0x01,0x01,0x3D,0x25,0x25,0x25,0x25,0x3D,0x41,0x81,0x7F,0x01,0x01,0x01,0x00};
/*-- 文字: 成 --*/
/*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/
code char C1[16] = {0x00,0x00,0xF8,0x88,0x88,0x88,0x88,0x08,0x08,0xFF,0x08,0x09,0x0A,0xC8,0x08,0x00};
code char C2[16] = {0x80,0x60,0x1F,0x00,0x10,0x20,0x1F,0x80,0x40,0x21,0x16,0x18,0x26,0x41,0xF8,0x00};
/*-- 文字: 长 --*/
/*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/
code char Z1[16] = {0x80,0x80,0x80,0x80,0xFF,0x80,0x80,0xA0,0x90,0x88,0x84,0x82,0x80,0x80,0x80,0x00};
code char Z2[16] = {0x00,0x00,0x00,0x00,0xFF,0x40,0x21,0x12,0x04,0x08,0x10,0x20,0x20,0x40,0x40,0x00};
/*-- 文字: 记 --*/
/*-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --*/
code char J1[16] = {0x40,0x40,0x42,0xCC,0x00,0x00,0x00,0x84,0x84,0x84,0x84,0x84,0xFC,0x00,0x00,0x00};
code char J2[16] = {0x00,0x00,0x00,0x7F,0x20,0x10,0x00,0x3F,0x40,0x40,0x40,0x40,0x41,0x40,0x70,0x00};
void IICStart() //IIC起始信号函数
{
SCL = 0; //防止雪花
SDA = 1; //根据起始信号时序图阴影部分,SDA先是高电平
SCL = 1; //根据起始信号时序图,SCL一直为高电平
_nop_(); //_nop_()寒素执行时间为5微秒,并不是1微秒,原因是调用函数时有进出栈操作
//此时在这里,根据起始信号时序图可知需要延时》4.7微秒
SDA = 0; //根据起始信号时序图阴影部分,SDA此时为低电平
_nop_(); //延时5微秒
}
void IICStop() //IIC终止信号函数
{
SCL = 0; //防止雪花
SDA = 0; //根据起始信号时序图阴影部分,SDA先是低电平
SCL = 1; //根据起始信号时序图,SCL一直为高电平
_nop_(); //延时5微秒
SDA = 1; //根据起始信号时序图阴影部分,SDA此时为高电平
_nop_(); //延时5微秒
}
char IIC_ACK()
{
char flag;
SDA = 1; //释放数据线
_nop_();
SCL = 1;
_nop_();
flag = SDA;
_nop_();
SCL = 0;
_nop_();
return flag;
}
void IICSendByte(char cdata)
{
char i;
for(i=0; i<8; i++ )
{
SCL = 0; //scl拉低,让sda做好数据准备
SDA = cdata & 0x80; //0x80 = 1000 0000获得cdata的最高位,给sda
_nop_(); //发送建立数据时间
SCL = 1; //SCL被拉高开始发送数据
_nop_(); //数据发送时间
SCL = 0; //发送完数据被拉低
_nop_();
cdata = cdata << 1;
}
}
void OledWriteCmd(char Cmd)
{
//1.start
IICStart();
//2.写入从机地址 b0111 1000 0x78
IICSendByte(0x78);
//3.ACK
IIC_ACK();
//4.cotrol byte: (0)(0)000000 写入命令 (0)(1)000000写入数据
IICSendByte(0x00);
//5.ACK
IIC_ACK();
//6. 写入指令/数据
IICSendByte(Cmd);
//7.ACK
IIC_ACK();
//8.STOP
IICStop();
}
void OledWriteData(char Data)
{
//1.start
IICStart();
//2.写入从机地址 b0111 1000 0x78
IICSendByte(0x78);
//3.ACK
IIC_ACK();
//4.cotrol byte: (0)(0)000000 写入命令 (0)(1)000000写入数据
IICSendByte(0x40);
//5.ACK
IIC_ACK();
//6. 写入指令/数据
IICSendByte(Data);
//7.ACK
IIC_ACK();
//8.STOP
IICStop();
}
void initOLED()
{
//( 01) display off (0xae)
OledWriteCmd(0xae);
//( 02) set low column address (0x00)
OledWriteCmd(0x00);
//( 03) set high column address (0x10)
OledWriteCmd(0x10);
//( 04) set start line address (0x40)
OledWriteCmd(0x40);
//( 05) set page address (0xb0)
OledWriteCmd(0xb0);
//( 06) contract control (0x81)
OledWriteCmd(0x81);
//( 07) send 0xff (多字节指令)
OledWriteCmd(0xff);
//( 08) set segment remap (0xa1)
OledWriteCmd(0xa1);
//( 09) set normal/reverse (0xa6)
OledWriteCmd(0xa6);
//( 10) set multiplex ratio (1 to 64) (0xa8 )
OledWriteCmd(0xa8);
//( 11) set duty 1/32 (0x3f)
OledWriteCmd(0x3f);
//( 12) com scan direction (0xc8)
OledWriteCmd(0xc8);
//( 13) set display offset (0xd3)
OledWriteCmd(0xd3);
//( 14) send 0x00
OledWriteCmd(0x00);
//( 15) set osc division (0xd5)
OledWriteCmd(0xd5);
//( 16) send 0x80
OledWriteCmd(0x80);
//( 17) set area color mode off (0xd8)
OledWriteCmd(0xd8);
//( 18) send 0x05
OledWriteCmd(0x05);
//( 19) set pre-charge period (0xd9)
OledWriteCmd(0xd9);
//( 20) send 0xf1
OledWriteCmd(0xf1);
//( 21) set com pin configuration (0xda)
OledWriteCmd(0xda);
//( 22) send 0x12
OledWriteCmd(0x12);
//( 23) set Vcomh (0xdb)
OledWriteCmd(0xdb);
//( 24) send 0x30
OledWriteCmd(0x30);
//( 25) set charge pump enable (0x8d)
OledWriteCmd(0x8d);
//( 26) send 0x14
OledWriteCmd(0x14);
//( 27) turn on oled panel(0xaf)
OledWriteCmd(0xaf);
}
void OLEDClearScreen()
{
unsigned char i; //使用无符号的字符型变量i,j的作用是防止内存越界。因为
unsigned char j; //有符号的字符型数据只能表示 -128~127,会在内层for中越界
for(i=0; i<8; i++)
{
OledWriteCmd(0xB0 + i); //偏移Page
OledWriteCmd(0x00); //从第一列开始清屏
OledWriteCmd(0x10);
for(j=0; j<128; j++) //列地址自动偏移
{
OledWriteData(0); //写入清屏数据0
}
}
}
void OLEDShowChineseChar(char CCdata[])
{
unsigned char i;
for(i=0; i<16; i++)
{
OledWriteData(CCdata[i]);
}
}
void main()
{
//1.初始化OLED
initOLED();
//2.选择一个位置
//2.1确认页寻址模式
OledWriteCmd(0x20);
OledWriteCmd(0x02);
OLEDClearScreen();
//2.2确认那个page显示,page 0
//写马哥成长记字符的上半部分
OledWriteCmd(0xB0);
OledWriteCmd(0x00);
OledWriteCmd(0x10);
OLEDShowChineseChar(M1);
OLEDShowChineseChar(G1);
OLEDShowChineseChar(C1);
OLEDShowChineseChar(Z1);
OLEDShowChineseChar(J1);
//写A字符的下半部分
OledWriteCmd(0xB1);
OledWriteCmd(0x00);
OledWriteCmd(0x10);
OLEDShowChineseChar(M2);
OLEDShowChineseChar(G2);
OLEDShowChineseChar(C2);
OLEDShowChineseChar(Z2);
OLEDShowChineseChar(J2);
//防止主函数退出
while(1);
}
6. OLED显示图片
6.1 OLED显示图片核心思路
百度搜索简笔图片
FastStone Capture
软件进行截图修改图片尺寸并保存为bmp格式
。- 使用
液晶显示模块字模工具
生成图片的数据 - 根据生成图片的数据
建立图片数组
- 构造发送
图片数据函数
6.2百度搜索简笔图片
6.3 FastStone Capture软件进行截图修改图片尺寸并保存为bmp格式
- 根据自己设置的截图快捷键截图(我的是Alt + A)
- 截图成功后在跳转页面按
Ctrl + R
调整图片大小为128×64
图片,如果不够自行拖拽画布到适宜比例后再调整。(画布调整直接拖动图片四周的线即可)
- 按
Ctrl+S
保存,保存选择格式为bmp
。
6.4使用液晶显示模块字模工具生成图片的数据
- 打开
液晶显示模块字模工具
- 点击打开图像图标找到刚才生成的bmp图片点击打开
- 点击取模方式–>点击C51即可。
6.5根据生成图片的数据建立图片数组
-
液晶显示模块字模工具生成的数据较大,需要用到code关键字,并且使用unsigned无符号内型数据。
-
图片数组代码
/*-- 调入了一幅图像:C:\Users\MaJinJun\Desktop\小车.bmp --*/
/*-- 宽度x高度=128x58 --*/
/*-- 宽度不是8的倍数,现调整为:宽度x高度=128x64 --*/
下面数组数据为128 * 8个,每个数组元素为8位
code unsigned char picture[] =
{
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,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,0x40,0xA0,
0xF0,0x50,0xA8,0xD8,0xD4,0x68,0x76,0xB6,0xBB,0x5B,0x5B,0x7D,0xAD,0xAD,0xAD,0xAF,
0xB6,0xB6,0x36,0xD6,0xB6,0xB6,0xAF,0xAD,0xAD,0x6D,0x7D,0x5B,0xDB,0xB7,0xB6,0x6A,
0xEC,0xD4,0xA8,0xF0,0xD0,0xA0,0x40,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,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,0x80,0xE8,0xFC,0xB6,0xFD,0xF6,0xBB,0xDD,
0xF6,0xBB,0xDD,0x6D,0xB6,0xDB,0x6D,0xAE,0x56,0x37,0x0B,0x1B,0x03,0x0D,0xFD,0x05,
0xFF,0xFF,0x00,0xFF,0xFF,0xFF,0x05,0xFD,0x0D,0x1B,0x1B,0x2B,0x76,0x56,0xAD,0x5D,
0xBB,0x76,0xED,0xDB,0x77,0xDF,0xBB,0xF6,0xFD,0xB6,0xE8,0xA0,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,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,0x40,0xC0,
0xA0,0x50,0xB0,0xA0,0xD8,0xD8,0xE8,0x6C,0x6E,0xB7,0xBD,0xFF,0xBB,0x7E,0x17,0x7D,
0x7F,0x6F,0x6D,0x6F,0x6D,0x6A,0x69,0x68,0x68,0x68,0x68,0x68,0x68,0x68,0x6F,0x68,
0x7F,0x7F,0x00,0xFF,0x7F,0x7F,0x68,0x6F,0x68,0x68,0x68,0x68,0x68,0x68,0x68,0x6B,
0x6E,0x6B,0x6E,0x6B,0x6F,0x7E,0x73,0x4E,0x7B,0xDF,0x7E,0xF7,0xDF,0xBA,0x50,0xA0,
0x40,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,0x40,0xA0,0x40,0x90,0xB4,0xDA,0xED,0x7E,0xDF,0x6D,
0xB6,0x5B,0x2B,0x15,0x0D,0x0A,0x04,0x03,0x03,0x00,0x01,0x01,0x00,0x01,0x00,0x01,
0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x2F,0x37,0x2F,0x2F,0x2F,0x2F,0x2F,0x2F,0x37,
0x2D,0x2F,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x17,0x2F,0x17,0x37,0x2F,
0x2F,0x2F,0x2F,0x2F,0x37,0x2D,0x37,0x00,0x01,0x02,0x0D,0x1A,0x75,0x5B,0x77,0xEE,
0xBF,0xF6,0xDD,0x72,0xD0,0xA0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x40,0xD0,0x7F,0xD5,0xFF,0x7F,0xB7,0xBF,0xBE,0xF7,0xFF,0x01,
0xF4,0x00,0x00,0x00,0xC0,0xA0,0xD0,0x68,0xA8,0xD0,0xEC,0x6C,0x74,0xB4,0xB4,0xB4,
0xB4,0xB4,0x74,0x6C,0xEC,0xD0,0xA8,0x58,0xD0,0xA0,0xC0,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x40,0xA0,0x58,0xA8,0xD8,0xEC,0x6C,0x74,0xB4,
0xB4,0xB4,0xB4,0xB4,0xB4,0x6C,0x6C,0xDC,0xD8,0xA8,0x50,0xA0,0x57,0x80,0xEF,0x77,
0xFF,0xED,0xBF,0xBF,0xB5,0xB7,0xFC,0xEC,0xB4,0xE8,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x17,0x5F,0xB5,0x7F,0xBF,0xB5,0xB7,0xB7,0xB4,0xBF,0xBF,0xB4,
0xB7,0xB4,0xB4,0xB5,0xB6,0xFB,0xFE,0xB7,0xFD,0x36,0xEB,0xF5,0x3A,0xED,0xED,0xED,
0xED,0xFD,0xFA,0xF5,0xDB,0xBE,0xFB,0xAF,0xFE,0xFB,0x6E,0x6D,0x68,0x68,0x68,0x68,
0x68,0x68,0x68,0x68,0x68,0x6C,0x6F,0xEB,0xFD,0x5F,0xFB,0xFD,0xDA,0xF5,0xFA,0xDD,
0xED,0xED,0xED,0xED,0xDF,0xFB,0xFF,0x5E,0xFD,0x7B,0xFF,0xFD,0x6F,0x6E,0x6F,0x68,
0x7F,0x7F,0x6D,0x6F,0x6F,0x68,0x7F,0xBF,0x68,0xBF,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x00,0x01,0x01,0x00,0x01,0x00,0x00,0x00,
0x00,0x00,0x00,0x17,0x5D,0xBB,0x6F,0xFD,0xB7,0x6F,0xDE,0xDB,0xB7,0xAE,0xAD,0xAD,
0xAD,0xB6,0xB7,0xDB,0xDE,0x6F,0xB7,0xDE,0x6F,0xBB,0x5F,0x17,0x01,0x01,0x01,0x01,
0x01,0x01,0x01,0x01,0x01,0x0B,0x2F,0x59,0xB7,0x5F,0xBB,0x77,0xEF,0xD5,0xDB,0xB6,
0xAF,0xAD,0xAD,0xAE,0xB6,0xDB,0xDD,0x6F,0x77,0xBD,0x7F,0xB7,0x5F,0x2F,0x03,0x01,
0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x02,0x03,0x01,0x02,0x02,0x01,0x01,0x01,0x01,
0x01,0x01,0x01,0x02,0x02,0x01,0x02,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x03,0x02,0x02,0x01,
0x01,0x01,0x01,0x01,0x01,0x02,0x02,0x01,0x03,0x02,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
};
6.6构造发送图片数据函数
-
构造图片数据函数的思路和清屏函数的思路基本一致,都是让数据从
Page0
填充到Page7
。但是发送图片数据函数需要发送的是8位
的数据,所以不能将内存循环变量j
简单的从0
开始,而是从i×128
开始,结束为128×(i+1)
。内层循环变量j定义为无符号的整型变量,外层信循环变量定义为无符号的字符型变量。其余都与清屏函数一致。 -
发送图片数据函数代码
void OLEDShowPicture(unsigned char *Pdata)
{
unsigned char i;
unsigned int j;
for(i=0; i<8; i++)
{
OledWriteCmd(0xB0 + i); //偏移Page
OledWriteCmd(0x00); //从第一列开始清屏
OledWriteCmd(0x10);
for(j=i*128; j<128*(i+1); j++)
{
OledWriteData(Pdata[j]);
}
}
}
6.7补充知识
BMP格式是一种无损的位图图像文件格式,全称为位图(Bitmap)图像文件格式。它通常用于Windows操作系统中,以存储图像数据的像素颜色信息。BMP文件以.bmp
为扩展名,可以存储单色、索引色、真彩色等不同类型的图像数据。每个像素的颜色信息都以RGB格式存储,使得BMP文件相对较大,但保留了图像的高质量和准确性。
6.8完整程序代码
#include "reg52.h"
#include "intrins.h"
sbit SCL = P0^1; //把SCL接单片机P0.1口
sbit SDA = P0^3; //把SDA接单片机P0.3口
/*-- 调入了一幅图像:C:\Users\MaJinJun\Desktop\小车.bmp --*/
/*-- 宽度x高度=128x58 --*/
/*-- 宽度不是8的倍数,现调整为:宽度x高度=128x64 --*/
code unsigned char picture[] =
{
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,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,0x40,0xA0,
0xF0,0x50,0xA8,0xD8,0xD4,0x68,0x76,0xB6,0xBB,0x5B,0x5B,0x7D,0xAD,0xAD,0xAD,0xAF,
0xB6,0xB6,0x36,0xD6,0xB6,0xB6,0xAF,0xAD,0xAD,0x6D,0x7D,0x5B,0xDB,0xB7,0xB6,0x6A,
0xEC,0xD4,0xA8,0xF0,0xD0,0xA0,0x40,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,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,0x80,0xE8,0xFC,0xB6,0xFD,0xF6,0xBB,0xDD,
0xF6,0xBB,0xDD,0x6D,0xB6,0xDB,0x6D,0xAE,0x56,0x37,0x0B,0x1B,0x03,0x0D,0xFD,0x05,
0xFF,0xFF,0x00,0xFF,0xFF,0xFF,0x05,0xFD,0x0D,0x1B,0x1B,0x2B,0x76,0x56,0xAD,0x5D,
0xBB,0x76,0xED,0xDB,0x77,0xDF,0xBB,0xF6,0xFD,0xB6,0xE8,0xA0,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,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,0x40,0xC0,
0xA0,0x50,0xB0,0xA0,0xD8,0xD8,0xE8,0x6C,0x6E,0xB7,0xBD,0xFF,0xBB,0x7E,0x17,0x7D,
0x7F,0x6F,0x6D,0x6F,0x6D,0x6A,0x69,0x68,0x68,0x68,0x68,0x68,0x68,0x68,0x6F,0x68,
0x7F,0x7F,0x00,0xFF,0x7F,0x7F,0x68,0x6F,0x68,0x68,0x68,0x68,0x68,0x68,0x68,0x6B,
0x6E,0x6B,0x6E,0x6B,0x6F,0x7E,0x73,0x4E,0x7B,0xDF,0x7E,0xF7,0xDF,0xBA,0x50,0xA0,
0x40,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,0x40,0xA0,0x40,0x90,0xB4,0xDA,0xED,0x7E,0xDF,0x6D,
0xB6,0x5B,0x2B,0x15,0x0D,0x0A,0x04,0x03,0x03,0x00,0x01,0x01,0x00,0x01,0x00,0x01,
0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x2F,0x37,0x2F,0x2F,0x2F,0x2F,0x2F,0x2F,0x37,
0x2D,0x2F,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x17,0x2F,0x17,0x37,0x2F,
0x2F,0x2F,0x2F,0x2F,0x37,0x2D,0x37,0x00,0x01,0x02,0x0D,0x1A,0x75,0x5B,0x77,0xEE,
0xBF,0xF6,0xDD,0x72,0xD0,0xA0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x40,0xD0,0x7F,0xD5,0xFF,0x7F,0xB7,0xBF,0xBE,0xF7,0xFF,0x01,
0xF4,0x00,0x00,0x00,0xC0,0xA0,0xD0,0x68,0xA8,0xD0,0xEC,0x6C,0x74,0xB4,0xB4,0xB4,
0xB4,0xB4,0x74,0x6C,0xEC,0xD0,0xA8,0x58,0xD0,0xA0,0xC0,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x40,0xA0,0x58,0xA8,0xD8,0xEC,0x6C,0x74,0xB4,
0xB4,0xB4,0xB4,0xB4,0xB4,0x6C,0x6C,0xDC,0xD8,0xA8,0x50,0xA0,0x57,0x80,0xEF,0x77,
0xFF,0xED,0xBF,0xBF,0xB5,0xB7,0xFC,0xEC,0xB4,0xE8,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x17,0x5F,0xB5,0x7F,0xBF,0xB5,0xB7,0xB7,0xB4,0xBF,0xBF,0xB4,
0xB7,0xB4,0xB4,0xB5,0xB6,0xFB,0xFE,0xB7,0xFD,0x36,0xEB,0xF5,0x3A,0xED,0xED,0xED,
0xED,0xFD,0xFA,0xF5,0xDB,0xBE,0xFB,0xAF,0xFE,0xFB,0x6E,0x6D,0x68,0x68,0x68,0x68,
0x68,0x68,0x68,0x68,0x68,0x6C,0x6F,0xEB,0xFD,0x5F,0xFB,0xFD,0xDA,0xF5,0xFA,0xDD,
0xED,0xED,0xED,0xED,0xDF,0xFB,0xFF,0x5E,0xFD,0x7B,0xFF,0xFD,0x6F,0x6E,0x6F,0x68,
0x7F,0x7F,0x6D,0x6F,0x6F,0x68,0x7F,0xBF,0x68,0xBF,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x00,0x01,0x01,0x00,0x01,0x00,0x00,0x00,
0x00,0x00,0x00,0x17,0x5D,0xBB,0x6F,0xFD,0xB7,0x6F,0xDE,0xDB,0xB7,0xAE,0xAD,0xAD,
0xAD,0xB6,0xB7,0xDB,0xDE,0x6F,0xB7,0xDE,0x6F,0xBB,0x5F,0x17,0x01,0x01,0x01,0x01,
0x01,0x01,0x01,0x01,0x01,0x0B,0x2F,0x59,0xB7,0x5F,0xBB,0x77,0xEF,0xD5,0xDB,0xB6,
0xAF,0xAD,0xAD,0xAE,0xB6,0xDB,0xDD,0x6F,0x77,0xBD,0x7F,0xB7,0x5F,0x2F,0x03,0x01,
0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x02,0x03,0x01,0x02,0x02,0x01,0x01,0x01,0x01,
0x01,0x01,0x01,0x02,0x02,0x01,0x02,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x03,0x02,0x02,0x01,
0x01,0x01,0x01,0x01,0x01,0x02,0x02,0x01,0x03,0x02,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
};
void IICStart() //IIC起始信号函数
{
SCL = 0; //防止雪花
SDA = 1; //根据起始信号时序图阴影部分,SDA先是高电平
SCL = 1; //根据起始信号时序图,SCL一直为高电平
_nop_(); //_nop_()寒素执行时间为5微秒,并不是1微秒,原因是调用函数时有进出栈操作
//此时在这里,根据起始信号时序图可知需要延时》4.7微秒
SDA = 0; //根据起始信号时序图阴影部分,SDA此时为低电平
_nop_(); //延时5微秒
}
void IICStop() //IIC终止信号函数
{
SCL = 0; //防止雪花
SDA = 0; //根据起始信号时序图阴影部分,SDA先是低电平
SCL = 1; //根据起始信号时序图,SCL一直为高电平
_nop_(); //延时5微秒
SDA = 1; //根据起始信号时序图阴影部分,SDA此时为高电平
_nop_(); //延时5微秒
}
char IIC_ACK()
{
char flag;
SDA = 1; //释放数据线
_nop_();
SCL = 1;
_nop_();
flag = SDA;
_nop_();
SCL = 0;
_nop_();
return flag;
}
void IICSendByte(char cdata)
{
char i;
for(i=0; i<8; i++ )
{
SCL = 0; //scl拉低,让sda做好数据准备
SDA = cdata & 0x80; //0x80 = 1000 0000获得cdata的最高位,给sda
_nop_(); //发送建立数据时间
SCL = 1; //SCL被拉高开始发送数据
_nop_(); //数据发送时间
SCL = 0; //发送完数据被拉低
_nop_();
cdata = cdata << 1;
}
}
void OledWriteCmd(char Cmd)
{
//1.start
IICStart();
//2.写入从机地址 b0111 1000 0x78
IICSendByte(0x78);
//3.ACK
IIC_ACK();
//4.cotrol byte: (0)(0)000000 写入命令 (0)(1)000000写入数据
IICSendByte(0x00);
//5.ACK
IIC_ACK();
//6. 写入指令/数据
IICSendByte(Cmd);
//7.ACK
IIC_ACK();
//8.STOP
IICStop();
}
void OledWriteData(char Data)
{
//1.start
IICStart();
//2.写入从机地址 b0111 1000 0x78
IICSendByte(0x78);
//3.ACK
IIC_ACK();
//4.cotrol byte: (0)(0)000000 写入命令 (0)(1)000000写入数据
IICSendByte(0x40);
//5.ACK
IIC_ACK();
//6. 写入指令/数据
IICSendByte(Data);
//7.ACK
IIC_ACK();
//8.STOP
IICStop();
}
void initOLED()
{
//( 01) display off (0xae)
OledWriteCmd(0xae);
//( 02) set low column address (0x00)
OledWriteCmd(0x00);
//( 03) set high column address (0x10)
OledWriteCmd(0x10);
//( 04) set start line address (0x40)
OledWriteCmd(0x40);
//( 05) set page address (0xb0)
OledWriteCmd(0xb0);
//( 06) contract control (0x81)
OledWriteCmd(0x81);
//( 07) send 0xff (多字节指令)
OledWriteCmd(0xff);
//( 08) set segment remap (0xa1)
OledWriteCmd(0xa1);
//( 09) set normal/reverse (0xa6)
OledWriteCmd(0xa6);
//( 10) set multiplex ratio (1 to 64) (0xa8 )
OledWriteCmd(0xa8);
//( 11) set duty 1/32 (0x3f)
OledWriteCmd(0x3f);
//( 12) com scan direction (0xc8)
OledWriteCmd(0xc8);
//( 13) set display offset (0xd3)
OledWriteCmd(0xd3);
//( 14) send 0x00
OledWriteCmd(0x00);
//( 15) set osc division (0xd5)
OledWriteCmd(0xd5);
//( 16) send 0x80
OledWriteCmd(0x80);
//( 17) set area color mode off (0xd8)
OledWriteCmd(0xd8);
//( 18) send 0x05
OledWriteCmd(0x05);
//( 19) set pre-charge period (0xd9)
OledWriteCmd(0xd9);
//( 20) send 0xf1
OledWriteCmd(0xf1);
//( 21) set com pin configuration (0xda)
OledWriteCmd(0xda);
//( 22) send 0x12
OledWriteCmd(0x12);
//( 23) set Vcomh (0xdb)
OledWriteCmd(0xdb);
//( 24) send 0x30
OledWriteCmd(0x30);
//( 25) set charge pump enable (0x8d)
OledWriteCmd(0x8d);
//( 26) send 0x14
OledWriteCmd(0x14);
//( 27) turn on oled panel(0xaf)
OledWriteCmd(0xaf);
}
void OLEDClearScreen()
{
unsigned char i; //使用无符号的字符型变量i,j的作用是防止内存越界。因为
unsigned char j; //有符号的字符型数据只能表示 -128~127,会在内层for中越界
for(i=0; i<8; i++)
{
OledWriteCmd(0xB0 + i); //偏移Page
OledWriteCmd(0x00); //从第一列开始清屏
OledWriteCmd(0x10);
for(j=0; j<128; j++) //列地址自动偏移
{
OledWriteData(0); //写入清屏数据0
}
}
}
void OLEDShowPicture(unsigned char *Pdata)
{
unsigned char i; //防止内存越界
unsigned int j; //防止内存越界
for(i=0; i<8; i++)
{
OledWriteCmd(0xB0 + i); //偏移Page
OledWriteCmd(0x00); //从第一列开始清屏
OledWriteCmd(0x10);
/*
发送图片数据函数需要发送的是`8位`的数据,所以不能将内存循环变量`j`简单的从`0`开始,
而是从`i×128`开始,结束为`128×(i+1)`。
*/
for(j=i*128; j<128*(i+1); j++)
{
OledWriteData(Pdata[j]);
}
}
}
void main()
{
//1.初始化OLED
initOLED();
//2.选择一个位置
//2.1确认页寻址模式
OledWriteCmd(0x20);
OledWriteCmd(0x02);
OLEDClearScreen();
//2.2确认那个page显示,page 0
//写马哥成长记字符的上半部分
OledWriteCmd(0xB0);
OledWriteCmd(0x00);
OledWriteCmd(0x10);
OLEDShowPicture(picture);
//防止主函数退出
while(1);
}
结束语
很高兴您能看到这里,点个赞再走呗。谢谢您啦!!!