通常我们所用的OLED屏有白色、蓝色、黄蓝双色等几种;屏的大小为0.96寸,像素点为128*64,所以我们也称之为0.96OLED屏或者12864屏。
内部驱动IC为SSD1306;通信方式一般为SPI或者I2C。如下图所示,配置哪种模式主要是根据BS0、BS1和BS2这三个管脚的电平逻辑来的。
如手册上关于I2C地址的描述,根据DC引脚电平的不同,地址为,0111100和0111101两种,通常我们设置DC引脚接地,所以作为I2C从机的七位地址为0111100;又因为我们与驱动IC交互时,都是主机发送命令或者数据到IC,也就是只有写数据,没有读数据,所以从机地址为0x78。
通信方式如上图所示:先发送从机地址,再发送命令字节,接着发送数据字节。注意每次主机要等待从机的应答。下图为写命令和写数据的代码示例。
/**********************************************
// IIC Write Command
**********************************************/
void Write_IIC_Command(unsigned char IIC_Command)
{
IIC_Start();
Write_IIC_Byte(0x78); //Slave address,SA0=0
IIC_Wait_Ack();
Write_IIC_Byte(0x00); //write command
IIC_Wait_Ack();
Write_IIC_Byte(IIC_Command);
IIC_Wait_Ack();
IIC_Stop();
}
/**********************************************
// IIC Write Data
**********************************************/
void Write_IIC_Data(unsigned char IIC_Data)
{
IIC_Start();
Write_IIC_Byte(0x78); //D/C#=0; R/W#=0
IIC_Wait_Ack();
Write_IIC_Byte(0x40); //write data
IIC_Wait_Ack();
Write_IIC_Byte(IIC_Data);
IIC_Wait_Ack();
IIC_Stop();
}
先来看关于OLED的显存分布情况。我们可以理解为:水平方向分布了128个像素点,垂直方向分布了64个像素点(如图一所示)。而驱动芯片在点亮像素点的时候,是以8个像素点为单位的。官方的例程推荐的是垂直扫描的方式,也就是先画垂直方向的8个像素点(如下图二所示),所以我们在画点的时候Y的取值为0-7,X的取值为0-127.
//存放格式如下.
//[0]0 1 2 3 ... 127
//[1]0 1 2 3 ... 127
//[2]0 1 2 3 ... 127
//[3]0 1 2 3 ... 127
//[4]0 1 2 3 ... 127
//[5]0 1 2 3 ... 127
//[6]0 1 2 3 ... 127
//[7]0 1 2 3 ... 127
图一
图二
理解了OLED的显示方式,那么取模就很简单了,根据上面的情况,我们选择列行式的取模方式,如下图所示。
取模完成,我们再来看看画点的算法。其实就是根据取模的方式按顺序画点,先画Y方向的八个点,再画X方向的128个点。以显示汉字为例,来分析一下
/***************************************************************
X:X坐标 Y:Y方向的页数 no:取模的汉字的序号
你(0) 好(1)
{0x00,0x80,0x60,0xF8,0x07,0x40,0x20,0x18,0x0F,0x08,0xC8,0x08,0x08,0x28,0x18,0x00},
{0x01,0x00,0x00,0xFF,0x00,0x10,0x0C,0x03,0x40,0x80,0x7F,0x00,0x01,0x06,0x18,0x00},/*"你",0*/
{0x10,0x10,0xF0,0x1F,0x10,0xF0,0x00,0x80,0x82,0x82,0xE2,0x92,0x8A,0x86,0x80,0x00},
{0x40,0x22,0x15,0x08,0x16,0x61,0x00,0x00,0x40,0x80,0x7F,0x00,0x00,0x00,0x00,0x00},/*"好",1*/
****************************************************************/
void tt_Oled_ShowChinese(unsigned char x,unsigned char y,unsigned char no)
{
UINT8 t;
tt_Oled_Set_Pos(x,y);
for(t=0;t<16;t++){
tt_Oled_WR_Byte(dis_word[2*no][t],OLED_DATA);
}
tt_Oled_Set_Pos(x,y+1);
for(t=0;t<16;t++){
tt_Oled_WR_Byte(dis_word[2*no+1][t],OLED_DATA);
}
}
因为我们的汉字大小是16*16的,所以会占两页,按照上面的分析,先画的是第一页(16*8个点),对应tt_Oled_WR_Byte(dis_word[2*no][t],OLED_DATA);,接着画第二页(16*8个点))tt_Oled_WR_Byte(dis_word[2*no][t],OLED_DATA);这样画完后我们就完成了一个汉字的显示(16*16)。怎么样,是不是很简单?
网上关于OLED的显示例程很多,基本都大同小异,一般选一个移植,再根据我上面的设置,显示字符、汉字甚至图片都是没有问题的。但是我们这些显示都是静态的,那怎么显示动态的呢?例如水平滚动,垂直滚动,斜向滚动等等。其实这些本质上都是画点的顺序不同而已,我们先来看看手册上的描述,如下图
垂直和水平滚动显示设置 垂直和水平滚动显示设置举例根据手册我们知道,设置2A(向左滚动)和29(向右滚动)以及之后的五个数,就可以设置水平和垂直滚动的效果了。需要注意的是设置前需要先关滚动,当需要显示的内容刷新好之后再开启滚动。以下是我代码的设置:
//以下添加水平滚动效果
tt_Oled_WR_Byte(0x2e,OLED_CMD);//关滚动
tt_Oled_WR_Byte(0x2A,OLED_CMD);//29向右,2a向左
tt_Oled_WR_Byte(0x00,OLED_CMD);//A:空字节
tt_Oled_WR_Byte(0x00,OLED_CMD);//B:水平起始页
tt_Oled_WR_Byte(0x00,OLED_CMD);//C:水平滚动速度
tt_Oled_WR_Byte(0x01,OLED_CMD);//D:水平结束页
tt_Oled_WR_Byte(0x00,OLED_CMD);//E:每次垂直滚动位移
//tt_Oled_WR_Byte(0x2f,OLED_CMD);//开滚动
备注:1. 本文章是个人总结,如有不足之处欢迎指正;
2. 部分参考内容来源于手册和网络,如有侵权请联系我删除。