声明:我是跟着B站江科大的视频的学习过程中记录下来作者的文案,记录下来是为了方便自己日后复习。如果你也是跟着江科大的视频学习的,可以一起学习
本节课主要使用软件SPI的方式实现功能。
因为是软件模拟的SPI,所以DI/DO/CLK/CS这四根线可以接到任意GPIO口。
复制OLED工程。
先规划一下整体框架:
先建立一个SPI的模块,在这个模块主要包括通信引脚封装、初始化、以及SPI通信的3个拼图,包括起始、终止和交换一个字节,这是SPI通信层的内容。
然后基于SPI层,再写一个W25Q64的模块,在这个模块,使用低层SPI层的拼图,来拼接各种指令和功能的完整时序,比如写使能、擦除、页编程和读数据等等,所以这一块可以叫做W25Q64的硬件驱动层。
最后在主函数里调用驱动层的函数,来完成要实现的功能。
首先在Hardware里建立MySPI的模块,
先来初始化SPI的通信引脚。对于STM32来说,时钟输出、片选、主机输出都是输出,所以这3个引脚配置为推挽输出,主机输入是输入,可以是浮空或上拉输入,选择配置为上拉输入。所以对应接线图的PA6为上拉输入,其他配置为推挽输出就可以了。
像I2C那样,把置引脚高低电平的函数进行封装,换个名字。
首先是从机选择,这个是输出引脚,
(BitAction)BitValue是将BitValue强转为BitAction类型。
这是另外两个输出引脚。
还有一个输入引脚MISO,
这样SPI的4个通信引脚的高低电平变化函数就包装好换好名字了。因为SPI引脚速度非常快,所以就不需要加延时了。
之后还有工作要做,就是置一下引脚初始化后的默认电平。
SS默认不选中从机,置高电平;我们选择用SPI模式0,所以SCK一开始默认是低电平。
MOSI没有要求,不用管;MISO是输入引脚,没有输出电平。
接下来是SPI的时序基本单元:
首先是起始信号,直接把SS置低电平即可。
终止是将SS置高电平即可。
然后是交换字节的时序。
在SS下降沿之后,开始交换字节,
虽然图上标的是SS下降沿时,数据移出是同时的,包括后面SCK下降沿和数据移出也是同时,但这并不代表要程序上要同时执行两条代码,当然这也做不到。
其实这是有先后顺序的,先SS下降沿或SCK下降沿,再进行数据移出,这个下降沿是触发数据移出动作的条件。先有了下降沿,才会有了数据移出这个动作,他们是有因果关系的。对于硬件SPI,由于使用了SPI硬件电路,所以这两个动作几乎是同时发生的。而对于软件SPI来说,由于程序是一条条执行的,不可能同时完成两个动作。所以对于软件SPI,直接将他看成是先后执行的。
以上就是SPI模式0交换一个字节的时序了。
(0x80 >> i)的作用就是用来挑出数据的某一位或者某几位,或者换种描述方式就是用来屏蔽其他的无关位,那就可以把这种类型的数据叫做掩码。
或者下面这种方法也可以,并且效率更高。但是ByteSend这个数据在移位的过程中改变了,for循环执行完,原始传入的参数就没有了。这种方法更契合移位模型。
“BitAction”类型在定义时只包含两个枚举值:“Bit_RESET = 0” 和 “Bit_SET = 1”。因此,他的有效值只能是1或0,用来表示位的清除和设置。
如果想用SPI模式1的流程,就是用下面的交换字节的代码,只是改一下程序的相位即可;
然后将四个函数放到.h头文件声明一下。
然后在此基础之上,再写W25Q64的驱动层。
在Hardware中建立W25Q64的.c和.h文件。
作为上层的W25Q64,他的初始化要调用低层的MySPI_Init();
先读取ID号,查看SPI通信是否有问题。
接着来测试一下有么有问题。
下面是测试正常显示的数据画面。