0.96寸OLED驱动(基于STM32f103)

最近入手了一块0.96寸的oled,一直在用给的例程,想自己从底层写一下驱动,了解oled的初始化流程和控制
注:本文只涉及oled的初始化,如果需要显示GUI或者图片,汉字,需要使用库或者自己更进一步折腾。
============================================================
  1. 硬件简介
    STM32f103ZET6,使用硬件SPI1。
    OLED:
    中景园0.96寸OLED,3线SPI
    淘宝给的oled介绍

  2. 驱动芯片SSD1306
    首先是SSD1306内部的GDDRAM,大小是128*64,即128列64行。显存区域被分成8页,每页128段,每段是一个字节,如下图。显存分页
    每页分段

接下来是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();	//开启显示

最后,这种构建虚拟显存的方式会占用较多的单片机内部存储空间,对于内存容量较小的单片机就需要考虑换种方式。

猜你喜欢

转载自blog.csdn.net/weixin_42415539/article/details/85212043