基于stm32的OLED显示屏显示

文章目录

  • 一、内容
  • 二、关于SPI
  • 三、关于OLED
  • 四、功能实现
    • 1)实验准备
    • 2)代码准备
      • 1、显示学号和姓名
      • 2、显示AHT20的温度和湿度
      • 3、滑动显示长字符
    • 3)结果展示
  • 五、参考内容
  • 六、总结

一、内容

理解OLED屏显和汉字点阵编码原理,使用STM32F103的SPI或IIC接口实现以下功能:

1.显示自己的学号和姓名;

2.显示AHT20的温度和湿度;

3.上下或左右的滑动显示长字符,比如“Hello,欢迎来到重庆!”或者一段歌词或诗词(最好使用硬件刷屏模式)。

关于汉字点阵编码的原理可以参考上一篇博客!

二、关于SPI

SPI,是英语Serial Peripheral interface的缩写,顾名思义就是串行外围设备接口。是Motorola首先在其MC68HCXX系列处理器上定义的。
SPI接口主要应用在 EEPROM,FLASH,实时时钟,AD转换器,还有数字信号处理器和数字信号解码器之间
SPI,是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚,同时为PCB的布局上节省空间,提供方便,正是出于这种简单易用的特性,现在越来越多的芯片集成了这种通信协议,比如AT91RM9200。

AT91RM9200的SPI接口主要由4个引脚构成:SPICLK、MOSI、MISO及 /SS,其中SPICLK是整个SPI总线的公用时钟,MOSI、MISO作为主机,从机的输入输出的标志,MOSI是主机的输出,从机的输入,MISO 是主机的输入,从机的输出。/SS是从机的标志管脚,在互相通信的两个SPI总线的器件,/SS管脚的电平低的是从机,相反/SS管脚的电平高的是主机。在一个SPI通信系统中,必须有主机。SPI总线可以配置成单主单从,单主多从,互为主从。

SPI的片选可以扩充选择16个外设,这时PCS输出=NPCS,说NPCS0~3 接4-16译码器,这个译码器是需要外接4-16译码器,译码器的输入为NPCS0~3,输出用于16个外设的选择。

SPI的通信原理很简单,它以主从方式工作,这种模式通常有一个主设备和一个或多个从设备,需要至少4根线,事实上3根也可以(单向传输时)。也是所有基于SPI的设备共有的,它们是SDI(数据输入),SDO(数据输出),SCK(时钟),CS(片选)

 - SDO – 主设备数据输出,从设备数据输入对应MOSI master output slave input 
 - SDI – 主设备数据输入,从设备数据输出对应MISO master input slave output 
 - SCLK   – 时钟信号,由主设备产生 
 - CS        – 从设备使能信号,由主设备控制

注意:SCK信号线只由主设备控制,从设备不能控制信号线。同样,在一个基于SPI的设备中,至少有一个主控设备。
这样传输的优点

  1. 与普通的串行通讯不同,普通的串行通讯一次连续传送至少8位数据,而SPI允许数据一位一位的传送,甚至允许暂停,因为SCK时钟线由主控设备控制,当没有时钟跳变时,从设备不采集或传送数据,也就是说,主设备通过对SCK时钟线的控制可以完成对通讯的控制
  2. SPI还是一个数据交换协议:因为SPI的数据输入和输出线独立,所以允许同时完成数据的输入和输出。不同的SPI设备的实现方式不尽相同,主要是数据改变和采集的时间不同,在时钟信号上沿或下沿采集有不同定义,具体请参考相关器件的文档。
  3. 在点对点的通信中,SPI接口不需要进行寻址操作,且为全双工通信,显得简单高效。在多个从设备的系统中,每个从设备需要独立的使能信号,硬件上比I2C系统要稍微复杂一些。

缺点:
没有指定的流控制,没有应答机制确认是否接收到数据。

三、关于OLED

通常我们所用的OLED屏有白色、蓝色、黄蓝双色等几种;屏的大小为0.96寸,像素点为128*64,所以我们也称之为0.96OLED屏或者12864屏。

内部驱动IC为SSD1306;通信方式一般为SPI或者I2C

配置哪种模式主要是根据BS0、BS1和BS2这三个管脚的电平逻辑来的。
关于OLED的显存分布情况
我们可以理解为:水平方向分布了128个像素点,垂直方向分布了64个像素点(如图一所示)。而驱动芯片在点亮像素点的时候,是以8个像素点为单位的。官方的例程推荐的是垂直扫描的方式,也就是先画垂直方向的8个像素点(如下图二所示),所以我们在画点的时候Y的取值为0-7,X的取值为0-127,具体请看参考内容。

四、功能实现

1)实验准备

软件:Keil uVision5、烧录软件、串口调试助手
硬件:PC机、STM32芯片、OLED显示屏、若干杜邦线、USB TO TTL串口

2)代码准备

1、显示学号和姓名

Ⅰ、字模提取
首先,先进行字模提取,在提取之前,需要进行一些选项设置,具体如下图:
基于stm32的OLED显示屏显示_第1张图片
然后在下方输入框中输入想要显示的内容,点击生成字模即可看到对用的字模编码,然后点击保存字模即可:
在这里插入图片描述
Ⅱ、代码完善

①下载路径:打开该博客,博主分享有完整代码;
②下载上述文件后,打开资料包,打开keil工程,如下图所示:
基于stm32的OLED显示屏显示_第2张图片
首先,将刚刚生成的字模编码添加到如下文件当中去,如下图所示:
基于stm32的OLED显示屏显示_第3张图片
然后打开test.c将以下函数的一部分修改为我们需要显示的内容:
基于stm32的OLED显示屏显示_第4张图片
函数说明

GUI_ShowString() 的参数

参数一:X 坐标参数二:Y 坐标参数三:字符串(ASCLL码中的)参数四:bit(表示字符显示格式,这里我用的 16,和汉字一样高)参数五:显示样式(1:白字黑底;0:黑字白底)
GUI_ShowChinese() 的参数

参数一:X 坐标参数二:Y 坐标参数三:汉字点阵大小(这里使用的是 16×16 的,参数应该是16)参数四:要显示的汉字参数五:显示样式(1:白字黑底;0:黑字白底)

Ⅲ、主要代码展示

主函数mian.c:

int main(void)
{	
	delay_init();	    	       //延时函数初始化	  
	NVIC_Configuration(); 	   //设置NVIC中断分组2:2位抢占优先级,2位响应优先级 	
	OLED_Init();			         //初始化OLED  
	OLED_Clear(0);             //清屏(全黑)
	while(1) 
	{	
		TEST_MainPage();         //主界面显示测试
	}
}

OLED相关函数:

//OLED控制用函数
void OLED_WR_Byte(unsigned dat,unsigned cmd);     							   		    
void OLED_Display_On(void);
void OLED_Display_Off(void);
void OLED_Set_Pos(unsigned char x, unsigned char y);
void OLED_Reset(void);
void OLED_Init_GPIO(void);	   							   		    
void OLED_Init(void);
void OLED_Set_Pixel(unsigned char x, unsigned char y,unsigned char color);
void OLED_Display(void);
void OLED_Clear(unsigned dat);  
#endif

2、显示AHT20的温度和湿度

Ⅰ、工程路径
打开博客,文章底部有博主分享的完整代码;将文件下载下来,并打开其中的Keil工程,如下图所示:
基于stm32的OLED显示屏显示_第5张图片
Ⅱ、主要代码
温湿度采集函数代码:
基于stm32的OLED显示屏显示_第6张图片
主函数main.c

#include "delay.h"
#include "usart.h"
#include "bsp_i2c.h"
#include "sys.h"

#include "oled.h"
#include "gui.h"
#include "test.h"

int main(void)
{	
	delay_init();	    	       //延时函数初始化    	  
	uart_init(115200);	 
	IIC_Init();
		  
	NVIC_Configuration(); 	   //设置NVIC中断分组2:2位抢占优先级,2位响应优先级 	
	OLED_Init();			         //初始化OLED  
	OLED_Clear(0); 
	while(1)
	{
		//printf("温度湿度显示");
		read_AHT20_once();
		OLED_Clear(0); 
		delay_ms(1500);
  }
}

3、滑动显示长字符

Ⅰ、字模提取
这里我显示的是热爱可抵岁月漫长,在字模编码生成器当中如第一部分所示生成对应的字模编码并添加:
基于stm32的OLED显示屏显示_第7张图片

    "热",0x10,0x40,0x10,0x40,0x10,0x40,0xFD,0xF8,0x10,0x48,0x10,0x48,0x1C,0xC8,0x30,0x48,
	0xD0,0xAA,0x10,0xAA,0x51,0x06,0x22,0x02,0x00,0x00,0x48,0x88,0x44,0x44,0x84,0x44,
    "爱",0x00,0x08,0x01,0xFC,0x7E,0x10,0x22,0x10,0x11,0x20,0x7F,0xFE,0x42,0x02,0x82,0x04,
	0x7F,0xF8,0x04,0x00,0x07,0xF0,0x0A,0x10,0x11,0x20,0x20,0xC0,0x43,0x30,0x1C,0x0E,
	"可",0x00,0x00,0x7F,0xFE,0x00,0x10,0x00,0x10,0x1F,0x10,0x11,0x10,0x11,0x10,0x11,0x10,
  0x11,0x10,0x11,0x10,0x1F,0x10,0x11,0x10,0x00,0x10,0x00,0x10,0x00,0x50,0x00,0x20,	
	"抵",0x10,0x08,0x10,0x3C,0x13,0xE0,0x12,0x20,0xFE,0x20,0x12,0x20,0x12,0x20,0x13,0xFE,
	0x1A,0x20,0x32,0x10,0xD2,0x10,0x12,0x12,0x12,0x0A,0x12,0x8A,0x53,0x26,0x22,0x12,
	"岁",0x01,0x00,0x21,0x08,0x21,0x08,0x21,0x08,0x3F,0xF8,0x02,0x00,0x02,0x00,0x07,0xF0,
	0x08,0x10,0x14,0x10,0x22,0x20,0x01,0x40,0x00,0x80,0x03,0x00,0x1C,0x00,0xE0,0x00,
	"月",0x00,0x00,0x1F,0xF8,0x10,0x08,0x10,0x08,0x10,0x08,0x1F,0xF8,0x10,0x08,0x10,0x08,
	0x10,0x08,0x1F,0xF8,0x10,0x08,0x10,0x08,0x20,0x08,0x20,0x08,0x40,0x28,0x80,0x10,
	"漫",0x03,0xF8,0x22,0x08,0x13,0xF8,0x12,0x08,0x83,0xF8,0x40,0x00,0x47,0xFC,0x14,0xA4,
	0x14,0xA4,0x27,0xFC,0xE0,0x00,0x23,0xF8,0x21,0x10,0x20,0xE0,0x23,0x18,0x0C,0x06,
	"长",0x08,0x00,0x08,0x10,0x08,0x20,0x08,0x40,0x08,0x80,0x09,0x00,0x08,0x00,0xFF,0xFE,
	0x0A,0x00,0x09,0x00,0x08,0x80,0x08,0x40,0x09,0x20,0x0A,0x18,0x0C,0x06,0x08,0x00,

保存该编码文件后,将对应文字编码添加到工程文件oledfont.h当中去。

Ⅱ、代码完善
首先,打开第一个板块:显示学号和姓名中的工程;
然后将如下代码添加到oled.c文件当中去:
代码如下:

void OLED_Display_scroll(void)
{
    OLED_WR_Byte(0x2e,OLED_CMD);//关滚动
    OLED_WR_Byte(0x2a,OLED_CMD);//29向右,2a向左(垂直水平滚动)
    OLED_WR_Byte(0x00,OLED_CMD);//A:空字节
    OLED_WR_Byte(0x00,OLED_CMD);//B:水平起始页
    OLED_WR_Byte(0x00,OLED_CMD);//C:水平滚动速度
    OLED_WR_Byte(0x07,OLED_CMD);//D:水平结束页
    OLED_WR_Byte(0x01,OLED_CMD);//E:每次垂直滚动位移
	OLED_WR_Byte(0x2f,OLED_CMD);//开滚动
}

再将该函数添加到oled.h文件当中去,如下:
基于stm32的OLED显示屏显示_第8张图片
其次,将led.c文件当中文字部分改成我们想要显示的内容:

void TEST_MainPage(void)
{	
	GUI_ShowCHinese(0,20,16,"热爱可抵岁月漫长",1);
	//GUI_ShowString(40,32,"64X128",16,1);
	//GUI_ShowString(4,48,"www.lcdwiki.com",16,1);
	delay_ms(1500);		
	delay_ms(1500);
}

三、主要代码
主函数main.c:

int main(void)
{	
	delay_init();	    	       //延时函数初始化	  
	NVIC_Configuration(); 	   //设置NVIC中断分组2:2位抢占优先级,2位响应优先级 	
	OLED_Init();			         //初始化OLED  
	OLED_Clear(0);             //清屏(全黑)
	
	OLED_Display_scroll();  //滚动屏幕
    delay_ms(1000);
    delay_ms(1000);
    delay_ms(1000);
    delay_ms(1000);
    delay_ms(1000);
    delay_ms(1000);
    delay_ms(1000);
	
	while(1) 
	{	
		TEST_MainPage();         //主界面显示测试
	}
}

3)结果展示

Ⅰ、电路连接
stm32芯片与USB TO TTL串口的连接方式可以参考我之前的博客

OLED和STM32芯片的连接方式,可以看工程打开时的函数开头所示,具体如下:
基于stm32的OLED显示屏显示_第9张图片
实物图为:
基于stm32的OLED显示屏显示_第10张图片
Ⅱ、代码烧录
打开烧录软件,将以上三个部分生成的HEX文件分别烧录到芯片当中去,烧录成功如下图所示:
基于stm32的OLED显示屏显示_第11张图片
Ⅲ、结果展示
烧录成功后,即可看到电子屏幕上的内容;
①显示学号和姓名(这里用的是同类型的内容代替
基于stm32的OLED显示屏显示_第12张图片
②显示温湿度

③滚动显示长字符

五、参考内容

SPI协议详解
关于0.96OLED的显示过程详解(I2C通信方式)
基于STM32的温湿度采集——OLED显示

六、总结

此次实验实现了字符在OLED显示屏上显示,虽然中途遇到了很多问题,但最终通过查询资料和询问同学都得到了解决,详细内容请看参考博客。

另外,我之前遇到在Keil中无法输入中文的问题,如有相同问题请见解决方法

你可能感兴趣的:(stm32,单片机,arm)