CH582、CH592、CH584芯片SPI实例讲解 硬件SPI驱动OLED显示屏

一、SPI接口简介

SPI(Serial Peripheral Interface)是一种高速全双工同步串行通信总线,广泛应用于嵌入式系统中连接外设与微控制器。以下从核心特性、硬件结构、通信模式等方面进行详细介绍:

一)、核心特性

  1. 同步串行传输‌:通过SCK时钟信号同步数据传输,支持全双工通信(同时收发数据)‌。
  2. 主从架构‌:仅支持单主设备控制多个从设备,主设备生成时钟信号(SCK)和片选信号(CS)‌。
  3. 高速灵活‌:传输速率可达数十Mbps,数据长度可自定义,且通过配置时钟极性(CPOL)和相位(CPHA)支持4种传输模式‌。

二)、硬件接口

SPI仅需4根信号线:

  • SCK‌:时钟信号,由主设备生成‌。
  • MOSI‌:主设备输出/从设备输入‌。
  • MISO‌:主设备输入/从设备输出‌。
  • CS‌:片选信号,低电平有效,用于选择目标从设备‌。

三)、通信流程

  1. 初始化‌:主设备拉低目标从设备的CS信号激活通信‌。
  2. 数据传输‌:SCK的每个上升沿/下降沿触发数据采样(取决于CPOL/CPHA配置)‌。
  3. 终止‌:主设备拉高CS信号结束通信‌。

四)、优缺点

五)、CH592SPI简介

  • 优势‌:硬件简单、传输速率高、支持多设备(需独立CS引脚)‌。
  • 局限‌:传输距离短(通常<10米)、无内置错误检测机制‌

CH582、CH584的SPI接口与CH592差不多,大家可以参考官方提供的规格书及例程。

二、SSD1306驱动OLED屏接口说明

我们以中景园电子的7Pin0.96OLED屏为例。

SSD1306为驱动的OLED屏可以支持多种接口,比如4-wire SPI、3-wire SPI、IIC等,本实例使用的7PinOLED,是4-wire SPI接口,3-wire SPI接口与4-wire SPI接口相比,少了D/C#引脚,所以在发送的数据中也会有所差异,如下图所示:

具体的区别大家可以参考对应产品的规格书,而且一般情况下,厂家都会提供Demo程序,参考Demo程序修改一下,应该就能正常使用。

三、硬件连接

|---------|-------------------|
| OLED显示屏 | CH582/CH592/CH584 |
| D0 | PA13 (CLK) |
| D1 | PA14 (MOSI) |
| RES | PA4 |
| DC | PA5 |
| CS | PA7 |

四、代码及简要说明

我们的代码支持硬件SPI协议及软件模拟SPI协议两种方式,大家只需要简单修改下图代码就可以切换两种方式。

cpp 复制代码
#ifndef __OLED_H
#define __OLED_H			  	 
#include "HAL.h"
 
#define PAGE_SIZE    8
#define XLevelL		   0x02
#define XLevelH		   0x10
#define YLevel       0xB0
#define	Brightness	 0xFF 
#define WIDTH 	     128
#define HEIGHT 	     64	

typedef  uint8_t u8;
typedef  uint16_t u16;
typedef  uint32_t u32;

enum{
	OLED_CMD = 0,
	OLED_DATA
};
#ifndef OLED_USE_SPI
//#define OLED_USE_SPI
#endif

#define delay_ms(x) DelayMs(x)

#if 1
#define OLED_CS   BV(12)   //7 Pin OLED屏CS
#define OLED_DC   BV(5)   //7 Pin OLED屏DC
#define OLED_RST  BV(4)   //7 Pin OLED屏RST
#define OLED_MOSI BV(14)  //7 Pin OLED屏D1/MOSI
#define OLED_CLK  BV(13)  //7 Pin OLED屏D0/CLK

#define OLED_CS_OUT   (R32_PA_OUT)   //7 Pin OLED屏CS
#define OLED_DC_OUT   (R32_PA_OUT)  //7 Pin OLED屏DC
#define OLED_RST_OUT  (R32_PA_OUT)   //7 Pin OLED屏RST
#define OLED_MOSI_OUT (R32_PA_OUT)  //7 Pin OLED屏D1/MOSI
#define OLED_CLK_OUT  (R32_PA_OUT)  //7 Pin OLED屏D0/CLK
#define OLED_OUT      (R32_PA_OUT)
#define OLED_PD_DRV   (R32_PA_PD_DRV)

#define OLED_CS_DIR   (R32_PA_DIR |= OLED_CS)   //7 Pin OLED屏CS
#define OLED_DC_DIR   (R32_PA_DIR |= OLED_DC)   //7 Pin OLED屏DC
#define OLED_RST_DIR  (R32_PA_DIR |= OLED_RST)   //7 Pin OLED屏RST
#define OLED_MOSI_DIR (R32_PA_DIR |= OLED_MOSI)  //7 Pin OLED屏D1/MOSI
#define OLED_CLK_DIR  (R32_PA_DIR |= OLED_CLK)  //7 Pin OLED屏D0/CLK


#if 1
#define OLED_CS_Clr()  (OLED_CS_OUT &= (~OLED_CS))
#define OLED_CS_Set()  (OLED_CS_OUT |= OLED_CS)

#define OLED_DC_Clr()  (OLED_DC_OUT &= (~OLED_DC))
#define OLED_DC_Set()  (OLED_DC_OUT |= OLED_DC)
 					   
#define OLED_RST_Clr()  (OLED_RST_OUT &= (~OLED_RST))
#define OLED_RST_Set()  (OLED_RST_OUT |= OLED_RST)
						 
#define	OLED_MOSI_Clr()  	(OLED_MOSI_OUT &= (~OLED_MOSI))
#define	OLED_MOSI_Set()  	(OLED_MOSI_OUT |= OLED_MOSI)
  
#define	Send_Clk_Signal()	(OLED_CLK_OUT &= (~OLED_CLK)) ;	\
                            (OLED_CLK_OUT |= OLED_CLK)

#define OLED_INIT_SET() (OLED_OUT |= (OLED_CS |OLED_DC | OLED_RST |OLED_MOSI |OLED_CLK));
#endif
#else
#define OLED_CS_PIN     GPIO_Pin_12
#define OLED_DC_PIN     GPIO_Pin_5
#define OLED_RST_PIN    GPIO_Pin_4
#endif

void SPI_WriteByte(uint8_t Data);

void OLED_WriteByte(uint8_t data,uint8_t cmd);    
void OLED_Display_On(void);
void OLED_Display_Off(void);

void OLED_Set_Pos(unsigned char x, unsigned char y);
void OLED_Reset(void);
void OLED_Init_GPIO(void);	   							   		    
void OLED_Init(void);
void OLED_Set_Pixel(unsigned char x, unsigned char y,unsigned char color);
void OLED_Display(void);
void OLED_Clear(uint8_t dat);

#endif
cpp 复制代码
#include "oled.h"
#include "stdlib.h"
#include "string.h" 	 
//#include "delay.h"
//OLED每一个字符和数字占8位
//OLED显存总共分为8页
//每页8行,一行128个像素点
//OLED的显存
//存放格式如下.
//[0]0 1 2 3 ... 127 (0~7)行	   
//[1]0 1 2 3 ... 127 (8~15)行	
//[2]0 1 2 3 ... 127 (16~23)行	
//[3]0 1 2 3 ... 127 (24~31)行	
//[4]0 1 2 3 ... 127 (32~39)行	
//[5]0 1 2 3 ... 127 (40~47)行	
//[6]0 1 2 3 ... 127 (48~55)行	
//[7]0 1 2 3 ... 127 (56~63)行			   

//数组每个bit存储OLED每个像素点的颜色值(1-亮(白色),0-灭(黑色))
//每个数组元素表示1列8个像素点,一共128列
uint8_t OLED_buffer[1024];

#if 0
uint8_t pic_tiger[] = {
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,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,0x80,0x80,
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,
0x00,0x40,0x20,0xA0,0x70,0x70,0xB8,0x88,0xC8,0xC8,0xC8,0xC8,0x88,0x06,0x00,0x01,
0x01,0x02,0x1E,0x28,0x28,0x28,0x48,0x08,0x88,0x18,0x3C,0x6C,0xE8,0xCC,0x8C,0x0C,
0x1C,0x3C,0x3C,0xE4,0xC6,0x86,0x0E,0x0E,0x1E,0x3F,0x3D,0xFD,0xF9,0xF1,0xE1,0x81,
0x01,0x01,0x03,0x07,0x3E,0x7E,0xFC,0xF1,0x81,0x01,0x01,0x01,0x01,0x03,0x3F,0x7D,
0xF3,0xE2,0x02,0x06,0x06,0x0C,0x3C,0xFC,0x0C,0x08,0x18,0x18,0x90,0x30,0x20,0xE0,
0x40,0x80,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0xC0,0x60,0x60,0x40,0x20,0x10,0x08,0x1C,0xDE,0xED,0x77,0x32,
0x1A,0x1F,0x60,0x1C,0x09,0x01,0x0D,0x08,0x00,0x80,0x80,0x00,0x09,0x10,0x70,0x62,
0x06,0x06,0x06,0xDE,0xF8,0x70,0x00,0x00,0x01,0x03,0x0E,0x1C,0xF0,0x81,0x0F,0xFE,
0x30,0x00,0x00,0x00,0x03,0x07,0x0F,0x7E,0xF8,0xF0,0x00,0x00,0x01,0x03,0x07,0x0F,
0x1F,0x1F,0x3C,0xF8,0xF0,0xE0,0x00,0x03,0x07,0x7F,0x0C,0x00,0x00,0x20,0x10,0x1E,
0x07,0x03,0x00,0x00,0x80,0x80,0x80,0xC0,0xC0,0x60,0x78,0x4C,0x4F,0x70,0x60,0x43,
0x8E,0x10,0x33,0x6D,0xDA,0x9C,0x38,0xF0,0x60,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,0x07,0x0C,0xC8,0x68,0x18,0x00,0x00,0x00,0xD0,0xE7,0x01,0x00,0x38,
0x78,0x40,0x40,0x40,0x0C,0x00,0x00,0x00,0x40,0x20,0x39,0x50,0xB0,0x00,0x00,0x20,
0x00,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x0E,0x01,0x04,0x03,
0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x10,
0xE0,0xC0,0x00,0x00,0x03,0x0F,0x0F,0xFC,0x80,0x00,0x30,0x80,0xE0,0xF8,0x7C,0x3E,
0x0E,0x0F,0x87,0x87,0xC3,0xC3,0x41,0x61,0x20,0x20,0x24,0x24,0x84,0x84,0x84,0x8C,
0x8C,0x98,0x18,0x18,0x10,0x31,0x62,0xC4,0x18,0x07,0x1F,0xF8,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,0x0F,0x7F,0xC0,0x00,0x00,0x00,0x03,0x07,0x0F,0x1E,0x18,
0x18,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x80,0x00,
0x00,0x00,0x00,0x00,0x20,0x20,0x20,0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x82,0x02,
0x02,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0xFF,0xFF,0xFF,0x10,0x00,0x00,0xC0,0x00,0x03,0x00,0x00,0x38,0xE3,0x87,0x0C,0x18,
0x3E,0x3F,0x3F,0x63,0x61,0x70,0x48,0x04,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x80,
0x00,0x81,0x80,0x41,0x02,0x10,0x00,0x80,0x40,0xC3,0x2A,0x34,0x03,0xC6,0xFC,0x90,
0x30,0x60,0x40,0xC0,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x60,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x78,0xCC,0x03,0x03,0x06,0x04,0x08,0x08,0x00,0x08,
0x88,0x80,0x18,0x40,0x28,0x10,0x08,0x04,0x06,0x02,0x01,0x01,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0x80,0x00,0x00,0x00,0x00,0x00,0x03,
0x06,0xFC,0xE0,0x00,0x00,0x00,0x80,0xE0,0x3F,0x00,0x00,0x00,0x00,0x00,0x80,0xE0,
0x3F,0x1F,0x8F,0xC0,0xC0,0xF0,0x7F,0x00,0x00,0x00,0x00,0xCE,0x2F,0x07,0x00,0x00,
0xF8,0xFC,0x80,0x00,0x00,0x00,0x00,0x0F,0xF0,0x20,0x60,0x50,0xC0,0x40,0xC0,0x01,
0xF0,0x13,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0xFF,0x60,0x2F,0x2F,0x23,0x20,
0x60,0x60,0x7F,0x7F,0x7E,0x43,0x40,0x40,0x40,0x4F,0x5F,0x40,0x40,0x07,0x24,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x06,0x0C,0x08,0x08,0x08,0x02,0x1E,
0x35,0x68,0x40,0x40,0x40,0x68,0x40,0x40,0x60,0x20,0x20,0x20,0x30,0x10,0x10,0x10,
0x10,0x08,0x08,0x08,0x0A,0x08,0x08,0x08,0x0C,0x0F,0x08,0x08,0x08,0x0E,0x08,0x08,
0x0F,0x0F,0x0D,0x0E,0x0E,0x0F,0x0F,0x0D,0x0C,0x0C,0x0C,0x0E,0x0E,0x0F,0x07,0x04,
0x04,0x06,0x07,0x07,0x07,0x06,0x06,0x06,0x02,0x02,0x02,0x03,0x02,0x02,0x02,0x06,
0x07,0x07,0x07,0x06,0x06,0x06,0x06,0x06,0x03,0x03,0x03,0x03,0x01,0x01,0x01,0x01,
0x01,0x07,0x04,0x0C,0x08,0x08,0x0A,0x0A,0x0A,0x0D,0x07,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
};
#endif

#ifndef OLED_USE_SPI
void SPI_WriteByte(uint8_t Data)
{
	uint8_t i=0;
	for(i=8;i>0;i--)
	{
	  if(Data&0x80)	
		{
			OLED_MOSI_Set(); //write data "1"
			
    }
		else
		{
			OLED_MOSI_Clr(); //write data "0"
	  }
		Send_Clk_Signal();
    Data<<=1; 
	}
}
#endif

/*******************************************************************
 * @function   :Write a byte of content to the OLED screen
 * @parameters :dat:Content to be written
                cmd:0-write command
								    1-write data
 * @retvalue   :None
********************************************************************/
void OLED_WriteByte(uint8_t dat,uint8_t cmd)
{
    if(cmd)
      OLED_DC_Set();
    else
      OLED_DC_Clr();

    OLED_CS_Clr();
#ifdef OLED_USE_SPI
    SPI0_MasterSendByte( dat );
#else
    SPI_WriteByte( dat );
#endif
    OLED_CS_Set();
}

/*******************************************************************
 * @function   :Set coordinates in the OLED screen
 * @parameters :x:x coordinates
                y:y coordinates
 * @retvalue   :None
********************************************************************/
void OLED_Set_Pos(unsigned char x, unsigned char y) 
{
 	OLED_WriteByte(YLevel+y/PAGE_SIZE,OLED_CMD);
	OLED_WriteByte((((x+2)&0xf0)>>4)|0x10,OLED_CMD);
	OLED_WriteByte(((x+2)&0x0f),OLED_CMD); 
}  

/*******************************************************************
 * @name       :void OLED_Display_On(void) 
 * @date       :2018-08-27
 * @function   :Turn on OLED display
 * @parameters :None
 * @retvalue   :None
********************************************************************/ 	 
//开启OLED显示  
void OLED_Display_On(void)
{
	OLED_WriteByte(0X8D,OLED_CMD);  //SET DCDC命令
	OLED_WriteByte(0X14,OLED_CMD);  //DCDC ON
	OLED_WriteByte(0XAF,OLED_CMD);  //DISPLAY ON
}

/*******************************************************************
 * @name       :void OLED_Display_Off(void)
 * @date       :2018-08-27
 * @function   :Turn off OLED display
 * @parameters :None
 * @retvalue   :None
********************************************************************/    
//关闭OLED显示   
void OLED_Display_Off(void)
{
	OLED_WriteByte(0X8D,OLED_CMD);  //SET DCDC命令
	OLED_WriteByte(0X10,OLED_CMD);  //DCDC OFF
	OLED_WriteByte(0XAE,OLED_CMD);  //DISPLAY OFF
}

/*******************************************************************
 * @name       :void OLED_Set_Pixel(unsigned char x, unsigned char y,unsigned char color)
 * @date       :2018-08-27
 * @function   :set the value of pixel to RAM
 * @parameters :x:the x coordinates of pixel
                y:the y coordinates of pixel
								color:the color value of the point
								      1-white
											0-black
 * @retvalue   :None
********************************************************************/ 
void OLED_Set_Pixel(unsigned char x, unsigned char y,unsigned char color)
{
	if(color)
	{
		OLED_buffer[(y/PAGE_SIZE)*WIDTH+x]|= (1<<(y%PAGE_SIZE))&0xff;
	}
	else
	{
		OLED_buffer[(y/PAGE_SIZE)*WIDTH+x]&= ~((1<<(y%PAGE_SIZE))&0xff);
	}
}		   			 

/*******************************************************************
 * @name       :void OLED_Display(void)
 * @date       :2018-08-27
 * @function   :Display in OLED screen
 * @parameters :None
 * @retvalue   :None
********************************************************************/  
void OLED_Display(void)
{
	u8 i,n;		    
	for(i=0;i<PAGE_SIZE;i++)  
	{  
		OLED_WriteByte (YLevel+i,OLED_CMD);    //设置页地址(0~7)
        OLED_WriteByte (XLevelH,OLED_CMD);      //设置显示位置---列高地址
		OLED_WriteByte (XLevelL,OLED_CMD);      //设置显示位置---列低地址
		for(n=0;n<WIDTH;n++)
		{
			OLED_WriteByte(OLED_buffer[i*WIDTH+n],OLED_DATA);
		}
	}   //更新显示
}

/*******************************************************************
 * @name       :void OLED_Clear(unsigned dat)  
 * @date       :2018-08-27
 * @function   :clear OLED screen
 * @parameters :dat:0-Display full black
                    1-Display full white
 * @retvalue   :None
********************************************************************/ 
void OLED_Clear(uint8_t dat)
{  
	if(dat)
	{
		memset(OLED_buffer,0xff,sizeof(OLED_buffer));
	}
	else
	{
		memset(OLED_buffer,0,sizeof(OLED_buffer));
	}
	OLED_Display();
}

/*******************************************************************
 * @name       :void OLED_Reset(void) 
 * @date       :2018-08-27
 * @function   :Reset OLED screen
 * @parameters :dat:0-Display full black
                    1-Display full white
 * @retvalue   :None
********************************************************************/ 
void OLED_Reset(void)
{
#if 1
	OLED_RST_Set();
	delay_ms(100);
	OLED_RST_Clr();
	delay_ms(100);
	OLED_RST_Set(); 
#else
  GPIOA_SetBits(OLED_RST_PIN);
  DelayMs(100);
  GPIOA_ResetBits(OLED_RST_PIN);
  DelayMs(200);
  GPIOA_SetBits(OLED_RST_PIN);

#endif
}	
	
/*******************************************************************
 * @name       :void OLED_Init_GPIO(void)
 * @date       :2018-08-27
 * @function   :Reset OLED screen
 * @parameters :None
 * @retvalue   :None
********************************************************************/ 
void OLED_Init_GPIO(void)
{
#ifdef OLED_USE_SPI
    GPIOA_SetBits( GPIO_Pin_12 );
    GPIOA_ModeCfg( GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14, GPIO_ModeOut_PP_5mA );
    SPI0_MasterDefInit();

    GPIOA_ModeCfg(GPIO_Pin_4|GPIO_Pin_5,GPIO_ModeOut_PP_5mA);
    GPIOA_SetBits( GPIO_Pin_4 );
    GPIOA_SetBits( GPIO_Pin_5 );
#else
    GPIOA_ModeCfg(GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14, GPIO_ModeOut_PP_5mA);
//    SPI0_MasterDefInit();
    OLED_INIT_SET();
#endif
}

/*******************************************************************
 * @name       :void OLED_Init(void)
 * @date       :2018-08-27
 * @function   :initialise OLED SH1106 control IC
 * @parameters :None
 * @retvalue   :None
********************************************************************/ 				    
void OLED_Init(void)
{
 	OLED_Init_GPIO(); //初始化GPIO
// 	delay_ms(200);
	OLED_Reset();     //复位OLED

	OLED_Display_Off(); //power off
	OLED_WriteByte(0xAE,OLED_CMD);//--turn off oled panel
	OLED_WriteByte(0x02,OLED_CMD);//---set low column address
	OLED_WriteByte(0x10,OLED_CMD);//---set high column address
	OLED_WriteByte(0x40,OLED_CMD);//--set start line address  Set Mapping RAM Display Start Line (0x00~0x3F)
	OLED_WriteByte(0x81,OLED_CMD);//--set contrast control register
	OLED_WriteByte(0xCF,OLED_CMD); // Set SEG Output Current Brightness
	OLED_WriteByte(0xA1,OLED_CMD);//--Set SEG/Column Mapping     0xa0左右反置 0xa1正常
	OLED_WriteByte(0xC8,OLED_CMD);//Set COM/Row Scan Direction   0xc0上下反置 0xc8正常
	OLED_WriteByte(0xA6,OLED_CMD);//--set normal display
	OLED_WriteByte(0xA8,OLED_CMD);//--set multiplex ratio(1 to 64)
	OLED_WriteByte(0x3f,OLED_CMD);//--1/64 duty
	OLED_WriteByte(0xD3,OLED_CMD);//-set display offset	Shift Mapping RAM Counter (0x00~0x3F)
	OLED_WriteByte(0x00,OLED_CMD);//-not offset
	OLED_WriteByte(0xd5,OLED_CMD);//--set display clock divide ratio/oscillator frequency
	OLED_WriteByte(0x80,OLED_CMD);//--set divide ratio, Set Clock as 100 Frames/Sec
	OLED_WriteByte(0xD9,OLED_CMD);//--set pre-charge period
	OLED_WriteByte(0xF1,OLED_CMD);//Set Pre-Charge as 15 Clocks & Discharge as 1 Clock
	OLED_WriteByte(0xDA,OLED_CMD);//--set com pins hardware configuration
	OLED_WriteByte(0x12,OLED_CMD);
	OLED_WriteByte(0xDB,OLED_CMD);//--set vcomh
	OLED_WriteByte(0x40,OLED_CMD);//Set VCOM Deselect Level
	OLED_WriteByte(0x20,OLED_CMD);//-Set Page Addressing Mode (0x00/0x01/0x02)
	OLED_WriteByte(0x02,OLED_CMD);//
	OLED_WriteByte(0x8D,OLED_CMD);//--set Charge Pump enable/disable
	OLED_WriteByte(0x14,OLED_CMD);//--set(0x10) disable
	OLED_WriteByte(0xA4,OLED_CMD);// Disable Entire Display On (0xa4/0xa5)
	OLED_WriteByte(0xA6,OLED_CMD);// Disable Inverse Display On (0xa6/a7) 
	OLED_WriteByte(0xAF,OLED_CMD);//--turn on oled panel

	OLED_WriteByte(0xAF,OLED_CMD); /*display ON*/
	  OLED_Clear(0);
	  OLED_Set_Pos(0,0);

//  OLED_Display_On(); // power on
}  

代码比较简单,初始化部分的命令,不同的OLED屏可能会有所差异。一般OLED产品的规格书上都有说明,不愿意看规格书的,也可以从厂家提供的Demo程序中得到。

完整的代码请下载:CH58x/CH59x SPI驱动7 Pin OLED driver