SPI协议应用——基于STM32的软件SPI驱动0.96寸OLED

目录

引言

一、理论研究

1.1. 接线与介绍

1.2 驱动芯片命令的了解

1.3 上电初始化顺序

1.4 显示的地址映射关系

二、代码编写

2.1 SPI通信协议的初始化

2.2 五个GPIO口的写函数

2.3 SPI的四个时序函数

2.4 OLDE初始化函数

2.5 指定光标地址函数

2.6 清屏函数

2.7 OLED字模库

2.8 在OLED上写一个字符

2.9 在OLED上写一个字符串

2.10 在OLED上写一个十进制的正数数字

2.11 在OLED上显示有符号的整数

2.12 在OLED上显示十六进制正数

2.13 在OLED上显示二进制整数

2.14 在OLED上显示浮点数float

三、全部代码

3.1 MySpiOLED.c文件

3.2 MySpiOLED.h文件

3.3 OLED_Font.h文件

四、总结


引言

这篇是我在江协科技学习了SPI知识后做的第一个应用。

江协科技:b站

0.96寸OLED的使用手册地址:

http://www.lcdwiki.com/res/MSP096X/0.96inch_OLED_SPI_Module_MSP096X_User_Manual_CN.pdf

OLED的驱动芯片为 SSD1306

分辨率为 128*64(Pixel)

使用的编程语言:C语言

编译环境:Keil 5

编程芯片:STM32F103C8T6 最小系统板

一、理论研究

首先,我现在个人没多少知识点,想通过自己研究锻炼自己的手册阅读能力和自己的编程查错能力,所以我从头开始。

1.1. 接线与介绍

我在手册书上看到模块的模式介绍:

根据上面的说明,加上我自己购买的模块的背面电阻的焊接情况,所以我下面需要用的协议和模式都是对应上图的 A、选择4线制SPI总线接口,所有的引脚都需要使用

首先可以从手册中看到模块的引脚说明:

以及四线制协议介绍:

和引脚使用说明:

根据上图补充说明和对应的STM32连线:

模块的 D0 : SCK 串行时钟信号线

模块的 D1 : SDIN 模块输入信号信号线,对应STM32上的MOSI主设备输出,从设备输入数据信号线,用于STM32向OLED发送数据,高位在前,一次传输8bit数据

模块的 CS# : 即片选信号,低电平有效,对应STM32中的SS

模块的 D/C# : 芯片命令线,当D/C#线为低电平时,此时主机给OLED发送的数据代表命令,当D/C#为高电平时,此时主机给OLED发送的数据就是发送数据。

模块的RES:即复位信号,低电平有效

由上可知,四线OLED的SPI线序跟我们平常学习的有点出入,对于平常学习的SPI线序,有SCK时钟线,MOSI主机输出从机输入数据线,MISO主机输入从机输出线,SS从机选择线,这时,就会产生一个疑问?如何读取数据呢?

在使用手册中,我并没有找到这个答案。

然后,通过查阅驱动芯片 SSD1306 的使用手册:

https://www.cnblogs.com/--Destroyer--/p/12322558.html

得到关于读写指令数据的一个表格:

而我购买的模块和模块使用手册并没有提到有留出R/W#接口,但是模块又能正常的进行写指令和写数据,然后我进一步去询问AI,在AI那得出

所以我大胆猜测模块的硬件将R/W#的引脚接在了低电平上,如果后续发现这里有错误再来修改。

1.2 驱动芯片命令的了解

要想能正常驱动芯片,肯定要先了解驱动芯片的一些命令,知道命令的使用。

驱动芯片 SSD1306 的中文说明手册:

https://www.cnblogs.com/--Destroyer--/p/12322558.html

以下是说明手册中提到的命令列表:

1.3 上电初始化顺序

在驱动芯片使用手册中,可以看到OLED的上电初始化顺序

也就是说,这即是我们的OLED初始化代码的配置

当然,在配置前还需要进行写指令和写数据等的函数封装。

1.4 显示的地址映射关系

OLED屏是一个128列*64行的点阵,由于STM32一次要给OLED发送一个字节即8bit数据

所以一次操作需要控制8bit,对此,设计者将OLED的行数分为8行,也就是8页:

在左上角的起始地址坐标为(0,0)

在这里有个例子:

通俗的解释一下即是:指定了第2行的第3列的地址,在这个地址下写入一个字节数据

那么,如何知道这个地址指定的映射呢?

对比下来,页地址,也就是行的映射相对简单,0xB0 ~ 0xB7,对应了0-7行,所以可以用B0 | 输入行,得到这个地址。

即 B0 |= y,(y = 0~7)

那么,高低起始列地址代表说明意思呢?

我们的列为0~127,对比下来的二进制即 0000 0000 ~ 0111 1110

那对应的高低位,也就是将一个字节的两个四位分离出来

设置低起始列指针通过0x00 ~ 0x0F

设置高起始列指针通过0x10 ~ 0x1F

即当我指定43列的时候

43的二进制为: 0010 1011 对应 2 B

即这时高地址为:0x12 

低地址为: 0x0B

也就是说,高位地址的第四位替换为输入数的高四位,低位地址的高四位替换为输入数的低四位

我们可以用输入和0xF0相&取得高四位,和0x0F相&取得低四位,再将高四位右移动四位,然后和0x10 相 | 获得高位地址,将低四位和 0x00 相 | 获得低位数据地址

二、代码编写

接下来一步步实现软件spi通信协议和oled的接口函数

2.1 SPI通信协议的初始化

我们知道OLED的接口是

所以需要初始化

D0 推挽输出       默认低电平

D1 推挽输出       默认低电平

RES 推挽输出    默认低电平

DC 推挽输出      默认高电平

CS 推挽输出       默认高电平

我选择的引脚是PA3-PA7,所以宏定义也是PA3-PA7的宏定义

所以有初始化代码:

头文件的宏定义部分:

#define MY_SPI_OLED_RCC 	RCC_APB2Periph_GPIOA	//GPIO时钟线

#define MY_SPI_OLED_GPIOX			GPIOA //从机片选线时钟源

#define MY_SPI_OLED_CS_PIN			GPIO_Pin_4 //从机片选线,OLED的CS线
#define MY_SPI_OLED_SCK_PIN			GPIO_Pin_5 //时钟总线,OLED的D0线
#define MY_SPI_OLED_DC_PIN			GPIO_Pin_6 //OLED的DC线
#define MY_SPI_OLED_MOSI_PIN		GPIO_Pin_7 //主机输出线,OLED的D1线
#define MY_SPI_OLED_RES_PIN			GPIO_Pin_3 //OLED的复位线

spi接口初始化函数:

/*
 *	重命名SPI的RES引脚的写函数
 *	参数(uint8_t bitValue):0 低电平 1 高电平
 */
void MySpiOLED_W_RES(uint8_t bitValue)
{
		GPIO_WriteBit(MY_SPI_OLED_GPIOX, MY_SPI_OLED_RES_PIN, (BitAction)bitValue);
}

/*
 *	我的SPI时序的初始化
 *	关于引脚定义在MySPIOLED.h文件
 */
void MySPIOLED_SPI_Init(void)
{
		GPIO_InitTypeDef GPIO_InitStucture;//定义结构体。引用结构体的所有变量
		
		RCC_APB2PeriphClockCmd(MY_SPI_OLED_RCC, ENABLE);//使能时钟

		GPIO_InitStucture.GPIO_Mode = GPIO_Mode_Out_PP;//推挽输出
		GPIO_InitStucture.GPIO_Pin = MY_SPI_OLED_CS_PIN | MY_SPI_OLED_SCK_PIN
																| MY_SPI_OLED_DC_PIN | MY_SPI_OLED_MOSI_PIN 
																| MY_SPI_OLED_RES_PIN;
		GPIO_InitStucture.GPIO_Speed = GPIO_Speed_50MHz;//GPIO_Speed_50MHz指给这个配置50MHz的
		GPIO_Init(MY_SPI_OLED_GPIOX,&GPIO_InitStucture);

	
		/* 初始化后默认引脚电平设置 */
		MySpiOLED_W_SS(1);
		MySpiOLED_W_SCK(0);
		MySpiOLED_W_MOSI(0);
		MySpiOLED_W_DC(1);
		MySpiOLED_W_RES(1);
}

2.2 五个GPIO口的写函数

为了方便后续代码的编写调用和阅读,故而封装了5个写函数去控制GPIO口的输出电平

/*
 *	重命名SPI的CS引脚的写函数
 *	参数(uint8_t bitValue):0 低电平 1 高电平
 */
void MySpiOLED_W_SS(uint8_t bitValue)
{
		GPIO_WriteBit(MY_SPI_OLED_GPIOX, MY_SPI_OLED_CS_PIN, (BitAction)bitValue);
}

/*
 *	重命名SPI的SCK引脚的写函数
 *	参数(uint8_t bitValue):0 低电平 1 高电平
 */
void MySpiOLED_W_SCK(uint8_t bitValue)
{
		GPIO_WriteBit(MY_SPI_OLED_GPIOX, MY_SPI_OLED_SCK_PIN, (BitAction)bitValue);
}

/*
 *	重命名SPI的MOSI引脚的写函数
 *	参数(uint8_t bitValue):0 低电平 1 高电平
 */
void MySpiOLED_W_MOSI(uint8_t bitValue)
{
		GPIO_WriteBit(MY_SPI_OLED_GPIOX, MY_SPI_OLED_MOSI_PIN, (BitAction)bitValue);
}

/*
 *	重命名SPI的DC引脚的写函数
 *	参数(uint8_t bitValue):0 低电平 1 高电平
 */
void MySpiOLED_W_DC(uint8_t bitValue)
{
		GPIO_WriteBit(MY_SPI_OLED_GPIOX, MY_SPI_OLED_DC_PIN, (BitAction)bitValue);
}

/*
 *	重命名SPI的RES引脚的写函数
 *	参数(uint8_t bitValue):0 低电平 1 高电平
 */
void MySpiOLED_W_RES(uint8_t bitValue)
{
		GPIO_WriteBit(MY_SPI_OLED_GPIOX, MY_SPI_OLED_RES_PIN, (BitAction)bitValue);
}

2.3 SPI的四个时序函数

根据手册的时序协议:

得到下面四个基础时序

/*
 *	SPI开始条件
 */
void MySpiOLED_Start(void)
{
		MySpiOLED_W_SS(0);
}

/*
 *	SPI结束条件
 */
void MySpiOLED_Stop(void)
{
		MySpiOLED_W_SS(1);
}

/*
 *	SPI的OLED写指令
 *	参数(uint8_t byteSend):要发送的指令
 */
void MySpiOLED_WriteCommand(uint8_t byteSend)
{
		uint8_t i;
		MySpiOLED_Start();//CS低电平时序开始
		MySpiOLED_W_SCK(0);//保证时钟线一开始是低电平
		MySpiOLED_W_DC(0);//DC引脚低电平代表写指令
		for(i = 0;i < 8; i ++)
		{
			/* 移出数据 */
			MySpiOLED_W_MOSI(byteSend & 0x80);
			/* 移位 */
			byteSend <<= 1;
			//时钟线翻转
			MySpiOLED_Turn_SCK();
		}
		MySpiOLED_Stop();//CS低电平时序开始
		MySpiOLED_W_SCK(0);//保证时钟线是低电平
		MySpiOLED_W_DC(1);//DC引脚默认高电平,保护模块
}

/*
 *	SPI的OLED写数据
 *	参数(uint8_t byteSend):要发送的数据
 */
void MySpiOLED_WriteData(uint8_t byteSend)
{
		uint8_t i;
		MySpiOLED_Start();//CS低电平时序开始
		MySpiOLED_W_SCK(0);//保证时钟线一开始是低电平
		MySpiOLED_W_DC(1);//DC引脚高电平代表写数据
		for(i = 0;i < 8; i ++)
		{
			/* 移出数据 */
			MySpiOLED_W_MOSI(byteSend & 0x80);
			/* 移位 */
			byteSend <<= 1;
			//时钟线翻转
			MySpiOLED_Turn_SCK();
		}
		MySpiOLED_Stop();//CS低电平时序开始
		MySpiOLED_W_SCK(0);//保证时钟线是低电平
}

2.4 OLDE初始化函数

根据这个初始化顺序进行设计

/* 初始化OLED */
void MySpi_OLED_Init(void)
{
		uint32_t i, j;
	
		for (i = 0; i < 1000; i++)			//上电延时
		{
			for (j = 0; j < 1000; j++);
		}
		
		MySPIOLED_SPI_Init();//端口初始化
		
		MySpiOLED_WriteCommand(0xAE);	//关闭显示
		
		MySpiOLED_WriteCommand(0xD5);	//设置时钟分频率
		MySpiOLED_WriteCommand(0x80);	//设置振荡器频率
		
		MySpiOLED_WriteCommand(0xA8); //设置复用率
		MySpiOLED_WriteCommand(0x3F); //设置复用率
		
		MySpiOLED_WriteCommand(0xD3); //设置显示偏移量
		MySpiOLED_WriteCommand(0x00); //设置显示偏移量
		
		MySpiOLED_WriteCommand(0x40); //设置显示起始线
		
		MySpiOLED_WriteCommand(0xA1); //设置段重映射
		
		MySpiOLED_WriteCommand(0xC8); //设置COM输出
		
		MySpiOLED_WriteCommand(0xDA); //设置COM引脚硬件配置
		MySpiOLED_WriteCommand(0x12); //设置COM引脚硬件配置
		
		MySpiOLED_WriteCommand(0x81); //设置对比度
		MySpiOLED_WriteCommand(0x66); //设置对比度

		MySpiOLED_WriteCommand(0xD9); //设置预充电周期
		MySpiOLED_WriteCommand(0xF1); //设置预充电周期
		
		MySpiOLED_WriteCommand(0xD8); //设置VCOMH取消选择等级
		MySpiOLED_WriteCommand(0x30); //设置VCOMH取消选择等级
		
		MySpiOLED_WriteCommand(0xA4); //设置全局显示开或关
	
		MySpiOLED_WriteCommand(0xA6); //设置正常显示或反显
		
		MySpi_OLED_Clean();           //清屏
		
		MySpiOLED_WriteCommand(0x8D); //设置电荷泵
		MySpiOLED_WriteCommand(0x14); //设置电荷泵
		
		MySpiOLED_WriteCommand(0xAF); //设置显示开
		
}

2.5 指定光标地址函数

指定光标,就是通过设置OLED的RAM接收指针地址

对应地址的指令说明在本文的 1.4

下面是函数代码:

/*
 * 指定OLED的显示光标
 * 参数(uint8_t y):y 坐标 0 ~ 7
 * 参数(uint8_t x):x 坐标 0 ~ 127 
 */
void MySpi_OLED_setCursor(uint8_t y, uint8_t x)
{
		MySpiOLED_WriteCommand(0xB0 | y);									//指定y坐标
		MySpiOLED_WriteCommand(0x10 | ((x & 0xF0) >> 4)); //指定x高起始位地址
		MySpiOLED_WriteCommand(0x00 | (x & 0x0F)); //指定x高起始位地址
}

2.6 清屏函数

清屏函数,即是把整个OLED的页输入数据0x00,使屏幕的全部OLED处于关闭状态即是清屏函数,( OLED是共阴极,高电平点亮 )

/*
 * OLED清屏函数
 */
void MySpi_OLED_Clean(void)
{
		uint8_t y,x;
		for(y = 0; y < 8; y ++)
		{
				MySpi_OLED_setCursor(y , 0); 		//指定坐标
				for(x = 0; x < 128; x ++)
				{
						MySpiOLED_WriteData(0x00);	//发送数据
				}
		}
}

2.7 OLED字模库

为了更加方便显示字符,添加了一个OLED字模库,宽8像素,高16像素

#ifndef __OLED_FONT_H
#define __OLED_FONT_H

/*OLED字模库,宽8像素,高16像素*/
const uint8_t OLED_F8x16[][16]=
{
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//  0
	
	0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x33,0x30,0x00,0x00,0x00,//! 1
	
	0x00,0x10,0x0C,0x06,0x10,0x0C,0x06,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//" 2
	
	0x40,0xC0,0x78,0x40,0xC0,0x78,0x40,0x00,
	0x04,0x3F,0x04,0x04,0x3F,0x04,0x04,0x00,//# 3
	
	0x00,0x70,0x88,0xFC,0x08,0x30,0x00,0x00,
	0x00,0x18,0x20,0xFF,0x21,0x1E,0x00,0x00,//$ 4
	
	0xF0,0x08,0xF0,0x00,0xE0,0x18,0x00,0x00,
	0x00,0x21,0x1C,0x03,0x1E,0x21,0x1E,0x00,//% 5
	
	0x00,0xF0,0x08,0x88,0x70,0x00,0x00,0x00,
	0x1E,0x21,0x23,0x24,0x19,0x27,0x21,0x10,//& 6
	
	0x10,0x16,0x0E,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//' 7
	
	0x00,0x00,0x00,0xE0,0x18,0x04,0x02,0x00,
	0x00,0x00,0x00,0x07,0x18,0x20,0x40,0x00,//( 8
	
	0x00,0x02,0x04,0x18,0xE0,0x00,0x00,0x00,
	0x00,0x40,0x20,0x18,0x07,0x00,0x00,0x00,//) 9
	
	0x40,0x40,0x80,0xF0,0x80,0x40,0x40,0x00,
	0x02,0x02,0x01,0x0F,0x01,0x02,0x02,0x00,//* 10
	
	0x00,0x00,0x00,0xF0,0x00,0x00,0x00,0x00,
	0x01,0x01,0x01,0x1F,0x01,0x01,0x01,0x00,//+ 11
	
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x80,0xB0,0x70,0x00,0x00,0x00,0x00,0x00,//, 12
	
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,//- 13
	
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x30,0x30,0x00,0x00,0x00,0x00,0x00,//. 14
	
	0x00,0x00,0x00,0x00,0x80,0x60,0x18,0x04,
	0x00,0x60,0x18,0x06,0x01,0x00,0x00,0x00,/// 15
	
	0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,
	0x00,0x0F,0x10,0x20,0x20,0x10,0x0F,0x00,//0 16
	
	0x00,0x10,0x10,0xF8,0x00,0x00,0x00,0x00,
	0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//1 17
	
	0x00,0x70,0x08,0x08,0x08,0x88,0x70,0x00,
	0x00,0x30,0x28,0x24,0x22,0x21,0x30,0x00,//2 18
	
	0x00,0x30,0x08,0x88,0x88,0x48,0x30,0x00,
	0x00,0x18,0x20,0x20,0x20,0x11,0x0E,0x00,//3 19
	
	0x00,0x00,0xC0,0x20,0x10,0xF8,0x00,0x00,
	0x00,0x07,0x04,0x24,0x24,0x3F,0x24,0x00,//4 20
	
	0x00,0xF8,0x08,0x88,0x88,0x08,0x08,0x00,
	0x00,0x19,0x21,0x20,0x20,0x11,0x0E,0x00,//5 21
	
	0x00,0xE0,0x10,0x88,0x88,0x18,0x00,0x00,
	0x00,0x0F,0x11,0x20,0x20,0x11,0x0E,0x00,//6 22
	
	0x00,0x38,0x08,0x08,0xC8,0x38,0x08,0x00,
	0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x00,//7 23
	
	0x00,0x70,0x88,0x08,0x08,0x88,0x70,0x00,
	0x00,0x1C,0x22,0x21,0x21,0x22,0x1C,0x00,//8 24
	
	0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,
	0x00,0x00,0x31,0x22,0x22,0x11,0x0F,0x00,//9 25
	
	0x00,0x00,0x00,0xC0,0xC0,0x00,0x00,0x00,
	0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00,//: 26
	
	0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,
	0x00,0x00,0x80,0x60,0x00,0x00,0x00,0x00,//; 27
	
	0x00,0x00,0x80,0x40,0x20,0x10,0x08,0x00,
	0x00,0x01,0x02,0x04,0x08,0x10,0x20,0x00,//< 28
	
	0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,
	0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x00,//= 29
	
	0x00,0x08,0x10,0x20,0x40,0x80,0x00,0x00,
	0x00,0x20,0x10,0x08,0x04,0x02,0x01,0x00,//> 30
	
	0x00,0x70,0x48,0x08,0x08,0x08,0xF0,0x00,
	0x00,0x00,0x00,0x30,0x36,0x01,0x00,0x00,//? 31
	
	0xC0,0x30,0xC8,0x28,0xE8,0x10,0xE0,0x00,
	0x07,0x18,0x27,0x24,0x23,0x14,0x0B,0x00,//@ 32
	
	0x00,0x00,0xC0,0x38,0xE0,0x00,0x00,0x00,
	0x20,0x3C,0x23,0x02,0x02,0x27,0x38,0x20,//A 33
	
	0x08,0xF8,0x88,0x88,0x88,0x70,0x00,0x00,
	0x20,0x3F,0x20,0x20,0x20,0x11,0x0E,0x00,//B 34
	
	0xC0,0x30,0x08,0x08,0x08,0x08,0x38,0x00,
	0x07,0x18,0x20,0x20,0x20,0x10,0x08,0x00,//C 35
	
	0x08,0xF8,0x08,0x08,0x08,0x10,0xE0,0x00,
	0x20,0x3F,0x20,0x20,0x20,0x10,0x0F,0x00,//D 36
	
	0x08,0xF8,0x88,0x88,0xE8,0x08,0x10,0x00,
	0x20,0x3F,0x20,0x20,0x23,0x20,0x18,0x00,//E 37
	
	0x08,0xF8,0x88,0x88,0xE8,0x08,0x10,0x00,
	0x20,0x3F,0x20,0x00,0x03,0x00,0x00,0x00,//F 38
	
	0xC0,0x30,0x08,0x08,0x08,0x38,0x00,0x00,
	0x07,0x18,0x20,0x20,0x22,0x1E,0x02,0x00,//G 39
	
	0x08,0xF8,0x08,0x00,0x00,0x08,0xF8,0x08,
	0x20,0x3F,0x21,0x01,0x01,0x21,0x3F,0x20,//H 40
	
	0x00,0x08,0x08,0xF8,0x08,0x08,0x00,0x00,
	0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//I 41
	
	0x00,0x00,0x08,0x08,0xF8,0x08,0x08,0x00,
	0xC0,0x80,0x80,0x80,0x7F,0x00,0x00,0x00,//J 42
	
	0x08,0xF8,0x88,0xC0,0x28,0x18,0x08,0x00,
	0x20,0x3F,0x20,0x01,0x26,0x38,0x20,0x00,//K 43
	
	0x08,0xF8,0x08,0x00,0x00,0x00,0x00,0x00,
	0x20,0x3F,0x20,0x20,0x20,0x20,0x30,0x00,//L 44
	
	0x08,0xF8,0xF8,0x00,0xF8,0xF8,0x08,0x00,
	0x20,0x3F,0x00,0x3F,0x00,0x3F,0x20,0x00,//M 45
	
	0x08,0xF8,0x30,0xC0,0x00,0x08,0xF8,0x08,
	0x20,0x3F,0x20,0x00,0x07,0x18,0x3F,0x00,//N 46
	
	0xE0,0x10,0x08,0x08,0x08,0x10,0xE0,0x00,
	0x0F,0x10,0x20,0x20,0x20,0x10,0x0F,0x00,//O 47
	
	0x08,0xF8,0x08,0x08,0x08,0x08,0xF0,0x00,
	0x20,0x3F,0x21,0x01,0x01,0x01,0x00,0x00,//P 48
	
	0xE0,0x10,0x08,0x08,0x08,0x10,0xE0,0x00,
	0x0F,0x18,0x24,0x24,0x38,0x50,0x4F,0x00,//Q 49
	
	0x08,0xF8,0x88,0x88,0x88,0x88,0x70,0x00,
	0x20,0x3F,0x20,0x00,0x03,0x0C,0x30,0x20,//R 50
	
	0x00,0x70,0x88,0x08,0x08,0x08,0x38,0x00,
	0x00,0x38,0x20,0x21,0x21,0x22,0x1C,0x00,//S 51
	
	0x18,0x08,0x08,0xF8,0x08,0x08,0x18,0x00,
	0x00,0x00,0x20,0x3F,0x20,0x00,0x00,0x00,//T 52
	
	0x08,0xF8,0x08,0x00,0x00,0x08,0xF8,0x08,
	0x00,0x1F,0x20,0x20,0x20,0x20,0x1F,0x00,//U 53
	
	0x08,0x78,0x88,0x00,0x00,0xC8,0x38,0x08,
	0x00,0x00,0x07,0x38,0x0E,0x01,0x00,0x00,//V 54
	
	0xF8,0x08,0x00,0xF8,0x00,0x08,0xF8,0x00,
	0x03,0x3C,0x07,0x00,0x07,0x3C,0x03,0x00,//W 55
	
	0x08,0x18,0x68,0x80,0x80,0x68,0x18,0x08,
	0x20,0x30,0x2C,0x03,0x03,0x2C,0x30,0x20,//X 56
	
	0x08,0x38,0xC8,0x00,0xC8,0x38,0x08,0x00,
	0x00,0x00,0x20,0x3F,0x20,0x00,0x00,0x00,//Y 57
	
	0x10,0x08,0x08,0x08,0xC8,0x38,0x08,0x00,
	0x20,0x38,0x26,0x21,0x20,0x20,0x18,0x00,//Z 58
	
	0x00,0x00,0x00,0xFE,0x02,0x02,0x02,0x00,
	0x00,0x00,0x00,0x7F,0x40,0x40,0x40,0x00,//[ 59
	
	0x00,0x0C,0x30,0xC0,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x01,0x06,0x38,0xC0,0x00,//\ 60
	
	0x00,0x02,0x02,0x02,0xFE,0x00,0x00,0x00,
	0x00,0x40,0x40,0x40,0x7F,0x00,0x00,0x00,//] 61
	
	0x00,0x00,0x04,0x02,0x02,0x02,0x04,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//^ 62
	
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,//_ 63
	
	0x00,0x02,0x02,0x04,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//` 64
	
	0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,
	0x00,0x19,0x24,0x22,0x22,0x22,0x3F,0x20,//a 65
	
	0x08,0xF8,0x00,0x80,0x80,0x00,0x00,0x00,
	0x00,0x3F,0x11,0x20,0x20,0x11,0x0E,0x00,//b 66
	
	0x00,0x00,0x00,0x80,0x80,0x80,0x00,0x00,
	0x00,0x0E,0x11,0x20,0x20,0x20,0x11,0x00,//c 67
	
	0x00,0x00,0x00,0x80,0x80,0x88,0xF8,0x00,
	0x00,0x0E,0x11,0x20,0x20,0x10,0x3F,0x20,//d 68
	
	0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,
	0x00,0x1F,0x22,0x22,0x22,0x22,0x13,0x00,//e 69
	
	0x00,0x80,0x80,0xF0,0x88,0x88,0x88,0x18,
	0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//f 70
	
	0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x00,
	0x00,0x6B,0x94,0x94,0x94,0x93,0x60,0x00,//g 71
	
	0x08,0xF8,0x00,0x80,0x80,0x80,0x00,0x00,
	0x20,0x3F,0x21,0x00,0x00,0x20,0x3F,0x20,//h 72
	
	0x00,0x80,0x98,0x98,0x00,0x00,0x00,0x00,
	0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//i 73
	
	0x00,0x00,0x00,0x80,0x98,0x98,0x00,0x00,
	0x00,0xC0,0x80,0x80,0x80,0x7F,0x00,0x00,//j 74
	
	0x08,0xF8,0x00,0x00,0x80,0x80,0x80,0x00,
	0x20,0x3F,0x24,0x02,0x2D,0x30,0x20,0x00,//k 75
	
	0x00,0x08,0x08,0xF8,0x00,0x00,0x00,0x00,
	0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//l 76
	
	0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x00,
	0x20,0x3F,0x20,0x00,0x3F,0x20,0x00,0x3F,//m 77
	
	0x80,0x80,0x00,0x80,0x80,0x80,0x00,0x00,
	0x20,0x3F,0x21,0x00,0x00,0x20,0x3F,0x20,//n 78
	
	0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,
	0x00,0x1F,0x20,0x20,0x20,0x20,0x1F,0x00,//o 79
	
	0x80,0x80,0x00,0x80,0x80,0x00,0x00,0x00,
	0x80,0xFF,0xA1,0x20,0x20,0x11,0x0E,0x00,//p 80
	
	0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x00,
	0x00,0x0E,0x11,0x20,0x20,0xA0,0xFF,0x80,//q 81
	
	0x80,0x80,0x80,0x00,0x80,0x80,0x80,0x00,
	0x20,0x20,0x3F,0x21,0x20,0x00,0x01,0x00,//r 82
	
	0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x00,
	0x00,0x33,0x24,0x24,0x24,0x24,0x19,0x00,//s 83
	
	0x00,0x80,0x80,0xE0,0x80,0x80,0x00,0x00,
	0x00,0x00,0x00,0x1F,0x20,0x20,0x00,0x00,//t 84
	
	0x80,0x80,0x00,0x00,0x00,0x80,0x80,0x00,
	0x00,0x1F,0x20,0x20,0x20,0x10,0x3F,0x20,//u 85
	
	0x80,0x80,0x80,0x00,0x00,0x80,0x80,0x80,
	0x00,0x01,0x0E,0x30,0x08,0x06,0x01,0x00,//v 86
	
	0x80,0x80,0x00,0x80,0x00,0x80,0x80,0x80,
	0x0F,0x30,0x0C,0x03,0x0C,0x30,0x0F,0x00,//w 87
	
	0x00,0x80,0x80,0x00,0x80,0x80,0x80,0x00,
	0x00,0x20,0x31,0x2E,0x0E,0x31,0x20,0x00,//x 88
	
	0x80,0x80,0x80,0x00,0x00,0x80,0x80,0x80,
	0x80,0x81,0x8E,0x70,0x18,0x06,0x01,0x00,//y 89
	
	0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x00,
	0x00,0x21,0x30,0x2C,0x22,0x21,0x30,0x00,//z 90
	
	0x00,0x00,0x00,0x00,0x80,0x7C,0x02,0x02,
	0x00,0x00,0x00,0x00,0x00,0x3F,0x40,0x40,//{ 91
	
	0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,//| 92
	
	0x00,0x02,0x02,0x7C,0x80,0x00,0x00,0x00,
	0x00,0x40,0x40,0x3F,0x00,0x00,0x00,0x00,//} 93
	
	0x00,0x06,0x01,0x01,0x02,0x02,0x04,0x04,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//~ 94
};

#endif

在这个字模库中,一个字符占据了上下两片共16字节大小,而且排序是依据ASCII码表对应的字符串的十进制数。

例如A的ASCII码为65 ,但是这个字模库没有全包含,而是往前挪了一个空格位置,例如‘ ’的ASCII码是32,所以对应字模库上的A = 65 - 32 = 33 

2.8 在OLED上写一个字符

经过前面的种种,假设我要在屏幕上显示一个A

由字模库可以看到,一个字符占了两页地址,我们的OLED显示屏只有8页地址

所以我们只能在OLED上显示4行的 8宽 * 16高 像素 的字

那么对应的列数为128 / 8 = 16

为了更加方便使用,按照人的思维进去写坐标,所以坐标轴为 

高 1 ~ 4

宽 1 ~ 16

假如我要在 (2,4)中写入A

那我需要先把光标定义在 y 轴的 (2 - 1)* 2上,x轴的 (4 - 1) * 8 上进行写A的上半部分的八个字节

然后再在下一页的 (2 - 1)* 2 + 1 , (4 - 1) * 8 上写A的下班部分的八个字节

对应的代码就是:

/**
  *  OLED显示一个字符
  *	参数(uint8_t Line):Line 行位置,范围:1~4
  * 参数(uint8_t Column) : Column 列位置,范围:1~16
  * 参数(char Char):  Char 要显示的一个字符,范围:ASCII可见字符
  */
void MySpi_OLED_ShowChar(uint8_t Line, uint8_t Column, char Char)
{      	
	uint8_t i;
	MySpi_OLED_setCursor((Line - 1) * 2, (Column - 1) * 8);		//设置光标位置在上半部分
	for (i = 0; i < 8; i++)
	{
		MySpiOLED_WriteData(OLED_F8x16[Char - ' '][i]);			//显示上半部分内容
	}
	MySpi_OLED_setCursor((Line - 1) * 2 + 1, (Column - 1) * 8);	//设置光标位置在下半部分
	for (i = 0; i < 8; i++)
	{
		MySpiOLED_WriteData(OLED_F8x16[Char - ' '][i + 8]);		//显示下半部分内容
	}
}

编写测试代码进行测试:

int main(void)
{

	MySpi_OLED_Init();

	MySpi_OLED_ShowChar(2,4,'B');
	MySpi_OLED_ShowChar(3,6,'H');
	MySpi_OLED_ShowChar(1,10,'4');
	while(1)
	{

	}
}//最后一行要空行,不然会报警告

得到测试结果:

证明初始化等函数并无问题。

2.9 在OLED上写一个字符串

这个函数就比较简单了,知道了如何写一个字符,那就是将字符串里的字符依次取出,用写字符的函数去写完整的字符。

/**
  *  OLED显示一个字符串
  *	参数(uint8_t Line):Line 行位置,范围:1~4
  * 参数(uint8_t Column) : Column 列位置,范围:1~16
  * 参数(char *String):  String 要显示的一个字符,范围:ASCII可见字符
  */
void MySpi_OLED_ShowString(uint8_t Line, uint8_t Column, char* String)
{      	
		uint8_t i;
		for(i = 0;String[i] != '\0'; i ++)
		{
				MySpi_OLED_ShowChar(Line, Column + i, String[i]);//依次写入每个字符
		}
}

测试代码:

int main(void)
{

		MySpi_OLED_Init();

		MySpi_OLED_ShowString(1,2,"niuBiDeYi");
		MySpi_OLED_ShowString(2,2,"niu:1234");
		while(1)
		{

		}
}//最后一行要空行,不然会报警告

2.10 在OLED上写一个十进制的正数数字

字符串会写了,如何写正数呢?

整数的范围是:0~4294967295(32位)

那么,首先就要依次从高位获取这个数据上的数

例如 1234 依次获取 1 ,2  , 3   , 4

然后按照字符输入的函数输入进去即可

获取这个数的个位数,则需要用到辗转相除法,即1234 / 1000 = 1(只取整数),1 % 10 = 1, 1234 / 100 = 12 ,12 % 10 = 2,这样即可依次得到这个 数的每个位数

代码如下:

/*
 * 获取一个数的n次方
 * 参数(uint32_t num):这个正整数
 * 参数(uint32_t n):这个正整数的n次
 * 返回值(uint32_t): 这个数求得的n次方 
 */
uint32_t getPower(uint32_t num, uint32_t n)
{
		uint32_t i,count = 1;
		for(i = 1; i <= n; i++)
		{
				count *= num;
		}
		return count;
}

/*
 * 在屏幕上输出一个正整数 范围 :0 ~ 4294967295
 *	参数(uint8_t Line):Line 行位置,范围:1~4
 * 参数(uint8_t Column) : Column 列位置,范围:1~16
 * 参数(uint32_t num):这个正整数
 * 参数(uint32_t length):这个正整数的长度,长度的范围:1 ~ 10
 */
void MySpi_OLED_ShowNum(uint8_t Line, uint8_t Column, uint32_t num, uint32_t length)
{
		uint32_t i;
		for( i = 0; i < length; i++)
		{
				MySpi_OLED_ShowChar(Line, Column + i, num / getPower(10 , (length - i - 1)) % 10 + '0');//将这个数的每位数据转换为字符后再依次显示
		}
}

测试代码:


int main(void)
{

		MySpi_OLED_Init();

		MySpi_OLED_ShowNum(2,2,12345,5);
		MySpi_OLED_ShowNum(4,4,67890,5);
		while(1)
		{

		}
}//最后一行要空行,不然会报警告

测试结果:

2.11 在OLED上显示有符号的整数

这个的字的显示逻辑跟2.10是一样的,但是有一些步骤的区别

输入数据的范围是:-2147483648~2147483647

以及第一位显示的应该是这个数的符号,即正负号,所以需要通过对这个数的判断,然后为了方便取余操作,需要获取这个数的绝对值。

代码如下:

/*
 * 在屏幕上输出一个十进制带符号整数 范围 :-2147483648~2147483647
 * 参数(uint8_t Line):Line 行位置,范围:1~4
 * 参数(uint8_t Column) :Column 列位置,范围:1~16
 * 参数(int32_t num):这个整数
 * 参数(uint32_t length):这个整数的长度,长度的范围:1 ~ 10
 */
void MySpi_OLED_ShowSingeNum(uint8_t Line, uint8_t Column, int32_t num, uint32_t length)
{
		uint32_t i,absNum = 0;
		if(num > 0)
		{
				MySpi_OLED_ShowChar(Line, Column, '+');
				absNum = num;
		}
		else if(num < 0)
		{
				MySpi_OLED_ShowChar(Line, Column, '-');
				absNum = -num;
		}
		for( i = 0; i < length; i++)
		{
				MySpi_OLED_ShowChar(Line, Column + i + 1, absNum / getPower(10 , (length - i - 1)) % 10 + '0');//将这个数的每位数据转换为字符后再依次显示
		}
}

测试代码:

int main(void)
{

		MySpi_OLED_Init();

		MySpi_OLED_ShowSingeNum(2,2,12345,5);
		MySpi_OLED_ShowSingeNum(4,4,-67890,5);
		while(1)
		{

		}
}//最后一行要空行,不然会报警告

测试结果:

2.12 在OLED上显示十六进制正数

这个显示的原理和十进制的类似,因为输入的是十进制数,所以需要进行十六进制转换,用辗转相除法让输入数对16等进行处理,得到的数据需要通过判断,如果小于10就输出本身,如果大于10就需要转换为对应的A~F再输出

代码如下:

/*
 * 在屏幕上输出一个十六进制正整数 显示的范围 :0~0xFFFFFFFF
 * 参数(uint8_t Line):Line 行位置,范围:1~4
 * 参数(uint8_t Column) : Column 列位置,范围:1~16
 * 参数(uint32_t num):这个整数
 * 参数(uint32_t length):这个正整数的长度 , 长度范围 1~8
 */
void MySpi_OLED_ShowHexNum(uint8_t Line, uint8_t Column, uint32_t num, uint32_t length)
{
		uint32_t i,hexNumber;
		for( i = 0; i < length; i++)
		{
				hexNumber =  num / getPower(16 , (length - i - 1)) % 16;
				if (hexNumber < 10)
					MySpi_OLED_ShowChar(Line, Column + i, hexNumber + '0');//将这个数的每位数据转换为字符后再依次显示
				else
					MySpi_OLED_ShowChar(Line, Column + i, hexNumber - 10 + 'A');
		}
}

测试代码:

int main(void)
{

		MySpi_OLED_Init();

		MySpi_OLED_ShowHexNum(2,2,10,2);
		MySpi_OLED_ShowHexNum(4,4,128,2);

		while(1)
		{

		}
}//最后一行要空行,不然会报警告

测试结果:

2.13 在OLED上显示二进制整数

二进制整数的显示和十进制的很像,通过不断地辗转相除法进行求值,再依次显示这个值。

代码如下:

/*
 * 在屏幕上输出一个二进制正整数 显示的范围 :1111 1111 1111 1111
 * 参数(uint8_t Line):Line 行位置,范围:1~4
 * 参数(uint8_t Column) : Column 列位置,范围:1~16
 * 参数(uint32_t num):这个整数
 * 参数(uint8_t length):这个正整数的长度 , 长度范围 1~16
 */
void MySpi_OLED_ShowBinNum(uint8_t Line, uint8_t Column, uint32_t num, uint8_t length)
{
		uint32_t i,hexNumber;
		for( i = 0; i < length; i++)
		{
				hexNumber =  num / getPower(2 , (length - i - 1)) % 2;
				MySpi_OLED_ShowChar(Line, Column + i, hexNumber + '0');//将这个数的每位数据转换为字符后再依次显示
		}
}

测试代码:

int main(void)
{

		MySpi_OLED_Init();

		MySpi_OLED_ShowBinNum(2,2,7,4);
		MySpi_OLED_ShowBinNum(4,4,55,8);

		while(1)
		{

		}
}//最后一行要空行,不然会报警告

测试结果:

2.14 在OLED上显示浮点数float

显示float类型数据,首先需要将小数部分和整数部分分离开来,然后先显示这个数的正负号,再显示这个数的整数部分,然后再显示小数点,再显示这个数的小数部分.。

代码如下:

/*
 * 在屏幕上输出一个float/double 型数据
 * 参数(uint8_t Line):Line 行位置,范围:1~4
 * 参数(uint8_t Column) : Column 列位置,范围:1~16
 * 参数(const float number):要显示的float/double型数据
 * 参数(uint32_t num):这个整数的长度,长度范围0~8
 * 参数(uint8_t length):这个小数的长度 , 长度范围 1~6
 */
void MySpi_OLED_ShowFloatNum(uint8_t Line, uint8_t Column, const float number, uint8_t num, uint8_t length)
{
    uint32_t i;
    int32_t integer = (int32_t)number; // 获取整数部分
    uint32_t diget;
    float decimal = number - integer; // 获取小数部分

    // 判断正负号
    if (integer < 0)
    {
        MySpi_OLED_ShowChar(Line, Column, '-');
        integer = -integer;
        decimal = -decimal;
        Column++;
    }

    // 显示整数部分
    for (i = 0; i < num; i++)
    {
        MySpi_OLED_ShowChar(Line, Column + i, integer / getPower(10, (num - i - 1)) % 10 + '0');
    }

    // 显示小数点
    MySpi_OLED_ShowChar(Line, Column + num, '.');

    // 显示小数部分
    decimal *= getPower(10, length);
    diget = (uint32_t)decimal;
    for (i = 0; i < length; i++)
    {
        MySpi_OLED_ShowChar(Line, Column + num + 1 + i, diget / getPower(10, (length - i - 1)) % 10 + '0');
    }
}

测试代码:


int main(void)
{

		MySpi_OLED_Init();

		MySpi_OLED_ShowFloatNum(2,2,0.34,3,6);
		MySpi_OLED_ShowFloatNum(4,2,292.381,4,6);
		while(1)
		{

		}
}//最后一行要空行,不然会报警告

测试结果:

很明显,这个测试结果跟我们期望的值并没有对应上,但是我发现这个数是偶然的,也就是说,如果我输入的292.34,它并不会出现这个情况,为此,我留下这一个疑问,等待后续学习后再进行解决。

三、全部代码

3.1 MySpiOLED.c文件

#include "MySpiOLED.h"

extern const uint8_t OLED_F8x16[][16];
/*
 *	重命名SPI的CS引脚的写函数
 *	参数(uint8_t bitValue):0 低电平 1 高电平
 */
void MySpiOLED_W_SS(uint8_t bitValue)
{
		GPIO_WriteBit(MY_SPI_OLED_GPIOX, MY_SPI_OLED_CS_PIN, (BitAction)bitValue);
}

/*
 *	重命名SPI的SCK引脚的写函数
 *	参数(uint8_t bitValue):0 低电平 1 高电平
 */
void MySpiOLED_W_SCK(uint8_t bitValue)
{
		GPIO_WriteBit(MY_SPI_OLED_GPIOX, MY_SPI_OLED_SCK_PIN, (BitAction)bitValue);
}

/*
 *	重命名SPI的SCK引脚,功能翻转时钟线
 */
void MySpiOLED_Turn_SCK(void)
{
		GPIO_WriteBit(MY_SPI_OLED_GPIOX, MY_SPI_OLED_SCK_PIN, (BitAction)(~GPIO_ReadOutputDataBit(MY_SPI_OLED_GPIOX, MY_SPI_OLED_SCK_PIN)));
}

/*
 *	重命名SPI的MOSI引脚的写函数
 *	参数(uint8_t bitValue):0 低电平 1 高电平
 */
void MySpiOLED_W_MOSI(uint8_t bitValue)
{
		GPIO_WriteBit(MY_SPI_OLED_GPIOX, MY_SPI_OLED_MOSI_PIN, (BitAction)bitValue);
}

/*
 *	重命名SPI的DC引脚的写函数
 *	参数(uint8_t bitValue):0 低电平 1 高电平
 */
void MySpiOLED_W_DC(uint8_t bitValue)
{
		GPIO_WriteBit(MY_SPI_OLED_GPIOX, MY_SPI_OLED_DC_PIN, (BitAction)bitValue);
}

/*
 *	重命名SPI的RES引脚的写函数
 *	参数(uint8_t bitValue):0 低电平 1 高电平
 */
void MySpiOLED_W_RES(uint8_t bitValue)
{
		GPIO_WriteBit(MY_SPI_OLED_GPIOX, MY_SPI_OLED_RES_PIN, (BitAction)bitValue);
}

/*
 *	我的SPI时序的初始化
 *	关于引脚定义在MySPIOLED.h文件
 */
void MySPIOLED_SPI_Init(void)
{
		GPIO_InitTypeDef GPIO_InitStucture;//定义结构体。引用结构体的所有变量
		
		RCC_APB2PeriphClockCmd(MY_SPI_OLED_RCC, ENABLE);//使能时钟

		GPIO_InitStucture.GPIO_Mode = GPIO_Mode_Out_PP;//推挽输出
		GPIO_InitStucture.GPIO_Pin = MY_SPI_OLED_CS_PIN | MY_SPI_OLED_SCK_PIN
																| MY_SPI_OLED_DC_PIN | MY_SPI_OLED_MOSI_PIN 
																| MY_SPI_OLED_RES_PIN;
		GPIO_InitStucture.GPIO_Speed = GPIO_Speed_50MHz;//GPIO_Speed_50MHz指给这个配置50MHz的
		GPIO_Init(MY_SPI_OLED_GPIOX,&GPIO_InitStucture);

	
		/* 初始化后默认引脚电平设置 */
		MySpiOLED_W_SS(1);
		MySpiOLED_W_SCK(0);
		MySpiOLED_W_MOSI(0);
		MySpiOLED_W_DC(1);
		MySpiOLED_W_RES(1);
}

/*
 *	SPI开始条件
 */
void MySpiOLED_Start(void)
{
		MySpiOLED_W_SS(0);
}

/*
 *	SPI结束条件
 */
void MySpiOLED_Stop(void)
{
		MySpiOLED_W_SS(1);
}

/*
 *	SPI的OLED写指令
 *	参数(uint8_t byteSend):要发送的指令
 */
void MySpiOLED_WriteCommand(uint8_t byteSend)
{
		uint8_t i;
		MySpiOLED_Start();//CS低电平时序开始
		MySpiOLED_W_DC(0);//DC引脚低电平代表写指令
		for(i = 0;i < 8; i ++)
		{
			/* 移出数据 */
			MySpiOLED_W_MOSI(byteSend & 0x80);
			/* 移位 */
			byteSend <<= 1;
			//时钟线翻转
			MySpiOLED_W_SCK(1);
			MySpiOLED_W_SCK(0);
		}
		MySpiOLED_Stop();//CS低电平时序开始
		MySpiOLED_W_DC(1);//DC引脚默认高电平,保护模块
}

/*
 *	SPI的OLED写数据
 *	参数(uint8_t byteSend):要发送的数据
 */
void MySpiOLED_WriteData(uint8_t byteSend)
{
		uint8_t i;
		MySpiOLED_Start();//CS低电平时序开始
		MySpiOLED_W_DC(1);//DC引脚高电平代表写数据
		for(i = 0;i < 8; i ++)
		{
			/* 移出数据 */
			MySpiOLED_W_MOSI(byteSend & 0x80);
			/* 移位 */
			byteSend <<= 1;
			//时钟线翻转
			MySpiOLED_W_SCK(1);
			MySpiOLED_W_SCK(0);
		}
		MySpiOLED_Stop();//CS低电平时序开始
}

/*
 * 指定OLED的显示光标
 * 参数(uint8_t y):y 坐标 0 ~ 7
 * 参数(uint8_t x):x 坐标 0 ~ 127 
 */
void MySpi_OLED_setCursor(uint8_t y, uint8_t x)
{
		MySpiOLED_WriteCommand(0xB0 | y);									//指定y坐标
		MySpiOLED_WriteCommand(0x10 | ((x & 0xF0) >> 4)); //指定x高起始位地址
		MySpiOLED_WriteCommand(0x00 | (x & 0x0F)); //指定x高起始位地址
}

/*
 * OLED清屏函数
 */
void MySpi_OLED_Clean(void)
{
		uint8_t y,x;
		for(y = 0; y < 8; y ++)
		{
				MySpi_OLED_setCursor(y , 0); 		//指定坐标
				for(x = 0; x < 128; x ++)
				{
						MySpiOLED_WriteData(0x00);	//发送数据
				}
		}
}


/**
  *  OLED显示一个字符
  *	参数(uint8_t Line):Line 行位置,范围:1~4
  * 参数(uint8_t Column) : Column 列位置,范围:1~16
  * 参数(char Char):  Char 要显示的一个字符,范围:ASCII可见字符
  */
void MySpi_OLED_ShowChar(uint8_t Line, uint8_t Column, char Char)
{      	
		uint8_t i;
		MySpi_OLED_setCursor((Line - 1) * 2, (Column - 1) * 8);		//设置光标位置在上半部分
		for (i = 0; i < 8; i++)
		{
			MySpiOLED_WriteData(OLED_F8x16[Char - ' '][i]);			//显示上半部分内容
		}
		MySpi_OLED_setCursor((Line - 1) * 2 + 1, (Column - 1) * 8);	//设置光标位置在下半部分
		for (i = 0; i < 8; i++)
		{
			MySpiOLED_WriteData(OLED_F8x16[Char - ' '][i + 8]);		//显示下半部分内容
		}
}

/**
  *  OLED显示一个字符串
  *	参数(uint8_t Line):Line 行位置,范围:1~4
  * 参数(uint8_t Column) : Column 列位置,范围:1~16
  * 参数(char *String):  String 要显示的一个字符,范围:ASCII可见字符
  */
void MySpi_OLED_ShowString(uint8_t Line, uint8_t Column, char* String)
{      	
		uint8_t i;
		for(i = 0;String[i] != '\0'; i ++)
		{
				MySpi_OLED_ShowChar(Line, Column + i, String[i]);//依次写入每个字符
		}
}

/*
 * 获取一个数的n次方
 * 参数(uint32_t num):这个正整数
 * 参数(uint32_t n):这个正整数的n次
 * 返回值(uint32_t): 这个数求得的n次方 
 */
uint32_t getPower(uint32_t num, uint32_t n)
{
		uint32_t i,count = 1;
		for(i = 1; i <= n; i++)
		{
				count *= num;
		}
		return count;
}

/*
 * 在屏幕上输出一个十进制正整数 范围 :0 ~ 4294967295
 * 参数(uint8_t Line):Line 行位置,范围:1~4
 * 参数(uint8_t Column) : Column 列位置,范围:1~16
 * 参数(uint32_t num):这个正整数
 * 参数(uint8_t length):这个正整数的长度 ,长度的范围:1 ~ 10
 */
void MySpi_OLED_ShowNum(uint8_t Line, uint8_t Column, uint32_t num, uint8_t length)
{
		uint32_t i;
		for( i = 0; i < length; i++)
		{
				MySpi_OLED_ShowChar(Line, Column + i, num / getPower(10 , (length - i - 1)) % 10 + '0');//将这个数的每位数据转换为字符后再依次显示
		}
}

/*
 * 在屏幕上输出一个十进制带符号整数 范围 :-2147483648~2147483647
 * 参数(uint8_t Line):Line 行位置,范围:1~4
 * 参数(uint8_t Column) :Column 列位置,范围:1~16
 * 参数(int32_t num):这个整数
 * 参数(uint8_t length):这个整数的长度 ,长度的范围:1~10
 */
void MySpi_OLED_ShowSingeNum(uint8_t Line, uint8_t Column, int32_t num, uint8_t length)
{
		uint32_t i,absNum = 0;
		if(num > 0)
		{
				MySpi_OLED_ShowChar(Line, Column, '+');
				absNum = num;
		}
		else if(num < 0)
		{
				MySpi_OLED_ShowChar(Line, Column, '-');
				absNum = -num;
		}
		for( i = 0; i < length; i++)
		{
				MySpi_OLED_ShowChar(Line, Column + i + 1, absNum / getPower(10 , (length - i - 1)) % 10 + '0');//将这个数的每位数据转换为字符后再依次显示
		}
}

/*
 * 在屏幕上输出一个十六进制正整数 显示的范围 :0~0xFFFFFFFF
 * 参数(uint8_t Line):Line 行位置,范围:1~4
 * 参数(uint8_t Column) : Column 列位置,范围:1~16
 * 参数(uint32_t num):这个整数
 * 参数(uint8_t length):这个正整数的长度 , 长度范围 1~8
 */
void MySpi_OLED_ShowHexNum(uint8_t Line, uint8_t Column, uint32_t num, uint8_t length)
{
		uint32_t i,hexNumber;
		for( i = 0; i < length; i++)
		{
				hexNumber =  num / getPower(16 , (length - i - 1)) % 16;
				if (hexNumber < 10)
					MySpi_OLED_ShowChar(Line, Column + i, hexNumber + '0');//将这个数的每位数据转换为字符后再依次显示
				else
					MySpi_OLED_ShowChar(Line, Column + i, hexNumber - 10 + 'A');
		}
}

/*
 * 在屏幕上输出一个二进制正整数 显示的范围 :1111 1111 1111 1111
 * 参数(uint8_t Line):Line 行位置,范围:1~4
 * 参数(uint8_t Column) : Column 列位置,范围:1~16
 * 参数(uint32_t num):这个整数
 * 参数(uint8_t length):这个正整数的长度 , 长度范围 1~16
 */
void MySpi_OLED_ShowBinNum(uint8_t Line, uint8_t Column, uint32_t num, uint8_t length)
{
		uint32_t i,hexNumber;
		for( i = 0; i < length; i++)
		{
				hexNumber =  num / getPower(2 , (length - i - 1)) % 2;
				MySpi_OLED_ShowChar(Line, Column + i, hexNumber + '0');//将这个数的每位数据转换为字符后再依次显示
		}
}

/*
 * 在屏幕上输出一个float/double 型数据
 * 参数(uint8_t Line):Line 行位置,范围:1~4
 * 参数(uint8_t Column) : Column 列位置,范围:1~16
 * 参数(const float number):要显示的float/double型数据
 * 参数(uint32_t num):这个整数的长度,长度范围0~8
 * 参数(uint8_t length):这个小数的长度 , 长度范围 1~6
 */
void MySpi_OLED_ShowFloatNum(uint8_t Line, uint8_t Column, const float number, uint8_t num, uint8_t length)
{
    uint32_t i;
    int32_t integer = (int32_t)number; // 获取整数部分
    uint32_t diget;
    float decimal = number - integer; // 获取小数部分

    // 判断正负号
    if (integer < 0)
    {
        MySpi_OLED_ShowChar(Line, Column, '-');
        integer = -integer;
        decimal = -decimal;
        Column++;
    }

    // 显示整数部分
    for (i = 0; i < num; i++)
    {
        MySpi_OLED_ShowChar(Line, Column + i, integer / getPower(10, (num - i - 1)) % 10 + '0');
    }

    // 显示小数点
    MySpi_OLED_ShowChar(Line, Column + num, '.');

    // 显示小数部分
    decimal *= getPower(10, length);
    diget = (uint32_t)decimal;
    for (i = 0; i < length; i++)
    {
        MySpi_OLED_ShowChar(Line, Column + num + 1 + i, diget / getPower(10, (length - i - 1)) % 10 + '0');
    }
}

/* 初始化OLED */
void MySpi_OLED_Init(void)
{
		uint32_t i, j;
	
		for (i = 0; i < 1000; i++)			//上电延时
		{
			for (j = 0; j < 1000; j++);
		}
		
		MySPIOLED_SPI_Init();//端口初始化
		
		MySpiOLED_WriteCommand(0xAE);	//关闭显示
		
		MySpiOLED_WriteCommand(0xD5);	//设置时钟分频率
		MySpiOLED_WriteCommand(0x80);	//设置振荡器频率
		
		MySpiOLED_WriteCommand(0xA8); //设置复用率
		MySpiOLED_WriteCommand(0x3F); //设置复用率
		
		MySpiOLED_WriteCommand(0xD3); //设置显示偏移量
		MySpiOLED_WriteCommand(0x00); //设置显示偏移量
		
		MySpiOLED_WriteCommand(0x40); //设置显示起始线
		
		MySpiOLED_WriteCommand(0xA1); //设置段重映射
		
		MySpiOLED_WriteCommand(0xC8); //设置COM输出
		
		MySpiOLED_WriteCommand(0xDA); //设置COM引脚硬件配置
		MySpiOLED_WriteCommand(0x12); //设置COM引脚硬件配置
		
		MySpiOLED_WriteCommand(0x81); //设置对比度
		MySpiOLED_WriteCommand(0x66); //设置对比度

		MySpiOLED_WriteCommand(0xD9); //设置预充电周期
		MySpiOLED_WriteCommand(0xF1); //设置预充电周期
		
		MySpiOLED_WriteCommand(0xD8); //设置VCOMH取消选择等级
		MySpiOLED_WriteCommand(0x30); //设置VCOMH取消选择等级
		
		MySpiOLED_WriteCommand(0xA4); //设置全局显示开或关
	
		MySpiOLED_WriteCommand(0xA6); //设置正常显示或反显
		
		MySpi_OLED_Clean();						//清屏
		
		MySpiOLED_WriteCommand(0x8D); //设置电荷泵
		MySpiOLED_WriteCommand(0x14); //设置电荷泵
		
		MySpiOLED_WriteCommand(0xAF); //设置显示开
		
}

3.2 MySpiOLED.h文件

#ifndef __MYSPIOLED_H//如果没有定义
#define __MYSPIOLED_H//这行就会定义__KEY_H
#include "stm32f10x.h"                  // Device header


#define MY_SPI_OLED_RCC 	RCC_APB2Periph_GPIOA	//GPIO时钟线

#define MY_SPI_OLED_GPIOX			GPIOA //从机片选线时钟源

#define MY_SPI_OLED_CS_PIN			GPIO_Pin_4 //从机片选线,OLED的CS线
#define MY_SPI_OLED_SCK_PIN			GPIO_Pin_5 //时钟总线,OLED的D0线
#define MY_SPI_OLED_DC_PIN			GPIO_Pin_6 //OLED的DC线
#define MY_SPI_OLED_MOSI_PIN		GPIO_Pin_7 //主机输出线,OLED的D1线
#define MY_SPI_OLED_RES_PIN			GPIO_Pin_3 //OLED的复位线


/* 初始化OLED */
void MySpi_OLED_Init(void);
//显示一个字符
void MySpi_OLED_ShowChar(uint8_t Line, uint8_t Column, char Char);
//显示一个字符串
void MySpi_OLED_ShowString(uint8_t Line, uint8_t Column, char* String);
//显示一个十进制正整数
void MySpi_OLED_ShowNum(uint8_t Line, uint8_t Column, uint32_t num, uint8_t length);
//显示一个十进制带符号整数
void MySpi_OLED_ShowSingeNum(uint8_t Line, uint8_t Column, int32_t num, uint8_t length);
//显示一个十六进制正整数
void MySpi_OLED_ShowHexNum(uint8_t Line, uint8_t Column, uint32_t num, uint8_t length);
//显示一个二进制正整数
void MySpi_OLED_ShowBinNum(uint8_t Line, uint8_t Column, uint32_t num, uint8_t length);
//显示一个float/double数据
void MySpi_OLED_ShowFloatNum(uint8_t Line, uint8_t Column, const float number, uint8_t num, uint8_t length);

#endif 

3.3 OLED_Font.h文件

#ifndef __OLED_FONT_H
#define __OLED_FONT_H

/*OLED字模库,宽8像素,高16像素*/
const uint8_t OLED_F8x16[][16]=
{
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//  0
	
	0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x33,0x30,0x00,0x00,0x00,//! 1
	
	0x00,0x10,0x0C,0x06,0x10,0x0C,0x06,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//" 2
	
	0x40,0xC0,0x78,0x40,0xC0,0x78,0x40,0x00,
	0x04,0x3F,0x04,0x04,0x3F,0x04,0x04,0x00,//# 3
	
	0x00,0x70,0x88,0xFC,0x08,0x30,0x00,0x00,
	0x00,0x18,0x20,0xFF,0x21,0x1E,0x00,0x00,//$ 4
	
	0xF0,0x08,0xF0,0x00,0xE0,0x18,0x00,0x00,
	0x00,0x21,0x1C,0x03,0x1E,0x21,0x1E,0x00,//% 5
	
	0x00,0xF0,0x08,0x88,0x70,0x00,0x00,0x00,
	0x1E,0x21,0x23,0x24,0x19,0x27,0x21,0x10,//& 6
	
	0x10,0x16,0x0E,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//' 7
	
	0x00,0x00,0x00,0xE0,0x18,0x04,0x02,0x00,
	0x00,0x00,0x00,0x07,0x18,0x20,0x40,0x00,//( 8
	
	0x00,0x02,0x04,0x18,0xE0,0x00,0x00,0x00,
	0x00,0x40,0x20,0x18,0x07,0x00,0x00,0x00,//) 9
	
	0x40,0x40,0x80,0xF0,0x80,0x40,0x40,0x00,
	0x02,0x02,0x01,0x0F,0x01,0x02,0x02,0x00,//* 10
	
	0x00,0x00,0x00,0xF0,0x00,0x00,0x00,0x00,
	0x01,0x01,0x01,0x1F,0x01,0x01,0x01,0x00,//+ 11
	
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x80,0xB0,0x70,0x00,0x00,0x00,0x00,0x00,//, 12
	
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,//- 13
	
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x30,0x30,0x00,0x00,0x00,0x00,0x00,//. 14
	
	0x00,0x00,0x00,0x00,0x80,0x60,0x18,0x04,
	0x00,0x60,0x18,0x06,0x01,0x00,0x00,0x00,/// 15
	
	0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,
	0x00,0x0F,0x10,0x20,0x20,0x10,0x0F,0x00,//0 16
	
	0x00,0x10,0x10,0xF8,0x00,0x00,0x00,0x00,
	0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//1 17
	
	0x00,0x70,0x08,0x08,0x08,0x88,0x70,0x00,
	0x00,0x30,0x28,0x24,0x22,0x21,0x30,0x00,//2 18
	
	0x00,0x30,0x08,0x88,0x88,0x48,0x30,0x00,
	0x00,0x18,0x20,0x20,0x20,0x11,0x0E,0x00,//3 19
	
	0x00,0x00,0xC0,0x20,0x10,0xF8,0x00,0x00,
	0x00,0x07,0x04,0x24,0x24,0x3F,0x24,0x00,//4 20
	
	0x00,0xF8,0x08,0x88,0x88,0x08,0x08,0x00,
	0x00,0x19,0x21,0x20,0x20,0x11,0x0E,0x00,//5 21
	
	0x00,0xE0,0x10,0x88,0x88,0x18,0x00,0x00,
	0x00,0x0F,0x11,0x20,0x20,0x11,0x0E,0x00,//6 22
	
	0x00,0x38,0x08,0x08,0xC8,0x38,0x08,0x00,
	0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x00,//7 23
	
	0x00,0x70,0x88,0x08,0x08,0x88,0x70,0x00,
	0x00,0x1C,0x22,0x21,0x21,0x22,0x1C,0x00,//8 24
	
	0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,
	0x00,0x00,0x31,0x22,0x22,0x11,0x0F,0x00,//9 25
	
	0x00,0x00,0x00,0xC0,0xC0,0x00,0x00,0x00,
	0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00,//: 26
	
	0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,
	0x00,0x00,0x80,0x60,0x00,0x00,0x00,0x00,//; 27
	
	0x00,0x00,0x80,0x40,0x20,0x10,0x08,0x00,
	0x00,0x01,0x02,0x04,0x08,0x10,0x20,0x00,//< 28
	
	0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,
	0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x00,//= 29
	
	0x00,0x08,0x10,0x20,0x40,0x80,0x00,0x00,
	0x00,0x20,0x10,0x08,0x04,0x02,0x01,0x00,//> 30
	
	0x00,0x70,0x48,0x08,0x08,0x08,0xF0,0x00,
	0x00,0x00,0x00,0x30,0x36,0x01,0x00,0x00,//? 31
	
	0xC0,0x30,0xC8,0x28,0xE8,0x10,0xE0,0x00,
	0x07,0x18,0x27,0x24,0x23,0x14,0x0B,0x00,//@ 32
	
	0x00,0x00,0xC0,0x38,0xE0,0x00,0x00,0x00,
	0x20,0x3C,0x23,0x02,0x02,0x27,0x38,0x20,//A 33
	
	0x08,0xF8,0x88,0x88,0x88,0x70,0x00,0x00,
	0x20,0x3F,0x20,0x20,0x20,0x11,0x0E,0x00,//B 34
	
	0xC0,0x30,0x08,0x08,0x08,0x08,0x38,0x00,
	0x07,0x18,0x20,0x20,0x20,0x10,0x08,0x00,//C 35
	
	0x08,0xF8,0x08,0x08,0x08,0x10,0xE0,0x00,
	0x20,0x3F,0x20,0x20,0x20,0x10,0x0F,0x00,//D 36
	
	0x08,0xF8,0x88,0x88,0xE8,0x08,0x10,0x00,
	0x20,0x3F,0x20,0x20,0x23,0x20,0x18,0x00,//E 37
	
	0x08,0xF8,0x88,0x88,0xE8,0x08,0x10,0x00,
	0x20,0x3F,0x20,0x00,0x03,0x00,0x00,0x00,//F 38
	
	0xC0,0x30,0x08,0x08,0x08,0x38,0x00,0x00,
	0x07,0x18,0x20,0x20,0x22,0x1E,0x02,0x00,//G 39
	
	0x08,0xF8,0x08,0x00,0x00,0x08,0xF8,0x08,
	0x20,0x3F,0x21,0x01,0x01,0x21,0x3F,0x20,//H 40
	
	0x00,0x08,0x08,0xF8,0x08,0x08,0x00,0x00,
	0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//I 41
	
	0x00,0x00,0x08,0x08,0xF8,0x08,0x08,0x00,
	0xC0,0x80,0x80,0x80,0x7F,0x00,0x00,0x00,//J 42
	
	0x08,0xF8,0x88,0xC0,0x28,0x18,0x08,0x00,
	0x20,0x3F,0x20,0x01,0x26,0x38,0x20,0x00,//K 43
	
	0x08,0xF8,0x08,0x00,0x00,0x00,0x00,0x00,
	0x20,0x3F,0x20,0x20,0x20,0x20,0x30,0x00,//L 44
	
	0x08,0xF8,0xF8,0x00,0xF8,0xF8,0x08,0x00,
	0x20,0x3F,0x00,0x3F,0x00,0x3F,0x20,0x00,//M 45
	
	0x08,0xF8,0x30,0xC0,0x00,0x08,0xF8,0x08,
	0x20,0x3F,0x20,0x00,0x07,0x18,0x3F,0x00,//N 46
	
	0xE0,0x10,0x08,0x08,0x08,0x10,0xE0,0x00,
	0x0F,0x10,0x20,0x20,0x20,0x10,0x0F,0x00,//O 47
	
	0x08,0xF8,0x08,0x08,0x08,0x08,0xF0,0x00,
	0x20,0x3F,0x21,0x01,0x01,0x01,0x00,0x00,//P 48
	
	0xE0,0x10,0x08,0x08,0x08,0x10,0xE0,0x00,
	0x0F,0x18,0x24,0x24,0x38,0x50,0x4F,0x00,//Q 49
	
	0x08,0xF8,0x88,0x88,0x88,0x88,0x70,0x00,
	0x20,0x3F,0x20,0x00,0x03,0x0C,0x30,0x20,//R 50
	
	0x00,0x70,0x88,0x08,0x08,0x08,0x38,0x00,
	0x00,0x38,0x20,0x21,0x21,0x22,0x1C,0x00,//S 51
	
	0x18,0x08,0x08,0xF8,0x08,0x08,0x18,0x00,
	0x00,0x00,0x20,0x3F,0x20,0x00,0x00,0x00,//T 52
	
	0x08,0xF8,0x08,0x00,0x00,0x08,0xF8,0x08,
	0x00,0x1F,0x20,0x20,0x20,0x20,0x1F,0x00,//U 53
	
	0x08,0x78,0x88,0x00,0x00,0xC8,0x38,0x08,
	0x00,0x00,0x07,0x38,0x0E,0x01,0x00,0x00,//V 54
	
	0xF8,0x08,0x00,0xF8,0x00,0x08,0xF8,0x00,
	0x03,0x3C,0x07,0x00,0x07,0x3C,0x03,0x00,//W 55
	
	0x08,0x18,0x68,0x80,0x80,0x68,0x18,0x08,
	0x20,0x30,0x2C,0x03,0x03,0x2C,0x30,0x20,//X 56
	
	0x08,0x38,0xC8,0x00,0xC8,0x38,0x08,0x00,
	0x00,0x00,0x20,0x3F,0x20,0x00,0x00,0x00,//Y 57
	
	0x10,0x08,0x08,0x08,0xC8,0x38,0x08,0x00,
	0x20,0x38,0x26,0x21,0x20,0x20,0x18,0x00,//Z 58
	
	0x00,0x00,0x00,0xFE,0x02,0x02,0x02,0x00,
	0x00,0x00,0x00,0x7F,0x40,0x40,0x40,0x00,//[ 59
	
	0x00,0x0C,0x30,0xC0,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x01,0x06,0x38,0xC0,0x00,//\ 60
	
	0x00,0x02,0x02,0x02,0xFE,0x00,0x00,0x00,
	0x00,0x40,0x40,0x40,0x7F,0x00,0x00,0x00,//] 61
	
	0x00,0x00,0x04,0x02,0x02,0x02,0x04,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//^ 62
	
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,//_ 63
	
	0x00,0x02,0x02,0x04,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//` 64
	
	0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,
	0x00,0x19,0x24,0x22,0x22,0x22,0x3F,0x20,//a 65
	
	0x08,0xF8,0x00,0x80,0x80,0x00,0x00,0x00,
	0x00,0x3F,0x11,0x20,0x20,0x11,0x0E,0x00,//b 66
	
	0x00,0x00,0x00,0x80,0x80,0x80,0x00,0x00,
	0x00,0x0E,0x11,0x20,0x20,0x20,0x11,0x00,//c 67
	
	0x00,0x00,0x00,0x80,0x80,0x88,0xF8,0x00,
	0x00,0x0E,0x11,0x20,0x20,0x10,0x3F,0x20,//d 68
	
	0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,
	0x00,0x1F,0x22,0x22,0x22,0x22,0x13,0x00,//e 69
	
	0x00,0x80,0x80,0xF0,0x88,0x88,0x88,0x18,
	0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//f 70
	
	0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x00,
	0x00,0x6B,0x94,0x94,0x94,0x93,0x60,0x00,//g 71
	
	0x08,0xF8,0x00,0x80,0x80,0x80,0x00,0x00,
	0x20,0x3F,0x21,0x00,0x00,0x20,0x3F,0x20,//h 72
	
	0x00,0x80,0x98,0x98,0x00,0x00,0x00,0x00,
	0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//i 73
	
	0x00,0x00,0x00,0x80,0x98,0x98,0x00,0x00,
	0x00,0xC0,0x80,0x80,0x80,0x7F,0x00,0x00,//j 74
	
	0x08,0xF8,0x00,0x00,0x80,0x80,0x80,0x00,
	0x20,0x3F,0x24,0x02,0x2D,0x30,0x20,0x00,//k 75
	
	0x00,0x08,0x08,0xF8,0x00,0x00,0x00,0x00,
	0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//l 76
	
	0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x00,
	0x20,0x3F,0x20,0x00,0x3F,0x20,0x00,0x3F,//m 77
	
	0x80,0x80,0x00,0x80,0x80,0x80,0x00,0x00,
	0x20,0x3F,0x21,0x00,0x00,0x20,0x3F,0x20,//n 78
	
	0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,
	0x00,0x1F,0x20,0x20,0x20,0x20,0x1F,0x00,//o 79
	
	0x80,0x80,0x00,0x80,0x80,0x00,0x00,0x00,
	0x80,0xFF,0xA1,0x20,0x20,0x11,0x0E,0x00,//p 80
	
	0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x00,
	0x00,0x0E,0x11,0x20,0x20,0xA0,0xFF,0x80,//q 81
	
	0x80,0x80,0x80,0x00,0x80,0x80,0x80,0x00,
	0x20,0x20,0x3F,0x21,0x20,0x00,0x01,0x00,//r 82
	
	0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x00,
	0x00,0x33,0x24,0x24,0x24,0x24,0x19,0x00,//s 83
	
	0x00,0x80,0x80,0xE0,0x80,0x80,0x00,0x00,
	0x00,0x00,0x00,0x1F,0x20,0x20,0x00,0x00,//t 84
	
	0x80,0x80,0x00,0x00,0x00,0x80,0x80,0x00,
	0x00,0x1F,0x20,0x20,0x20,0x10,0x3F,0x20,//u 85
	
	0x80,0x80,0x80,0x00,0x00,0x80,0x80,0x80,
	0x00,0x01,0x0E,0x30,0x08,0x06,0x01,0x00,//v 86
	
	0x80,0x80,0x00,0x80,0x00,0x80,0x80,0x80,
	0x0F,0x30,0x0C,0x03,0x0C,0x30,0x0F,0x00,//w 87
	
	0x00,0x80,0x80,0x00,0x80,0x80,0x80,0x00,
	0x00,0x20,0x31,0x2E,0x0E,0x31,0x20,0x00,//x 88
	
	0x80,0x80,0x80,0x00,0x00,0x80,0x80,0x80,
	0x80,0x81,0x8E,0x70,0x18,0x06,0x01,0x00,//y 89
	
	0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x00,
	0x00,0x21,0x30,0x2C,0x22,0x21,0x30,0x00,//z 90
	
	0x00,0x00,0x00,0x00,0x80,0x7C,0x02,0x02,
	0x00,0x00,0x00,0x00,0x00,0x3F,0x40,0x40,//{ 91
	
	0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,//| 92
	
	0x00,0x02,0x02,0x7C,0x80,0x00,0x00,0x00,
	0x00,0x40,0x40,0x3F,0x00,0x00,0x00,0x00,//} 93
	
	0x00,0x06,0x01,0x01,0x02,0x02,0x04,0x04,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//~ 94
};

#endif

四、总结

在第2.14时出现一些bug没有解决,但是总体来说,这篇算得上是我人生历史上第一个查找模块手册,自己配置协议,接线等等,自己去理解,一步步写出来的第一个驱动,虽然功能不多,但是也算是一个好的开始吧,接下来我还会写硬件SPI驱动OLED、软硬件结合自选驱动的OLED,软件IIC驱动的OLED,硬件IIC驱动的OLED,软硬件IIC驱动的OLED,以及OLED的滚动菜单等文章作为学习系列的补充。欢迎各位大佬对我提出纠错和建议,谢谢。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

跳河轻生的鱼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值