最近入手了一块0.96寸的oled,一直在用给的例程,想自己从底层写一下驱动,了解oled的初始化流程和控制
注:本文只涉及oled的初始化,如果需要显示GUI或者图片,汉字,需要使用库或者自己更进一步折腾。
============================================================
接下来是SSD1306的初始化,我们使用SPI总线(SSD1306可以通过配置特定引脚电平来设置对外接口模式,有8080,IIC,SPI)。使用的屏幕的接线如图:D/C标志数据/命令,RES是复位,D0-CLK,D1-DATA(接spi主机的MOSI)
然后是传输时序的要求,可以看到SSD1306在时钟上升沿采集数据,并且高位在前,这关系到之后STM32的配置:
4.程序编写
首先配置STM32的SPI外设,构建一个能传输指令和数据的函数,这里就不在赘述,函数原型如下
void OLED_WRITE(uint8_t data,uint8_t cmd)
{
if(cmd==0)// 写命令
{
DC_LOW();
SPI_senddata( data);
DC_HIGH();
}
else if(cmd==1)//写数据
{
DC_HIGH();
SPI_senddata( data);
}
}
其次是构建一个虚拟缓存,
unsigned char GDDRAM[8][128]
构建一个显存更新函数,每次向SSD1306的显存中更新这个数组的值,而在程序中就只需要对数组做操作。
构建功能函数,包括1:显存更新函数
void OLED_Refresh_Gram(void)
{
uint8_t i,n;
for(i=0;i<8;i++)
{
OLED_WRITE(0xB0+i,CMD); //设置页地址(0~7)每页中的GDDRAM列地址是自动增加的。
OLED_WRITE(0x00,CMD); //设置显示开始位置—列低地址
OLED_WRITE(0x10,CMD); //设置显示开始位置—列高地址
for(n=0;n<128;n++)
{
OLED_WRITE(GDDRAM[i][n],DATA); //#define OLED_DATA 1 //写数据
}
}
}
2:控制显示开关
void OLED_Display_Off(void)
{
OLED_WRITE(0x8D,CMD); //SET DCDC命令
OLED_WRITE(0x10,CMD); //DCDC OFF
OLED_WRITE(0xAE,CMD); //DISPLAY OFF
}
void OLED_Display_On(void)
{
OLED_WRITE(0x8D,CMD); //SET DCDC命令
OLED_WRITE(0x14,CMD); //DCDC ON
OLED_WRITE(0xAF,CMD); //DISPLAY ON
}
最后是初始化指令,具体的指令表可以去下载SSD1306的数据手册,这里直接给出初始化的指令序列
void OLED_init0(void)
{
uint8_t i;
OLED_RES_LOW();//复位一次
for(i=0;i<100;i++);
OLED_RES_HIGH();
OLED_WRITE(0xAE,CMD); //关闭显示
OLED_WRITE(0xD5,CMD); //设置时钟分频因子,震荡频率
OLED_WRITE(0x50,CMD); //[3:0],分频因子;[7:4],震荡频率
OLED_WRITE(0xA8,CMD); //设置驱动路数
OLED_WRITE(0x3F,CMD); //默认0X3F(1/64)
OLED_WRITE(0xD3,CMD); //设置显示偏移
OLED_WRITE(0x00,CMD); //默认为0
OLED_WRITE(0x40,CMD); //设置显示开始行 [5:0],行数.
OLED_WRITE(0x8D,CMD); //电荷泵设置
OLED_WRITE(0x14,CMD); //bit2,开启/关闭
OLED_WRITE(0x20,CMD); //设置内存寻址模式
OLED_WRITE(0x02,CMD); //[1:0],00,列地址模式;01,行地址模式;10,页地址模式;默认10;
OLED_WRITE(0xA1,CMD); //段重定义设置,bit0: 0,column 0->SEG 0; 1,column 0->SEG 127;
OLED_WRITE(0xC8,CMD); //设置COM扫描方向;bit3:0,普通模式;1,重定义模式 COM[N-1]->COM0;N:驱动路数
OLED_WRITE(0xDA,CMD); //设置COM硬件引脚配置 [5:4]配置 配置COM(SSD1306)与ROW(液晶)的连接关系
OLED_WRITE(0x12,CMD); //[5:4]配置 配置COM(SSD1306)与ROW(液晶)的连接关系
OLED_WRITE(0x81,CMD); //对比度设置
OLED_WRITE(0xEF,CMD); //1~255;默认0X7F (亮度设置,越大越亮)
OLED_WRITE(0xD9,CMD); //设置预充电周期
OLED_WRITE(0xF1,CMD); //[3:0],PHASE 1;[7:4],PHASE 2;
OLED_WRITE(0xDB,CMD); //设置VCOMH 电压倍率
OLED_WRITE(0x30,CMD); //[6:4] 000,0.65*vcc;001,0.77*vcc;011,0.83*vcc;
OLED_WRITE(0xA4,CMD); //全局显示开启;bit0:1,开启;0,关闭;(白屏/黑屏)
OLED_WRITE(0xA6,CMD); //设置显示方式;bit0:1,反相显示;0,正常显示
OLED_WRITE(0xAF,CMD); //开启显示
}
至此oled已经初始化完成,可以向虚拟显存数组中写入数据,然后更新至SSD1306内部,最后控制开启显示即可。
OLED_Refresh_Gram(); //更新显存
OLED_Display_On(); //开启显示
最后,这种构建虚拟显存的方式会占用较多的单片机内部存储空间,对于内存容量较小的单片机就需要考虑换种方式。