1 芯片介绍
1.1 硬件连接图
该芯片的型号为SH1106,通讯方式有几种类型,这里选用的是I2C通信,其连接如下图所示:
参考洋桃电子家的电路图:
左下角的LM75a是温度传感器,不用看。这里我也没看懂这里的电路图,感觉和数据手册的电路图不太匹配。
1.2 OLED0561屏行列地址
该屏有13264(列行)的像素点,实际边上只有128列,估计是为显示不要太靠边了,不然不好看吧。
英文显示的像素点为88,但为了和汉字对齐,为了美观,通常用816的像素点,汉字用1616,所以12864的像素点只能显示164个英文字母,或者84个汉字,即4行16个英文字母或4行8个汉字。
关于行列地址的划分,该芯片还有另外的讲究,参考数据手册中的行列地址的说明。
在ADC这个位为0时,SEG0-SEG131的地址是从0x0-0x83,若ADC=1时,地址是从0x83-0x0,此外这个还能设置滚动的效果。
它这里说其实显示的地址是从1D(H)开始的,参照下面的图可以发现,好像确实是这样。
根据箭头的方向可以看到滚动的方向,放大局部可以看滚动的起始位置确实是从1D(H)开始的,它这里标的是1CH,但这里想表达的意思应该是已经滚动一行之后的地址,具体的情况可以在写代码的时候调试一下。从这里也可以看到滚动的方向是向上滚动的。这里1D(H)对应的行数是PAGE3,之后试一下效果。
从局部可以发现数据D0-D7共8位组成一个PAGE,也就是说64行对应64位数据,可以组成8个PAGE,这里对应着PAGE0-PAGE7,地址是由D0-D3组成的从0000-0007。列是被分为了128列,地址从00(H)-83(H),对应着SEG0-SEG131。
具体的列地址看数据手册
列地址的选择是由两个字节来决定的,Higher bits和Lower bits,Highter bits决定着A4-A7,Lower bits决定着A0-A3,Higher bits的高4位为0001,Lower bits的高4位为0000。所以在发送列地址时,应该发送Higher bits:0x10-0x1F,和Lower bits:0x00-0x0F。
行地址的选取:
1.3 指令控制集
除了上述的行列地址的选取,此外还有很多另外的指令集。
-
设置电压值(0x30-0x33)
这个是用来设置内部电荷的,不知道有啥用。
-
设置显示的初始行(0x40-0x3f)
当改变这个值时,将发生平滑滚动或页面更改。刚开始以为这个是行地址选取,有点懵,后来发现这个不是。
-
设置对比度寄存器(双字节)
这个是通过调节电流的大小来调节显示屏幕的亮度的,发送时得发送两个字节。电流大小的计算公式为:
ISEG = a/256 X IREF X scale factor
其中a为往寄存器设置的值,范围为00-FF(H),IREF是参考电流为12.5uA,scale factor=16。
设置对比度命令为0x81(10000001)。
对比度设置:0x00-0xFF
-
设置段区重映射(0xa0/0xa1)
这里根据描述应该是显示内容旋转。
-
设置开关(0xa4/0xa5)
A4为关,A5为开。
-
正常/反转显示(A6/A7)
即当D=0时,写入ram的数据为1,则OLED的灯亮,当D=1时,写入ram的数据为0,则OLED的灯亮。正常显示时,是ram里的数据为1时,灯亮。 -
设置多路复用(双字节)(A8,00-3F)
这个是用来设置行数使用的多少,比如设置的是31,则表示使用的是前32行(0-31)。代码设置的是0x3F,对应的Multiplex Ratio为64。
-
设置DC-DC控制(双字节)
在设置这个命令时,需要把显示面板关闭。
-
显示打开和关闭(AF/AE)
这个还有一个睡眠模式。
-
设置显示方向(C0/C8)
这个是设置行的方向。
-
设置显示偏移(双字节0xd3, 0x00-0x3f)
偏移了对显示好像没啥用,也不知道干啥
-
设置显示时钟的分频/晶振频率(双字节)
A0-A3是设置时钟的分频,A4-A7是用来设置晶振的频率。
-
设置放电/预充电周期(双字节)
-
设置COM的排列顺序
这个应该和硬件的COM的布局有关。设置为0x02时,COM应该是按31,30—1,0,32,33—62,63布局。设置为0x12时,COM应该是62,60—2,0,1,3—61,63。 -
Set VCOM Deselect Level(双字节)
这个感觉是设置输出电压的。 -
Read-Modify-Write: (E0H)
-
End(EE(H))
从16-19不知道为啥没有用到。估计是跟IIC的通信方式有关吧。
1.4 实际应用
u8 buf[22]={
0xae,//0xae:关显示,0xaf:开显示
//设置内部电荷值,这里设置8.0
0x32,
//设置初始行(0x40-0x3f)
//感觉这里不用设置
//设置对比度(双字节),这里设置为FF吧,对比度最高
0x81, 0xff,
//设置列从那边开始显示(0xa0/0xa1)
0xa1,
//DC-DC控制
//感觉这里不用设置
//设置开/关A5/A4,这里A5是整体点亮,A4是正常显示
0xa4,
//设置数据显示的方式,正常为数据为1,灯亮(0xa6/0xa7)
0xa6,
//设置使用那几行,正常来说整屏要使用(双字节,0xa8, 00-0x3f)
0xa8, 0x3f,
//设置行从上/下开始显示(C0/C8)
0xc8,
//设置显示偏移(双字节,0xd3,0x00-0x3f)
0xd3, 0x00,
//设置时频的分频和晶振频率(双字节0xd5, 0x00-0xff)
0xd5, 0x50,
//设置放电/预充电周期(双字节,0xd9, 0x00-0xff)
0xd9, 0x22,
//设置COM排列顺序(双字节,0xda, 0x02/0x12)
0xda, 0x12,
//Set VCOM Deselect Level(双字节,0xdb,0x00-0xff),不知道啥意思,乱设置一个
0xdb, 0x01,
0xaf//0xae:关显示,0xaf:开显示
}; //
初始化成功。
void OLED_DISPLAY_OFF (void){
//OLED屏初始值设置并开显示
u8 buf[3]={
0xae,//0xae:关显示,0xaf:开显示
0x8d,0x10//VCC电源
}; //
I2C_SAND_BUFFER(0x78,0x00,buf,3);
}
void OLED_DISPLAY_CLEAR(void)
{
u8 row,col;
for(row = 0xB0; row < 0xB8; row++)
{
//行地址
I2C_SAND_BYTE(0x78, 0x00, row);
//列地址,这里只用给起始地址
I2C_SAND_BYTE(0x78, 0x00, 0x10);
I2C_SAND_BYTE(0x78, 0x00, 0x00);
//写入数据
for(col = 0; col < 132; col++)
{
I2C_SAND_BYTE(0x78, 0x40, 0x00);
}
}
}
void OLED0561_Init (void){//OLED屏开显示初始化
OLED_DISPLAY_OFF(); //OLED关显示
OLED_DISPLAY_CLEAR(); //清空屏幕内容
OLED_DISPLAY_ON(); //OLED屏初始值设置并开显示
//I2C_SAND_BYTE(0x78, 0x00, 0xa5);
}
void OLDE0561_DISPLAY(u8 oled_row, u8 oled_col, u16 len)//oled_row1-4行,oled_col为1-8列
{
u8 row, col;
/遍历两次,第一次遍历完之后数据的位数是8*16(高*宽),即显示屏的第一行,第二次遍历是16*16,即显示屏的第二行
for(row = 0; row < 2; row++)
{
//行地址
I2C_SAND_BYTE(0x78, 0x00, 2*(oled_row-1)+row+0xB0);
//列地址,这里只用给起始地址
I2C_SAND_BYTE(0x78, 0x00, 0x10+oled_col);//高位,高位加1,相当于列数加16列
I2C_SAND_BYTE(0x78, 0x00, 0x00);//低位,低位加1,相当于列数加1列
//写入数据,第一次遍历前16个数据,第二次遍历后16个数据
for(col = 0; col < 16; col++)
{
if(row == 1)
{
I2C_SAND_BYTE(0x78,0x40,picture[(len-1)*32+16+col]);
}
if(row == 0)
{
I2C_SAND_BYTE(0x78,0x40,picture[(len-1)*32+col]);
}
}
}
I2C_SAND_BYTE(0x78, 0x00, 0xaf);
}