STM32驱动0.96寸OLED液晶屏(12864液晶屏)
1 序言
在利用单片机是设计产品的过程中常常需要利用一些数据显示设备来显示一些关键信息,常用的做法是利用串口将数据传送到计算机上显示,或者是利用蓝牙模块将数据送到移动终端上显示,那么还有一种方法,就是将数据直接显示在一块小的液晶屏幕上,这种方式也是十分的方便快捷的。那么如何要在我们打单片机系统上添加一块液晶显示屏到底该怎么做呢?我相信这也是许多在网上搜OLED液晶显示屏驱动程序的小伙伴们最为关心的问题。本片文章将以STM32F103单片机为例,讲解如何在单片机系统上面加一块液晶显示屏,并且使其能够显示我们想要的数据,文字符号或者图片信息等。
2 如何利用STM32单片机驱动12864液晶屏
STM32单片机是目前市面上使用最为广泛的单片机,该单片机型号众多,每种型号适用于不同的工作要求,大致可分为F0、F1、F4、F7等系列。那么我所使用的单片机型号为STM32F103RC,其他型号的液晶屏驱动程序也是类似的,差异并不是非常大,而所使用的液晶屏幕为市面上常见的0.96寸OLED液晶屏幕(也叫12864液晶屏),都是淘宝上买的,价格也就几十块钱。如图2-1所示。
Fig. 1:0.96寸OLED液晶显示屏及STM32F103RC单片机做小系统外观图
2.1 0.96寸OLED端口含义
说道硬件的引脚连接,这个问题似乎也没多大难度,但是很多刚开始接触这一块知识的小伙伴在网上搜了好多资料之后就纳闷了,例如:网上的所提到的SCL,SDA引脚是啥啊?我这液晶屏上面怎么没有啊?或者是这个程序里面的DIN,CLK是指的那个端口啊?我这硬件上也没有啊。图2.1-1显示了市面上两种常见的OLED液晶显示屏的端口标号。
Fig. 2.1-1:两种常见的液晶显示屏端口标号
两种液晶片的引脚数不一样,左边的有7个引脚,而右边的只有6个。其次,端口的标号也不完全一样,第一个分别标为GND,VCC,D0,D1,RES,DC和CS第二个分别标为GND,VCC,SCL,SDA,RST,D/C。除了GND和VCC小伙伴们也许已经猜到了,其他的引脚是什么含义,有什么用应该也不是非常的清楚。
先讲解右边的,右边的端口标号是最为直观的:
GND --- 接地端口
VCC --- 接3.3V电源端口
SCL --- CLK时钟信号端口
SDA --- MOSI数据端口
RST --- 复位端口
D/C --- 数据/命令选择引脚
弄懂了每个引脚的含义,其实左边的标号不一样,只要知道它最本质的含义,也对我们编写程序产生不了多大影响。左边的端口号的含义分别为:
GND --- 接地端口
VCC --- 接3.3V电源端口
D0 --- CLK时钟信号(等同于上面的SCL)
D1 --- 数据端口(等同于上面的SDA)
RES --- 复位端口(等同于上面的RST)
DC --- 数据/命令选择引脚(等同于上面的D/C)
CS --- 片选引脚(低电平有效,也就是所需要接低电平,我实际试验过不接该引脚也是可以正常使用的)
其实弄清楚含义之后左边的只是比右边的多了一个CS片选引脚,而这个引脚也是无关紧要的,所以说其实本质上两者是一样的。
2.2 0.96寸OLED液晶屏引脚与单片机系统引脚的硬件连接
具体说来怎么连接,我所理解的在STM32中含有CLK时钟信号有两个一个是IIC,另一个是SPI,两种通讯方式都有时钟信号,但是这里的时钟信号端口是不是必须接IIC和SPI的CLK端口呢?经过我的测试所得到的答案是否定的,并不需要刻意将OLED液晶屏端口的CLK端口和数据端口接IIC的时钟及数据引脚或者是SPI的时钟及数据引脚。
我的连接方式为:
GND --- GND
VCC --- VCC
D0(SCL) --- PC0
D1(SDA) --- PC1
RES(RST) --- PC2
DC(D/C) --- PC3
CS --- 悬空
连接实物图如图2.2-1所示
Fig. 2.2-1:STM32与0.96寸OLED实物连接图
2.3 0.96寸OLED液晶屏驱动程序
OLED驱动程序获取链接:
个人论坛:>>>点击访问
Github: >>>点击访问
百度云盘下载:点击链接 提取码为:59dx
上述代码只是一个驱动程序中的一部分代码,需要先初始化系统时钟,其次初始化调用OLED初始化函数,程序方可正常运行。
3 实验结果
我们利用液晶屏幕可显示数据,字符以及各种图片信息。
3.1 利用液晶屏显示字符串数据信息
首先,先来介绍显示字符串数据信息,因为这种信息显示是最为方便的。我们直接调用OLED_ShowString(uint8_t x,uint8_t y,char *chr)函数即可。
参考主程序代码如下
#include "stm32f10x.h" #include "oled.h" #include "bsp_systick.h" int main(void) { char Buffer[15] = "Hello, World!"; Systick_InitConfig(); GPIO_OLED_InitConfig(); OLED_Clear(); OLED_ShowString(20, 2, Buffer); while(1); }
这个函数主要用于显示字符串数据,效果如图3.1-1所示。
Fig.3.1-2 液晶屏显示字符串数据信息
3.2 利用液晶屏显示数据信息
我们的数据一般分为两种,一种是整型数据,一种是浮点型数据。整型数据好显示,我们可以用上述代码里面的OLED_ShowNum(uint8_t x,uint8_t y,uint32_t num,uint8_t len,uint8_t size)函数。
例如:我们在主函数中写下如下代码:
#include "stm32f10x.h" #include "oled.h" #include "bsp_systick.h" int main(void) { int Num = 125; float Data = 12.50; Systick_InitConfig(); GPIO_OLED_InitConfig(); OLED_Clear(); OLED_ShowNum(20, 2, Num, 8, 16); OLED_ShowNum(20, 4, Data, 8, 16); while(1); }
观察屏幕中的数据,如下所示:
Fig. 3.2-1液晶屏显示数据信息
可以发现,整型数据被很好的显示出来,而浮点型数据则显示有误,12.5只保留了整数部分。怎么解决这个问题?
我们可以用sprintf()函数将浮点数据转化为字符串数据进行显示,代码如下所示:
#include "stm32f10x.h" #include "oled.h" #include "bsp_systick.h" int main(void) { float Data = 12.50; char Buffer[5]; sprintf(Buffer, "%0.2f", Data); Systick_InitConfig(); GPIO_OLED_InitConfig(); OLED_Clear(); OLED_ShowString(20, 2, Buffer); while(1); }
这样就很好地解决了浮点型数据的显示问题,我个人觉得这个方法非常的重要,也非常的实用,毕竟我们生活中传感器采集到的数据大多数都是浮点型数据。
效果如图3.2-2所示。
Fig. 3.2-2 浮点型数据转化为字符串数据显示
大家在做传感器数据显示的时候也可以尝试用这种方法,非常的方便。
3.3 利用液晶屏显示中文信息
显示中文信息需要用到字模工具,下载可到本人搭建的论坛下载: --> PCtoLCD论坛下载 //目前无法通过此途径获取,请用下面的链接获取方式
也可以从百度云盘下载: --> PCtoLCD百度网盘下载 提取码为:lyhc
字模软件的配置与使用方式如图
Fig. 3.3-1 字模软件PCtoLCD2002配置与使用方法
将生成的代码复制到字模文件oledfont.h中,我们在oledfont.h文件中新建一个函数,将该代码复制到该文件中。
char SHOW[][32]={ {0x20,0x24,0x24,0x24,0xFE,0x23,0x22,0x20,0x20,0xFF,0x20,0x22,0x2C,0xA0,0x20,0x00}, {0x00,0x08,0x48,0x84,0x7F,0x02,0x41,0x40,0x20,0x13,0x0C,0x14,0x22,0x41,0xF8,0x00},/*"我",0*/ {0x80,0x64,0x2C,0x34,0x24,0x24,0xEC,0x32,0x22,0x22,0x32,0x2E,0x23,0xA2,0x60,0x00}, {0x00,0x41,0x21,0x91,0x89,0x87,0x4D,0x55,0x25,0x25,0x55,0x4D,0x81,0x80,0x80,0x00},/*"爱",1*/ {0x00,0x80,0x60,0xF8,0x07,0x40,0x20,0x18,0x0F,0x08,0xC8,0x08,0x08,0x28,0x18,0x00}, {0x01,0x00,0x00,0xFF,0x00,0x10,0x0C,0x03,0x40,0x80,0x7F,0x00,0x01,0x06,0x18,0x00},/*"你",2*/ {0x00,0x00,0xF0,0x10,0x10,0x10,0x10,0xFF,0x10,0x10,0x10,0x10,0xF0,0x00,0x00,0x00}, {0x00,0x00,0x0F,0x04,0x04,0x04,0x04,0xFF,0x04,0x04,0x04,0x04,0x0F,0x00,0x00,0x00},/*"中",3*/ {0x00,0xFE,0x02,0x12,0x92,0x92,0x92,0xF2,0x92,0x92,0x92,0x12,0x02,0xFE,0x00,0x00}, {0x00,0xFF,0x40,0x48,0x48,0x48,0x48,0x4F,0x48,0x4A,0x4C,0x48,0x40,0xFF,0x00,0x00},/*"国",4*/ {0x00,0x00,0xFF,0x05,0x05,0xF5,0x55,0x5D,0x55,0x55,0x55,0x55,0xF5,0x05,0x01,0x00}, {0x40,0x30,0x0F,0x80,0xA0,0x97,0xBD,0x55,0x55,0x55,0x55,0x55,0xB7,0x80,0x80,0x00},/*"厦",5*/ {0x20,0x20,0x20,0x20,0x20,0x20,0x20,0xFF,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x00}, {0x80,0x80,0x40,0x20,0x10,0x0C,0x03,0x00,0x03,0x0C,0x10,0x20,0x40,0x80,0x80,0x00},/*"大",6*/ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, {0x00,0x00,0x58,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*",",7*/ };
接下来,我们需要在主程序里通过调用OLED_ShowCHinese(uint8_t x,uint8_t y,uint8_t no)函数来实现中文字符的显示。
#include "stm32f10x.h" #include "oled.h" #include "bsp_systick.h" int main(void) { Systick_InitConfig(); GPIO_OLED_InitConfig(); OLED_Clear();
/* (x, y, 汉字序号) */ OLED_ShowCHinese(10, 2, 0); OLED_ShowCHinese(24, 2, 1); OLED_ShowCHinese(38, 2, 2); OLED_ShowCHinese(52, 2, 7); OLED_ShowCHinese(66, 2, 3); OLED_ShowCHinese(80, 2, 4); OLED_ShowCHinese(10, 5, 0); OLED_ShowCHinese(24, 5, 1); OLED_ShowCHinese(38, 5, 2); OLED_ShowCHinese(52, 5, 7); OLED_ShowCHinese(66, 5, 5); OLED_ShowCHinese(80, 5, 6); while(1); }
显示结果如下图所示
Fig. 3.3-2 OLED液晶显示中文字符
3.4 利用液晶屏幕显示图片信息
图片信息的显示其实并不麻烦,而获取图片代码的过程稍稍有些许麻烦。
先以图3.4-1为例,将其利用PCtoLCD的图像转换功能转换为代码。
Fig. 3.4-1:PCtoLCD图像转换实例文件
在输入到软件之前需要通过图像处理软件调整图像分辨率并做二值化处理(就是将图像变成黑白色,分辨率调整为128x64)
过程我就省略了,对此有需求或者有兴趣的小伙伴请在评论区留言。
转换的代码放在bmp.h文件内,如下所示
#ifndef __BMP_H #define __BMP_H unsigned char BMP[] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xC0,0xE0,0xE0,0xF0,0xF8, 0xF8,0xBC,0x1C,0x1C,0x0E,0x0E,0xFF,0xFF,0xFF,0xBF,0xBF,0xE7,0x63,0x63,0x43,0x43, 0x63,0x63,0xFF,0x9F,0x9F,0xFF,0x3F,0x3F,0x0E,0x0E,0x1C,0x1C,0xBC,0xF8,0xF8,0xF0, 0xE0,0xE0,0xC0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0xF0,0xFE,0xFE,0xFF,0xE7,0xF3,0xF3,0xE7,0xCF,0xCF,0xF7, 0x8D,0x8C,0x86,0x87,0xFD,0xFD,0xFE,0xFF,0xFF,0xFE,0xFA,0xFA,0xFA,0xFA,0xFA,0xFA, 0xFE,0xFF,0xFF,0xFE,0xFD,0xFD,0x87,0x87,0x8F,0x8F,0xFF,0xC7,0xC7,0xE3,0xF1,0xF1, 0xE7,0xFF,0xFE,0xFE,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x1F,0xFF,0xFF,0xFE,0xFC,0xFD,0xFD,0xFD,0xF7,0xF7,0x9E,0x6F,0xFF, 0xFB,0x7F,0xFC,0xF4,0xFF,0xEE,0xE6,0xE7,0xEF,0xFF,0xFF,0xFF,0xFF,0xEF,0xE7,0xE6, 0xEE,0xFF,0xF4,0xFC,0x7F,0xFB,0xFF,0x6F,0x9E,0xE7,0xE7,0xFD,0xFD,0xFD,0xFC,0xFE, 0xFF,0xFF,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x01,0x07,0x07,0x0F,0x1F,0x1F,0x3B,0x7F,0xFF,0x7F,0xFE,0xFE,0xFD, 0xFF,0xFF,0x9B,0xFF,0xFC,0xFC,0xFC,0xE4,0xF4,0xF4,0x84,0x8C,0xFC,0xFC,0xFF,0xFB, 0xFF,0xFF,0xFD,0xFE,0xFE,0x7F,0xFF,0x7F,0x3F,0x1F,0x1F,0x0F,0x07,0x07,0x01,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x03, 0x03,0x03,0x03,0x03,0x03,0x07,0x07,0x07,0x07,0x03,0x03,0x03,0x03,0x03,0x03,0x01, 0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xD8, 0xF8,0xFC,0xBC,0xBC,0xBC,0xBC,0xFC,0xDC,0xDE,0xDE,0xFE,0xFE,0xFE,0x7E,0x7E,0x6E, 0x4C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0xE0,0xE0,0xE0,0xC0,0xC0, 0x40,0x60,0xE0,0xE0,0xE0,0xC0,0xC0,0xC0,0xC0,0xE0,0x20,0x20,0xF0,0xF0,0xF0,0xF0, 0xE0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x18,0xFC,0xFC,0xF8,0xF8,0xF8,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8, 0xFC,0xFE,0xFE,0xB6,0xE0,0xE0,0xFC,0xDC,0xFF,0xFF,0xBE,0xDE,0xD4,0xF6,0xFE,0xFE, 0x7E,0x0C,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xF8,0xFC,0xFF,0xFF,0x1F, 0x1F,0x83,0xFD,0xFD,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0x7E,0x36,0x36,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0x37,0x1F, 0x1F,0x1F,0x3F,0x00,0x00,0x07,0x1F,0x1F,0x1B,0x1B,0x1F,0x1F,0xFF,0xFF,0xFF,0xFF, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x1C,0x1C,0xBC,0xFC,0xFC,0xFC, 0xFE,0xFF,0xFF,0x7F,0xFF,0xFF,0xFF,0xEF,0xE7,0xC7,0x87,0x0F,0x0F,0x06,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x3C,0x3C,0x38,0x1C,0x0E,0x0F,0x0F,0x1F, 0x1F,0xBF,0xBF,0xBF,0xFF,0xFF,0xFF,0xDF,0x97,0xC6,0xC6,0xC7,0xCF,0xCF,0x9E,0x1E, 0x1E,0x1E,0xC0,0xF0,0xF0,0xFC,0x7F,0x7F,0x3F,0x0F,0x0F,0x03,0x00,0x10,0x10,0x4D, 0x6F,0x6F,0x37,0x3F,0x3F,0x1D,0x3D,0x3F,0x3F,0x7F,0xF2,0xF2,0xF0,0xE0,0xE0,0xE0, 0x60,0x60,0x40,0x00,0x00,0x00,0x00,0x0F,0x0F,0x1F,0x0F,0x07,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x04,0x04,0x0C,0x1C,0x1C,0x1C,0x3F,0x3F,0x3F,0x1F,0x00,0x00, 0x00,0x00,0x00,0x00,0x18,0x1C,0x1C,0x0E,0x0E,0x0E,0x07,0x07,0x03,0x03,0x01,0x00, 0x00,0x00,0x00,0x00,0x01,0x03,0x03,0x07,0x0F,0x1F,0x1F,0x3E,0x3E,0x3E,0x1C,0x18, 0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x03,0x03,0x03,0x33,0x33,0x73, 0x71,0x71,0xF9,0x7F,0x7F,0x3F,0x03,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00, }; #endif
在主程序中需要调用OLED_DrawBMP();函数,主函数代码如下
#include "stm32f10x.h" #include "oled.h" #include "bsp_systick.h" #include "bmp.h" int main(void) { Systick_InitConfig(); GPIO_OLED_InitConfig(); OLED_Clear(); OLED_DrawBMP(0,0,126,8,BMP); while(1); }
显示结果如图3.4-2所示
Fig. 3.4-1: 液晶屏图片显示实验
至此,几个关于0.96寸OLED的STM32驱动显示实验就基本展示完毕了。
4 总结
1、OLED的液晶显示屏幕使我们做项目中起到一个数据显示的作用,可以显示数据,字符(各种阿拉伯字符,英文字符,汉字字符等等),图片等。
2、在显示浮点型数据时采用sprintf();函数将浮点型数据转化为字符型数据能很好的解决浮点数数据的显示问题,如果小伙伴们有更好的办法,如能在评论区添加我联系方式告知的话,万分感激。
3、市面上的0.96寸OLED液晶屏的引脚标号千奇百怪,但是它核心的引脚实际上就只有四个,分别是的数据、时钟、复位以及数据命令选择引脚。
4、液晶屏的数据和时钟引脚无需刻意连接单片机的IIC或者SPI的数据时钟引脚。
5、完整工程代码请到下载方式:>>>点击获取
百度云获取方式:点击链接 提取码为:hmy6
2019.2.20 于厦门