STM32使用4线SPI模式驱动SSD1351

STM32与SSD1351的接线如下:
PC9 – CS :片选低电平有效
PC8–DC :数据/命令控制
PC7–RST :控制器和驱动器的电源复位RES
PB15–SDA :SPI2_MOSI
PB13–SCL : SPI2_SCK
字模取模方式:阴码 逐行式 顺向
图片取模:16位真彩色 高位在前

/*ssd1351.h*/
#ifndef __ssd1351_H
#define __ssd1351_H
#include "stm32f10x.h"

/* 宏定义 --------------------------------------------------------------------*/
#define		Black		0x0000		//黑色(不亮)
#define		Navy		0x000F		//深蓝色
#define		Dgreen		0x03E0		//深绿色
#define		Dcyan		0x03EF		//深青色
#define		Maroon		0x7800		//深红色
#define		Purple		0x780F		//紫色
#define		Olive		0x7BE0		//橄榄绿
#define		Lgray		0xC618		//灰白色
#define		Dgray		0x7BEF		//深灰色
#define		Blue		0x001F		//蓝色
#define		Green		0x07E0		//绿色
#define		Cyan		0x07FF		//青色
#define		Red			0xF800		//红色
#define		Magenta		0xF81F		//品红
#define		Yellow		0xFFE0		//黄色
#define		White		0xFFFF		//白色

#define Max_Column	  0x7f			// 128-1
#define Max_Row		  0x7f			// 128-1

//PC7	  LCD_RST	控制器和驱动器的电源复位
#define OLED_RES_GPIO_PORT      (GPIOC)				//RES#引脚
#define OLED_RES_GPIO_PINS      (GPIO_Pin_7)
//PC8	  LCD_DC	数据/命令控制
#define OLED_DC_GPIO_PORT       (GPIOC)				//D/C#引脚
#define OLED_DC_GPIO_PINS       (GPIO_Pin_8)
//PC9	  LCD_CS	片选 低电平有效
#define OLED_CS_GPIO_PORT      	(GPIOC)				//CS#引脚
#define OLED_CS_GPIO_PINS      	(GPIO_Pin_9)

#define OLED_RES_Set()          GPIO_SetBits(OLED_RES_GPIO_PORT, OLED_RES_GPIO_PINS)
#define OLED_RES_Clr()          GPIO_ResetBits(OLED_RES_GPIO_PORT,OLED_RES_GPIO_PINS)

#define OLED_DC_Set()           GPIO_SetBits(OLED_DC_GPIO_PORT, OLED_DC_GPIO_PINS)
#define OLED_DC_Clr()           GPIO_ResetBits(OLED_DC_GPIO_PORT, OLED_DC_GPIO_PINS)

#define	SPI_NSS_HIGH()			GPIO_SetBits(OLED_CS_GPIO_PORT, OLED_CS_GPIO_PINS)
#define	SPI_NSS_LOW()			GPIO_ResetBits(OLED_CS_GPIO_PORT, OLED_CS_GPIO_PINS)

/* 函数声明-------------------------------------------------------------------*/
void OLED_GPIO_Init(void);//IO口初始化
void SPI2_Init(void);//SPI初始化
u8 SPI_RW_Byte(u8 data);//使用SPI0读写1Byte

void Fill_RAM(int Colour_RGB);//填充全屏(刷屏)
void Clear_Screen(unsigned char Var_Row);//指定某一行清屏(一共8行:0~7)
//指定坐标画一个字符(逐行式),字符大小固定为8*16
void Display_Char(unsigned char x, unsigned char y, unsigned char Var_Char, int Colour_RGB);
//显示字符串
void Display_String(unsigned char x, unsigned char y, unsigned char *chr, int Colour_RGB);
//指定坐标画一个字符(逐行式),字符大小固定为16*16
void Display_Chinese16x16(unsigned char x, unsigned char y, unsigned char Var_Char, int Colour_RGB);
//指定坐标画一个字符(逐行式),字符大小固定为12*12
void Display_Chinese12x12(unsigned char x, unsigned char y, unsigned char Var_Char, int Colour_RGB);
//显示数字
void Display_Num(unsigned char x,unsigned char y,int Var_Num, unsigned char Num_Len, int Colour_RGB);
//显示图片
void Display_Pattern(unsigned char *Pattern_Data, unsigned char Start_x, unsigned char End_x, unsigned char Start_y, unsigned char End_y);
//画点
void Draw_Point(const unsigned char x, const unsigned char y, int Colour_RGB);
//画圆圈
void Display_Circle(const u8 x,const u8 y,const u8 r, int Colour_RGB);
//灰阶表设置
void Set_Gray_Scale_Table(void);
//OLED显示初始化
void OLED_Init(void);
#endif
/*ssd1351.c*/
#include "font.h"
/****************************************************
函数名:OLED_GPIO_Init
形参:
返回值:
函数功能:OLED的信号引脚初始化
****************************************************/
void OLED_GPIO_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;	//定义结构体

    RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOC, ENABLE);	//使能GPIOC时钟
    GPIO_InitStructure.GPIO_Pin = OLED_RES_GPIO_PINS | OLED_DC_GPIO_PINS | OLED_CS_GPIO_PINS;		//初始化用于控制OLED的相关引脚
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;	//推挽输出
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOC, &GPIO_InitStructure);	//初始化

    GPIO_SetBits(GPIOC, OLED_RES_GPIO_PINS | OLED_DC_GPIO_PINS | OLED_CS_GPIO_PINS);	//将RES、DC、CS引脚拉高
}
/****************************************************
函数名:SPI2_Init
形参:
返回值:
函数功能:初始化SPI2
****************************************************/
void SPI2_Init(void)
{
    /* 定义spi与GPIO配置参数结构体 */
    SPI_InitTypeDef  SPI_InitStruct;
    GPIO_InitTypeDef GPIO_InitStructure;

    /* 打开SPI2的端口时钟、AFIO与外设时钟 */
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15 | GPIO_Pin_13;	//初始化PB13(CLK)与PB15(MOSI)
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;	//复用推挽输出
    GPIO_Init(GPIOB, &GPIO_InitStructure);

    SPI_InitStruct.SPI_Direction = SPI_Direction_2Lines_FullDuplex;	//全双工
    SPI_InitStruct.SPI_Mode      = SPI_Mode_Master;	//SPI主模式
    SPI_InitStruct.SPI_DataSize  = SPI_DataSize_8b;	//8位数据结构
    SPI_InitStruct.SPI_CPOL      = SPI_CPOL_High;	//时钟极性高
    SPI_InitStruct.SPI_CPHA      = SPI_CPHA_2Edge;	//第二个时钟沿有效
    SPI_InitStruct.SPI_NSS       = SPI_NSS_Soft;	//NSS引脚软件控制
    SPI_InitStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16;//定义波特率预分频的值:波特率预分频值为256 SPI_BaudRatePrescaler_64
    SPI_InitStruct.SPI_FirstBit  = SPI_FirstBit_MSB;	//高位先发送
    SPI_InitStruct.SPI_CRCPolynomial = 7;	//CRC校验7
    SPI_Init(SPI2, &SPI_InitStruct);	//初始化
    SPI_Cmd(SPI2, ENABLE);	//使能SPI2
}
/****************************************************
函数名:SPI_RW_Byte
形参:  data:发送的数据
返回值:  temp:读取的数据
函数功能:使用SPI0读写1Byte
****************************************************/
u8 SPI_RW_Byte(u8 data)
{
    u8 temp=0;	//定义变量读取数据
    /* 等待发送缓存器空 */
    while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET);//检查指定的SPI标志位设置与否:发送缓存空标志位
    /* 发送数据 */
    SPI_I2S_SendData(SPI2, data);
//	/* 等待接收缓存器非空 */
    while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET);
    /* 接收一字节数据 */
    temp = SPI_I2S_ReceiveData(SPI2);
    return temp;
}
/**
  * @函数名       Delay
  * @功  能       延迟
  * @参  数       data:延迟data
  * @返回值       无
  */
static void Delay(uint32_t data)
{
    while(data--);
}
/****************************************************
函数名:Write_Command
形参:  Cmd:发送的命令
返回值:
函数功能:往OLED发送命令
****************************************************/
void Write_Command(unsigned char Cmd)
{
    SPI_NSS_LOW(); //片选拉低,选通器件
    OLED_DC_Clr();  //DC拉低,发送命令
    SPI_RW_Byte(Cmd); //发送数据
    OLED_DC_Set(); //DC拉高,空闲时为高电平
    SPI_NSS_HIGH(); //片选拉高,关闭器件
}
/****************************************************
函数名:Write_Data
形参:  Data:发送的数据
返回值:
函数功能:往OLED发送数据
****************************************************/
void Write_Data(unsigned char Data)
{
    SPI_NSS_LOW(); //片选拉低,选通器件
    OLED_DC_Set();  //DC拉高,发送数据
    SPI_RW_Byte(Data); //发送数据
    OLED_DC_Clr();
    SPI_NSS_HIGH(); //片选拉高,关闭器件
}
/****************************************************
函数名:Set_Column_Address
形参:  Clo_Start:列起始地址;Clo_End:列结束地址 0-127
返回值:
函数功能:设置列地址
****************************************************/
void Set_Column_Address(unsigned char Clo_Start, unsigned char Clo_End)
{
    Write_Command(0x15);  // 设置列地址
    Write_Data(Clo_Start);  // 列起始地址
    Write_Data(Clo_End);  // 列结束地址
}

/****************************************************
函数名:Set_Row_Address
形参:  Row_Start:行起始地址;Row_End:行结束地址
返回值:
函数功能:设置行地址
****************************************************/
void Set_Row_Address(unsigned char Row_Start, unsigned char Row_End)
{
    Write_Command(0x75);  // 设置行地址
    Write_Data(Row_Start);  // 行起始地址
    Write_Data(Row_End);  // 行结束地址
}

/****************************************************
函数名:Set_Write_RAM
形参:
返回值:
函数功能:使能MCU写RAM
****************************************************/
void Set_Write_RAM()
{
    Write_Command(0x5C);  //使能MCU写RAM
}

/****************************************************
函数名:Set_Read_RAM
形参:
返回值:
函数功能:使能MCU读RAM
****************************************************/
void Set_Read_RAM()
{
    Write_Command(0x5D);  //使能MCU读RAM
}
/****************************************************
函数名:Fill_RAM
形参:  Colour_RGB:填充颜色:RRRRRGGGGGGBBBBB
返回值:
函数功能:填充全屏(刷屏)
****************************************************/
void Fill_RAM(int Colour_RGB)
{
    unsigned char i,j;  //定义变量
    Set_Column_Address(0x00,0x7F);  //设置列地址0~127
    Set_Row_Address(0x00,0x7F);   //设置行地址0~127
    Set_Write_RAM();  //使能MCU写RAM
    for(i=0; i<128; i++) //填充128列*128行
    {
        for(j=0; j<128; j++)
        {
            Write_Data(Colour_RGB >> 8);  //写入填充颜色高字节
            Write_Data(Colour_RGB); //写入填充颜色低字节
        }
    }
}
/****************************************************
函数名:Clear_Screen
形参:  Var_Row:第Var_Row行
返回值:
函数功能:指定某一行清屏(一共8行:0~7)
****************************************************/
void Clear_Screen(unsigned char Var_Row)
{
    unsigned int i;
    Set_Column_Address(0x00, 0x7F);	//设置列地址0~127
    Set_Row_Address(Var_Row*16, (Var_Row*16 + 15));		//设置行地址
    Set_Write_RAM();	//使能MCU写RAM

    for(i = 0; i < 2048; i++)	//把这一行清屏,点数量 = 16*128 = 2048
    {
        Write_Data(0x00);
        Write_Data(0x00);
    }
}
/****************************************************
函数名:Draw_Point
形参:  x:列起始地址;y:行起始地址;Colour_RGB:填充颜色:RRRRRGGGGGGBBBBB
返回值:
函数功能:画点
****************************************************/
void Draw_Point(const unsigned char x, const unsigned char y, int Colour_RGB)
{
    Write_Command(0x15);  // 设置列地址
    Write_Data(x);

    Write_Command(0x75);  // 设置行地址
    Write_Data(y);

    Set_Write_RAM();  //使能MCU写RAM

    Write_Data(Colour_RGB >> 8); //写入填充颜色高字节
    Write_Data(Colour_RGB);  //写入填充颜色低字节
}
/****************************************************
函数名:Display_Char
形参:  x:列起始地址;y:行起始地址;Var_Char:写入的字符;Colour_RGB:填充颜色:RRRRRGGGGGGBBBBB
返回值:
函数功能:指定坐标画一个字符(逐行式),字符大小固定为8*16
****************************************************/
void Display_Char(unsigned char x, unsigned char y, unsigned char Var_Char, int Colour_RGB)
{
    unsigned char i, j; //定义变量
    unsigned char Var_Temp, x_Temp; //定义变量

    x_Temp = x; //获取x起始坐标
    for (i = 0; i < 16; i++)
    {
        Var_Temp = ACSII_Font[Var_Char - 0x20][i];  //获取字符在数组的偏移量
        for ( j = 0; j < 8; j++)
        {
            if (Var_Temp & 0x80)  //先画最高位的点,为1则画对应的颜色
                Draw_Point(x, y, Colour_RGB);
            //else
            //Draw_Point(x, y, 0x0000); //为0则黑色(都不亮),可作为背景色

            Var_Temp <<= 1; //移位,准备画下一个点
            x++;  //x坐标加1

            if((x - x_Temp) == 8)
            {
                x = x_Temp; //x坐标回到起始位置
                y++;  //y坐标加1
                break;  //退出当前循环
            }
        }
    }
}
/****************************************************
函数名:Display_String
形参:  x:列起始地址;y:行起始地址;*chr:显示的字符串;Colour_RGB:填充颜色:RRRRRGGGGGGBBBBB
返回值:
函数功能:显示字符串
****************************************************/
void Display_String(unsigned char x, unsigned char y, unsigned char *chr, int Colour_RGB)
{
    unsigned char i = 0;  //定义变量

    while(chr[i] != '\0') //判断是否结束
    {
        Display_Char(x, y, chr[i], Colour_RGB); //显示字符
        x += 8; //x坐标加8(一个字符x方向占8个点,Y方向占16个点)
        i++;  //下一个字符
    }
}
/****************************************************
函数名:Display_Circle
形参:  圆心:(x0, y0) 半径:r;Colour_RGB:填充颜色:RRRRRGGGGGGBBBBB
返回值:
函数功能:显示空心圆圈
****************************************************/
int a, b, num;
void Display_Circle(const u8 x,const u8 y,const u8 r, int Colour_RGB)
{

    a = 0;
    b = r;
    while(2 * b * b >= r * r)          // 1/8圆即可
    {
        Draw_Point(x + a, y - b+2,Colour_RGB); // 0~1
        Draw_Point(x + b-2, y + a,Colour_RGB); // 2~3 00000
        Draw_Point(x - a, y + b-2,Colour_RGB); // 4~5
        Draw_Point(x - b+2, y - a,Colour_RGB); // 6~7
        Draw_Point(x + b-2, y - a,Colour_RGB); // 2~1 
        Draw_Point(x + a, y + b-2,Colour_RGB); // 4~3   
        Draw_Point(x - b+2, y + a,Colour_RGB); // 6~5  
        Draw_Point(x - a, y - b+2,Colour_RGB); // 0~7 
          
        a++;
        num = (a * a + b * b) - r*r;
        if(num > 0)
        {
            a--; 
            b--;
        }
    }
}
/****************************************************
函数名:Display_Chinese
形参:  x:列起始地址;y:行起始地址;Var_Char:汉字在数组的下标;Colour_RGB:填充颜色:RRRRRGGGGGGBBBBB
返回值:
函数功能:指定坐标画一个字符(逐行式),字符大小固定为16*16
****************************************************/
void Display_Chinese16x16(unsigned char x, unsigned char y, unsigned char Var_Char, int Colour_RGB)
{
    unsigned char i, j; //定义变量
    unsigned char Var_Temp, x_Temp; //定义变量

    x_Temp = x; //获取x起始坐标
    for(i = 0; i < 32; i++) //16*16 = 32*8;一次只能写入一字节,也就是8位,所以采用8*32的画法
    {
        Var_Temp = Chinese_Font[Var_Char][i]; //获取汉字在数组的偏移量
        for(j = 0; j < 8; j++)
        {
            if(Var_Temp & 0x80)   //先画最高位的点,为1则画对应的颜色
                Draw_Point(x, y, Colour_RGB);
            //else
            //Draw_Point(x, y, 0x0000); //为0则黑色(都不亮),可作为背景色
            Var_Temp <<= 1; //移位,准备画下一个点
            x++;  //x坐标加1

            if((x - x_Temp) == 16)  //画完一列
            {
                x = x_Temp; //x坐标回到起始位置
                y++;  //y坐标加1
                break;  //退出当前循环
            }
        }
    }
}
/****************************************************
函数名:Display_Chinese
形参:  x:列起始地址;y:行起始地址;Var_Char:汉字在数组的下标;Colour_RGB:填充颜色:RRRRRGGGGGGBBBBB
返回值:
函数功能:指定坐标画一个字符(逐行式),字符大小固定为16*16
****************************************************/
void Display_Chinese12x12(unsigned char x, unsigned char y, unsigned char Var_Char, int Colour_RGB)
{
    unsigned char i, j; //定义变量
    unsigned char Var_Temp, x_Temp; //定义变量

    x_Temp = x; //获取x起始坐标
    for(i = 0; i < 24; i++) //12*12 = 18*8;一次只能写入一字节,也就是8位,所以采用8*18的画法
    {
        Var_Temp = Chinese_Font_12[Var_Char][i]; //获取汉字在数组的偏移量
        for(j = 0; j < 8; j++)
        {
            if(Var_Temp & 0x80)   //先画最高位的点,为1则画对应的颜色
                Draw_Point(x, y, Colour_RGB);
            //else
            //Draw_Point(x, y, 0x0000); //为0则黑色(都不亮),可作为背景色
            Var_Temp <<= 1; //移位,准备画下一个点
            x++;  //x坐标加1

            if((x - x_Temp) == 12)  //画完一列
            {
                x = x_Temp; //x坐标回到起始位置
                y++;  //y坐标加1
                break;  //退出当前循环
            }
        }
    }
}
/****************************************************
函数名:Num_Pow
形参:  m:底数;n:指数
返回值:
函数功能:m^n幂运算
****************************************************/
uint32_t Num_Pow(unsigned char m,unsigned char n)
{
    uint32_t result=1; //定义变量

    while(n--)result*=m;  //m^n
    return result;  //返回结果
}

/****************************************************
函数名:Display_Num
形参:  x:列起始地址;y:行起始地址;Var_Num:显示的数字;Num_Len:数字长度;Colour_RGB:填充颜色:RRRRRGGGGGGBBBBB
返回值:
函数功能:显示数字
****************************************************/
void Display_Num(unsigned char x,unsigned char y,int Var_Num, unsigned char Num_Len, int Colour_RGB)
{
    unsigned char i;  //定义变量
    unsigned char Var_Temp;   //定义变量
    unsigned char Var_Show = 0; //定义变量

    for(i = 0; i < Num_Len; i++)  //显示数字
    {
        Var_Temp  =  (Var_Num / Num_Pow(10, Num_Len-i-1)) % 10;  //获取最高位(数字显示是一位一位取出来再显示)
        if(Var_Show == 0 && i<(Num_Len - 1))  //判断首位数字是否为0
        {
            if(Var_Temp == 0)
            {
                Display_Char(x+8*i, y, ' ', Colour_RGB);  //首位数据为0则不显示
                continue; //继续循环
            }
            else
                Var_Show = 1; //后面的数字正常显示
        }

        Display_Char(x+8*i, y, Var_Temp + '0', Colour_RGB); //显示数字
    }
}
/****************************************************
函数名:Display_Pattern
形参:  *Pattern_Data:图片数组;Start_x:x方向起点;End_x:x方向终点;Start_y:y方向起点;End_y:y方向终点
返回值:
函数功能:显示图片
****************************************************/
void Display_Pattern(unsigned char *Pattern_Data, unsigned char Start_x, unsigned char End_x, unsigned char Start_y, unsigned char End_y)
{
    unsigned char *Data_Pointer;	//定义指针变量
    unsigned char i, j;		//定义变量
    Data_Pointer = Pattern_Data;	//获取数组首地址
    Set_Column_Address(Start_x, End_x);	//设置列范围
    Set_Row_Address(Start_y, End_y);	//设置行范围
    Set_Write_RAM();	//设置MCU写RAM

    for(i = 0; i < (End_y - Start_y + 1); i++)	//y方向(End_y - Start_y + 1)
    {
        for(j = 0; j < (End_x - Start_x + 1); j++)	//x方向(End_x - Start_x + 1)
        {
            Write_Data(*Data_Pointer);	//写入数据(一个点需要写入16位数据:RRRRRGGGGGGBBBBB)
            Data_Pointer++;
            Write_Data(*Data_Pointer);
            Data_Pointer++;
        }
    }
}
/****************************************************
函数名:Set_Gray_Scale_Table
形参:
返回值:
函数功能:灰阶表设置
****************************************************/
void Set_Gray_Scale_Table(void)
{
    Write_Command(0xB8);
    Write_Data(0x02);     // Gray Scale Level 1
    Write_Data(0x03);     // Gray Scale Level 2
    Write_Data(0x04);     // Gray Scale Level 3
    Write_Data(0x05);     // Gray Scale Level 4
    Write_Data(0x06);     // Gray Scale Level 5
    Write_Data(0x07);     // Gray Scale Level 6
    Write_Data(0x08);     // Gray Scale Level 7
    Write_Data(0x09);     // Gray Scale Level 8
    Write_Data(0x0A);     // Gray Scale Level 9
    Write_Data(0x0B);     // Gray Scale Level 10
    Write_Data(0x0C);     // Gray Scale Level 11
    Write_Data(0x0D);     // Gray Scale Level 12
    Write_Data(0x0E);     // Gray Scale Level 13
    Write_Data(0x0F);     // Gray Scale Level 14
    Write_Data(0x10);     // Gray Scale Level 15
    Write_Data(0x11);     // Gray Scale Level 16
    Write_Data(0x12);     // Gray Scale Level 17
    Write_Data(0x13);     // Gray Scale Level 18
    Write_Data(0x15);     // Gray Scale Level 19
    Write_Data(0x17);     // Gray Scale Level 20
    Write_Data(0x19);     // Gray Scale Level 21
    Write_Data(0x1B);     // Gray Scale Level 22
    Write_Data(0x1D);     // Gray Scale Level 23
    Write_Data(0x1F);     // Gray Scale Level 24
    Write_Data(0x21);     // Gray Scale Level 25
    Write_Data(0x23);     // Gray Scale Level 26
    Write_Data(0x25);     // Gray Scale Level 27
    Write_Data(0x27);     // Gray Scale Level 28
    Write_Data(0x2A);     // Gray Scale Level 29
    Write_Data(0x2D);     // Gray Scale Level 30
    Write_Data(0x30);     // Gray Scale Level 31
    Write_Data(0x33);     // Gray Scale Level 32
    Write_Data(0x36);     // Gray Scale Level 33
    Write_Data(0x39);     // Gray Scale Level 34
    Write_Data(0x3C);     // Gray Scale Level 35
    Write_Data(0x3F);     // Gray Scale Level 36
    Write_Data(0x42);     // Gray Scale Level 37
    Write_Data(0x45);     // Gray Scale Level 38
    Write_Data(0x48);     // Gray Scale Level 39
    Write_Data(0x4C);     // Gray Scale Level 40
    Write_Data(0x50);     // Gray Scale Level 41
    Write_Data(0x54);     // Gray Scale Level 42
    Write_Data(0x58);     // Gray Scale Level 43
    Write_Data(0x5C);     // Gray Scale Level 44
    Write_Data(0x60);     // Gray Scale Level 45
    Write_Data(0x64);     // Gray Scale Level 46
    Write_Data(0x68);     // Gray Scale Level 47
    Write_Data(0x6C);     // Gray Scale Level 48
    Write_Data(0x70);     // Gray Scale Level 49
    Write_Data(0x74);     // Gray Scale Level 50
    Write_Data(0x78);     // Gray Scale Level 51
    Write_Data(0x7D);     // Gray Scale Level 52
    Write_Data(0x82);     // Gray Scale Level 53
    Write_Data(0x87);     // Gray Scale Level 54
    Write_Data(0x8C);     // Gray Scale Level 55
    Write_Data(0x91);     // Gray Scale Level 56
    Write_Data(0x96);     // Gray Scale Level 57
    Write_Data(0x9B);     // Gray Scale Level 58
    Write_Data(0xA0);     // Gray Scale Level 59
    Write_Data(0xA5);     // Gray Scale Level 60
    Write_Data(0xAA);     // Gray Scale Level 61
    Write_Data(0xAF);     // Gray Scale Level 62
    Write_Data(0xB4);     // Gray Scale Level 63
}
/****************************************************
函数名:OLED_Init
形参:
返回值:
函数功能:OLED显示初始化
****************************************************/
void OLED_Init(void)
{
    OLED_GPIO_Init();     //初始化RES、DC与CS引脚

    SPI_NSS_LOW();
    Delay(100);
    OLED_RES_Clr();
    Delay(500);
    OLED_RES_Set();
    Delay(500); //延迟,由于单片机上电初始化比OLED快,所以必须加上延迟,等待OLED上电初始化完成

    Write_Command(0xFD);  // 解锁OLED驱动IC(SSD1351)的命令输入
    Write_Data(0x12);

    Write_Command(0xFD);  //设置 命令:A2,B1,B3,BB,BE 为可访问状态
    Write_Data(0xB1);

    Write_Command(0xAE);  //关显示(进入睡眠模式)
    Write_Command(0xA4);  //Normal Display mode

    Write_Command(0x15);	//set column address
    Write_Data(0x00);     //column address start 00
    Write_Data(0x7f);     //column address end 95
    Write_Command(0x75);	//set row address
    Write_Data(0x00);     //row address start 00
    Write_Data(0x7f);     //row address end 63

    Write_Command(0xB3);  //设置显示时钟分频&内部振荡器频率
    Write_Data(0xF1);   //时钟2分频,振荡器频率最高

    Write_Command(0xCA);  //设置 MUX Ratio
    Write_Data(0x7F);   //128


    Write_Command(0xA0);  //设置重映射格式
    Write_Data(0x74);   //水平地址增长模式、列地址0映射到SEG0、颜色数据传输顺序D[15:0] = [RRRRR:GGGGGG:BBBBB]、扫描方向:COM127~COM0、使能奇偶分离、颜色模式65K

    Write_Command(0xA1);  //设置显示起始行
    Write_Data(0x00);   //0x00

    Write_Command(0xA2);  //设置显示偏移
    Write_Data(0x00);   //无偏移

    Write_Command(0xAB);  //功能选择设置
    Write_Data(0x01);   //使能VDD内部稳压器、选择8位并行接口

    Write_Command(0xB4);  //VSL设置
    Write_Data(0xA0);   //使能外部VSL
    Write_Data(0xB5);
    Write_Data(0x55);

    Write_Command(0xC1);  //设置色彩的对比电流
    Write_Data(0xC8);   //A-->Red
    Write_Data(0x80);   //B-->Green
    Write_Data(0xC0);   //C-->Blue

    Write_Command(0xC7);  //主对比度电流控制
    Write_Data(0x0f);   //0x0f

    Write_Command(0xB1);  //设置阶段1(复位阶段)&阶段2(预充电)的周期
    Write_Data(0x32);   //阶段1为5个时钟周期、阶段2为3个时钟周期

    Write_Command(0xB2);
    Write_Data(0xA4);
    Write_Data(0x00);
    Write_Data(0x00);

    Write_Command(0xBB);  //设置预充电电压
    Write_Data(0x17);   //0.5*VCC Set_Gray_Scale_Table(); // 设置灰度表脉冲宽度

    Write_Command(0xB6);  //设置Second预充周期
    Write_Data(0x01);   //1个时钟周期(1DCLKS)

    Write_Command(0xBE);  //设置VCOMH电压
    Write_Data(0x05);   //0.82*VCC

    Write_Command(0xA6);  //设置显示模式:正常模式

    Fill_RAM(0x0000);  //清屏

    Write_Command(0xAF);  //开显示
}

/*font.h*/
#ifndef __FONT_H
#define __FONT_H
/************************************16*8的ACSII表************************************/
const unsigned char ACSII_Font[][16] = {
    {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*" ",32*/
    {0x00,0x00,0x00,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x00,0x10,0x10,0x00,0x00},/*"!",33*/
    {0x00,0x12,0x24,0x24,0x48,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*""",34*/
    {0x00,0x00,0x00,0x12,0x12,0x12,0x7E,0x24,0x24,0x24,0x7E,0x24,0x24,0x24,0x00,0x00},/*"#",35*/
    {0x00,0x00,0x08,0x3C,0x4A,0x4A,0x48,0x38,0x0C,0x0A,0x0A,0x4A,0x4A,0x3C,0x08,0x08},/*"$",36*/
    {0x00,0x00,0x00,0x44,0xA4,0xA8,0xA8,0xB0,0x54,0x1A,0x2A,0x2A,0x4A,0x44,0x00,0x00},/*"%",37*/
    {0x00,0x00,0x00,0x30,0x48,0x48,0x48,0x50,0x6E,0xA4,0x94,0x98,0x89,0x76,0x00,0x00},/*"&",38*/
    {0x00,0x60,0x20,0x20,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"'",39*/
    {0x00,0x02,0x04,0x08,0x08,0x10,0x10,0x10,0x10,0x10,0x10,0x08,0x08,0x04,0x02,0x00},/*"(",40*/
    {0x00,0x40,0x20,0x10,0x10,0x08,0x08,0x08,0x08,0x08,0x08,0x10,0x10,0x20,0x40,0x00},/*")",41*/
    {0x00,0x00,0x00,0x00,0x10,0x10,0xD6,0x38,0x38,0xD6,0x10,0x10,0x00,0x00,0x00,0x00},/*"*",42*/
    {0x00,0x00,0x00,0x00,0x00,0x08,0x08,0x08,0x7F,0x08,0x08,0x08,0x00,0x00,0x00,0x00},/*"+",43*/
    {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x20,0x20,0x40},/*",",44*/
    {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"-",45*/
    {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x60,0x00,0x00},/*".",46*/
    {0x00,0x00,0x02,0x04,0x04,0x04,0x08,0x08,0x10,0x10,0x10,0x20,0x20,0x40,0x40,0x00},/*"/",47*/
    {0x00,0x00,0x00,0x18,0x24,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x24,0x18,0x00,0x00},/*"0",48*/
    {0x00,0x00,0x00,0x08,0x38,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x3E,0x00,0x00},/*"1",49*/
    {0x00,0x00,0x00,0x3C,0x42,0x42,0x42,0x02,0x04,0x08,0x10,0x20,0x42,0x7E,0x00,0x00},/*"2",50*/
    {0x00,0x00,0x00,0x3C,0x42,0x42,0x02,0x04,0x18,0x04,0x02,0x42,0x42,0x3C,0x00,0x00},/*"3",51*/
    {0x00,0x00,0x00,0x04,0x0C,0x0C,0x14,0x24,0x24,0x44,0x7F,0x04,0x04,0x1F,0x00,0x00},/*"4",52*/
    {0x00,0x00,0x00,0x7E,0x40,0x40,0x40,0x78,0x44,0x02,0x02,0x42,0x44,0x38,0x00,0x00},/*"5",53*/
    {0x00,0x00,0x00,0x18,0x24,0x40,0x40,0x5C,0x62,0x42,0x42,0x42,0x22,0x1C,0x00,0x00},/*"6",54*/
    {0x00,0x00,0x00,0x7E,0x42,0x04,0x04,0x08,0x08,0x10,0x10,0x10,0x10,0x10,0x00,0x00},/*"7",55*/
    {0x00,0x00,0x00,0x3C,0x42,0x42,0x42,0x24,0x18,0x24,0x42,0x42,0x42,0x3C,0x00,0x00},/*"8",56*/
    {0x00,0x00,0x00,0x38,0x44,0x42,0x42,0x42,0x46,0x3A,0x02,0x02,0x24,0x18,0x00,0x00},/*"9",57*/
    {0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00},/*":",58*/
    {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x10,0x10,0x10},/*";",59*/
    {0x00,0x00,0x00,0x02,0x04,0x08,0x10,0x20,0x40,0x20,0x10,0x08,0x04,0x02,0x00,0x00},/*"<",60*/
    {0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00},/*"=",61*/
    {0x00,0x00,0x00,0x40,0x20,0x10,0x08,0x04,0x02,0x04,0x08,0x10,0x20,0x40,0x00,0x00},/*">",62*/
    {0x00,0x00,0x00,0x3C,0x42,0x42,0x62,0x04,0x08,0x08,0x08,0x00,0x18,0x18,0x00,0x00},/*"?",63*/
    {0x00,0x00,0x00,0x38,0x44,0x5A,0xAA,0xAA,0xAA,0xAA,0xAA,0x5C,0x42,0x3C,0x00,0x00},/*"@",64*/
    {0x00,0x00,0x00,0x10,0x10,0x18,0x28,0x28,0x24,0x3C,0x44,0x42,0x42,0xE7,0x00,0x00},/*"A",65*/
    {0x00,0x00,0x00,0xF8,0x44,0x44,0x44,0x78,0x44,0x42,0x42,0x42,0x44,0xF8,0x00,0x00},/*"B",66*/
    {0x00,0x00,0x00,0x3E,0x42,0x42,0x80,0x80,0x80,0x80,0x80,0x42,0x44,0x38,0x00,0x00},/*"C",67*/
    {0x00,0x00,0x00,0xF8,0x44,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x44,0xF8,0x00,0x00},/*"D",68*/
    {0x00,0x00,0x00,0xFC,0x42,0x48,0x48,0x78,0x48,0x48,0x40,0x42,0x42,0xFC,0x00,0x00},/*"E",69*/
    {0x00,0x00,0x00,0xFC,0x42,0x48,0x48,0x78,0x48,0x48,0x40,0x40,0x40,0xE0,0x00,0x00},/*"F",70*/
    {0x00,0x00,0x00,0x3C,0x44,0x44,0x80,0x80,0x80,0x8E,0x84,0x44,0x44,0x38,0x00,0x00},/*"G",71*/
    {0x00,0x00,0x00,0xE7,0x42,0x42,0x42,0x42,0x7E,0x42,0x42,0x42,0x42,0xE7,0x00,0x00},/*"H",72*/
    {0x00,0x00,0x00,0x7C,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x7C,0x00,0x00},/*"I",73*/
    {0x00,0x00,0x00,0x3E,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x88,0xF0},/*"J",74*/
    {0x00,0x00,0x00,0xEE,0x44,0x48,0x50,0x70,0x50,0x48,0x48,0x44,0x44,0xEE,0x00,0x00},/*"K",75*/
    {0x00,0x00,0x00,0xE0,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x42,0xFE,0x00,0x00},/*"L",76*/
    {0x00,0x00,0x00,0xEE,0x6C,0x6C,0x6C,0x6C,0x6C,0x54,0x54,0x54,0x54,0xD6,0x00,0x00},/*"M",77*/
    {0x00,0x00,0x00,0xC7,0x62,0x62,0x52,0x52,0x4A,0x4A,0x4A,0x46,0x46,0xE2,0x00,0x00},/*"N",78*/
    {0x00,0x00,0x00,0x38,0x44,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x44,0x38,0x00,0x00},/*"O",79*/
    {0x00,0x00,0x00,0xFC,0x42,0x42,0x42,0x42,0x7C,0x40,0x40,0x40,0x40,0xE0,0x00,0x00},/*"P",80*/
    {0x00,0x00,0x00,0x38,0x44,0x82,0x82,0x82,0x82,0x82,0x82,0xB2,0x4C,0x38,0x06,0x00},/*"Q",81*/
    {0x00,0x00,0x00,0xFC,0x42,0x42,0x42,0x7C,0x48,0x48,0x44,0x44,0x42,0xE3,0x00,0x00},/*"R",82*/
    {0x00,0x00,0x00,0x3E,0x42,0x42,0x40,0x20,0x18,0x04,0x02,0x42,0x42,0x7C,0x00,0x00},/*"S",83*/
    {0x00,0x00,0x00,0xFE,0x92,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x38,0x00,0x00},/*"T",84*/
    {0x00,0x00,0x00,0xE7,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x3C,0x00,0x00},/*"U",85*/
    {0x00,0x00,0x00,0xE7,0x42,0x42,0x44,0x24,0x24,0x28,0x28,0x18,0x10,0x10,0x00,0x00},/*"V",86*/
    {0x00,0x00,0x00,0xD6,0x54,0x54,0x54,0x54,0x54,0x6C,0x28,0x28,0x28,0x28,0x00,0x00},/*"W",87*/
    {0x00,0x00,0x00,0xE7,0x42,0x24,0x24,0x18,0x18,0x18,0x24,0x24,0x42,0xE7,0x00,0x00},/*"X",88*/
    {0x00,0x00,0x00,0xEE,0x44,0x44,0x28,0x28,0x10,0x10,0x10,0x10,0x10,0x38,0x00,0x00},/*"Y",89*/
    {0x00,0x00,0x00,0x7E,0x84,0x04,0x08,0x08,0x10,0x20,0x20,0x42,0x42,0xFC,0x00,0x00},/*"Z",90*/
    {0x00,0x1E,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x1E,0x00},/*"[",91*/
    {0x00,0x00,0x40,0x20,0x20,0x20,0x10,0x10,0x10,0x08,0x08,0x04,0x04,0x04,0x02,0x02},/*"\",92*/
    {0x00,0x78,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x78,0x00},/*"]",93*/
    {0x00,0x18,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"^",94*/
    {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF},/*"_",95*/
    {0x00,0x60,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"`",96*/
    {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x44,0x0C,0x34,0x44,0x4C,0x36,0x00,0x00},/*"a",97*/
    {0x00,0x00,0x00,0x00,0xC0,0x40,0x40,0x58,0x64,0x42,0x42,0x42,0x64,0x58,0x00,0x00},/*"b",98*/
    {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x22,0x40,0x40,0x40,0x22,0x1C,0x00,0x00},/*"c",99*/
    {0x00,0x00,0x00,0x00,0x06,0x02,0x02,0x3E,0x42,0x42,0x42,0x42,0x46,0x3B,0x00,0x00},/*"d",100*/
    {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3C,0x42,0x42,0x7E,0x40,0x42,0x3C,0x00,0x00},/*"e",101*/
    {0x00,0x00,0x00,0x00,0x0C,0x12,0x10,0x7C,0x10,0x10,0x10,0x10,0x10,0x7C,0x00,0x00},/*"f",102*/
    {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x44,0x44,0x38,0x40,0x3C,0x42,0x42,0x3C},/*"g",103*/
    {0x00,0x00,0x00,0x00,0xC0,0x40,0x40,0x5C,0x62,0x42,0x42,0x42,0x42,0xE7,0x00,0x00},/*"h",104*/
    {0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x70,0x10,0x10,0x10,0x10,0x10,0x7C,0x00,0x00},/*"i",105*/
    {0x00,0x00,0x00,0x0C,0x0C,0x00,0x00,0x1C,0x04,0x04,0x04,0x04,0x04,0x04,0x44,0x78},/*"j",106*/
    {0x00,0x00,0x00,0x00,0xC0,0x40,0x40,0x4E,0x48,0x50,0x70,0x48,0x44,0xEE,0x00,0x00},/*"k",107*/
    {0x00,0x00,0x00,0x10,0x70,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x7C,0x00,0x00},/*"l",108*/
    {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x49,0x49,0x49,0x49,0x49,0xED,0x00,0x00},/*"m",109*/
    {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xDC,0x62,0x42,0x42,0x42,0x42,0xE7,0x00,0x00},/*"n",110*/
    {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3C,0x42,0x42,0x42,0x42,0x42,0x3C,0x00,0x00},/*"o",111*/
    {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xD8,0x64,0x42,0x42,0x42,0x64,0x58,0x40,0xE0},/*"p",112*/
    {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1A,0x26,0x42,0x42,0x42,0x26,0x1A,0x02,0x07},/*"q",113*/
    {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xEE,0x32,0x20,0x20,0x20,0x20,0xF8,0x00,0x00},/*"r",114*/
    {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x42,0x40,0x3C,0x02,0x42,0x7C,0x00,0x00},/*"s",115*/
    {0x00,0x00,0x00,0x00,0x00,0x10,0x10,0x7C,0x10,0x10,0x10,0x10,0x12,0x0C,0x00,0x00},/*"t",116*/
    {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC6,0x42,0x42,0x42,0x42,0x46,0x3B,0x00,0x00},/*"u",117*/
    {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xEE,0x44,0x44,0x28,0x28,0x10,0x10,0x00,0x00},/*"v",118*/
    {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xDB,0x89,0x4A,0x5A,0x54,0x24,0x24,0x00,0x00},/*"w",119*/
    {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x76,0x24,0x18,0x18,0x18,0x24,0x6E,0x00,0x00},/*"x",120*/
    {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE7,0x42,0x24,0x24,0x18,0x18,0x10,0x10,0x60},/*"y",121*/
    {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x44,0x08,0x10,0x10,0x22,0x7E,0x00,0x00},/*"z",122*/
    {0x00,0x03,0x04,0x04,0x04,0x04,0x04,0x04,0x08,0x04,0x04,0x04,0x04,0x04,0x03,0x00},/*"{",123*/
    {0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08},/*"|",124*/
    {0x00,0xC0,0x20,0x20,0x20,0x20,0x20,0x20,0x10,0x20,0x20,0x20,0x20,0x20,0xC0,0x00},/*"}",125*/
    {0x20,0x5A,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"~",126*/
    {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"",127*/
};
/************************************16*16的汉字码表************************************/
const unsigned char Chinese_Font[][32] = {
    0x00,0x08,0x00,0x08,0x7C,0x08,0x44,0x08,0x45,0xFE,0x44,0x08,0x44,0x08,0x7C,0x08,
    0x44,0x88,0x44,0x48,0x44,0x48,0x44,0x08,0x7C,0x08,0x44,0x08,0x00,0x28,0x00,0x10,/*"时",0*/

    0x20,0x00,0x13,0xFC,0x10,0x04,0x40,0x04,0x47,0xC4,0x44,0x44,0x44,0x44,0x44,0x44,
    0x47,0xC4,0x44,0x44,0x44,0x44,0x44,0x44,0x47,0xC4,0x40,0x04,0x40,0x14,0x40,0x08,/*"间",1*/
};

/************************************12*12的汉字码表************************************/
const unsigned char Chinese_Font_12[][24] = {
    0x00,0x40,0xF0,0x40,0x90,0x40,0x97,0xE0,0x90,0x40,0xF0,0x40,0x92,0x40,0x91,0x40,
    0x91,0x40,0xF0,0x40,0x90,0x40,0x01,0xC0,/*"时",0*/

    0x4F,0xE0,0x20,0x20,0x00,0x20,0x5F,0xA0,0x50,0xA0,0x50,0xA0,0x5F,0xA0,0x50,0xA0,
    0x50,0xA0,0x5F,0xA0,0x40,0x20,0x40,0xE0,/*"间",1*/
};


#endif

图片数组自己取模使用函数调用就好

/*main.c*/
#include "ssd1351.h"
#include "font.h"
int main(void)
{

    SPI2_Init();//显示SPI初始化
    OLED_Init();//初始化OLED屏幕
    Fill_RAM(0x0000);	//清屏
    Display_Pattern(gImage_bck0, 0, 127, 0, 127);//图片需要自己取模更换
    Display_Chinese12x12(52,  114, 2, 0X0BFF);	//显示汉字/*"时",2*/
    Display_Chinese12x12(64,  114, 3, 0X0BFF);	//显示汉字/*"间",3*/
    Display_Circle(63,58,38,0x09FF);
}

你可能感兴趣的:(STM32)