目录
引言
这篇是我在江协科技学习了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的滚动菜单等文章作为学习系列的补充。欢迎各位大佬对我提出纠错和建议,谢谢。