【STM32学习笔记】4、SPIO&OLED

发布于 2021-01-30  151 次阅读


这次的任务是驱动手上的ssd1306OLED显示器显示内容。

要使得显示器显示数据,我们首先要给它数据和命令,告诉他要干什么,是去刷新显存还是清屏还是显示文字,是显示字母还是显示数字等等。那么要实现这个功能,我们就得了解SPIO总线,从底层去理解这样一个模块是如何运行的。

如何给OLED模块发送指令?首先我们需要看懂下面这张图:

让人摸不着头脑的官方文档

好,我们只需要看懂上面的这个Table 8-4就行,这是什么意思呢?啊,但凡有个高中文化水平都能知道,第一行是代表了写入命令时需要做的动作,第二行是写入数据时要执行的操作。

再仔细来看,前两项都是一样的,我们着重看后面,首先要执行写入操作,都要把片选电压拉低;接着D / C#位确定下一个数据字节充当命令或数据,如果给D/C一个低电平, 设置为逻辑“0”,则将以下数据字节定义为命令。 如果给D/C一个高电平, 设置为逻辑“1”,则它将以下数据字节定义为数据。每次数据写入后,RAM中地址指针将自动增加1。 最后再结束的时候再拉高D0。

整个流程如下图:

可以看到,在每一个D0的上升沿输入数据or指令。

好,在大概了解了数据的传递方式以后我们来康康官方给出的库函数。

在有了上面这些函数后,我们开始编写程序。

要实现目标有两个,一个是开机的画面,第二个是显示按下的矩阵键盘的键位。

第一个开机画面,我想的是要放一个诺基亚的开机画面上去,然后发现给定的库函数中并没有显示GIF的功能,只有一个显示图片的功能,于是就想到去给GIF抽帧,然后连续播放去实现一个动画的效果。先对原始的开机动画进行了抽帧处理,得到了下面的这个GIF:

自带BGM的动图

只有十一帧。然后用小软件去转换每一帧,得到的BMP文件再用取模软件取模,并存入bmp.h中分别命名为bmp1、bmp2.....,然后开始编写程序,为了方便调用,我在oled.h中定义了一个OLED_ShowGif( )函数用来精简代码(PS:其实后面想起来才发现可以用二维数组去存放然后直接一条命令就可以播放所有的图片了

//BMP:对应存放在bmp.h中的图片编号
 //time: 图片的播放间隔
 void OLED_ShowGif(u8 BMP[],int time)
 {
     OLED_ShowPicture(0,0,128,64,BMP,0);
     delay_ms(time);
     OLED_Refresh();
 } 

最后在主程序中依次显示每一个关键帧即可实现播放动图:

OLED_ShowGif(BMP1,200);
OLED_ShowGif(BMP2,200);
OLED_ShowGif(BMP3,200);
OLED_ShowGif(BMP4,200);
OLED_ShowGif(BMP5,200);
OLED_ShowGif(BMP6,200);
OLED_ShowGif(BMP7,200);
OLED_ShowGif(BMP8,200);
OLED_ShowGif(BMP9,200);
OLED_ShowGif(BMP10,200);
OLED_ShowGif(BMP11,200);

然后再调用之前写好的矩阵键盘的函数,即可实现要求的功能,源代码如下:

#include "stm32f10x.h"
#include "delay.h"
#include "led.h"
#include "key16.h"
#include "stdio.h"
#include "usart.h"
#include "oled.h"
#include "bmp.h"

int main(void)
{
	u8 num;
	delay_init();
	key_init();//初始化按钮
	
	OLED_Init();
	OLED_ColorTurn(0); //0 正常显示  ;1 反色显示
	OLED_DisplayTurn(0);//0 正常显示 1 屏幕反转显示
	OLED_Clear();//清屏


	delay_ms(1000);
	OLED_ShowGif(BMP1,200);
	OLED_ShowGif(BMP2,200);
	OLED_ShowGif(BMP3,200);
	OLED_ShowGif(BMP4,200);
	OLED_ShowGif(BMP5,200);
	OLED_ShowGif(BMP6,200);
	OLED_ShowGif(BMP7,200);
	OLED_ShowGif(BMP8,200);
	OLED_ShowGif(BMP9,200);
	OLED_ShowGif(BMP10,200);
	OLED_ShowGif(BMP11,200);
	
	delay_ms(1000);
	delay_ms(1000);
	OLED_Clear();
	while(1){
		num=KEY_SCAN();
		OLED_Refresh();
		OLED_ShowString(0,0,"KeyNum=",16,1);
		if(num){
				OLED_ShowNum(56,0,num,2,16,1);
		}
	}
}

当我们写好程序之后,编译的时候发现,报错了,报错信息如下:.\OBJ\Template.axf: Error: L6200E: Symbol BMP11 multiply defined (by oled.o and main.o)

多重定义,怎么回事呢?通过仔细查看我们的模板文件发现,在OLED.c和main.c中都引用了头文件bmp.h我们注释掉oled.c中的引用即可正常编译下载了。最后的效果如下: