文章目录

  • 1、SPI协议
    • 1、硬件连接
    • 2、通讯时序
    • 3、不同的通信模式
  • 2、W25Q64介绍
  • 3、SPI读写驱动编写
  • 4、源码

1、SPI协议

SPI 协议是由摩托罗拉公司提出的通讯协议(Serial Peripheral Interface),即串行外围设备接口,是一种高速全双工的通信总线。它被广泛地使用在 ADC、 LCD 等设备与 MCU 间,==要求通讯速率较高的场合。==这里就可以对比下iic,iic的速率较低,一般是低速设备之间通讯。

1、硬件连接

常见的SPI硬件连接图如下所示:

相关引脚说明如下:

  • SS(Slave Select): 从设备选择信号线,常称为片选信号线,也称为 NSS、 CS,以下用 NSS 表示。 当有多个 SPI 从设备与 SPI 主机相连时,设备的其它信号线 SCK、MOSI 及 MISO 同时并联到相同的 SPI 总线上,即无论有多少个从设备,都共同只使用这 3 条总线;而每个从设备都有独立的这一条 NSS 信号线,本信号线独占主机的一个引脚,即有多少个从设备,就有多少条片选信号线。 I2C 协议中通过设备地址来寻址、选中总线上的某个设备并与其进行通讯;而 SPI 协议中没有设备地址,它使用 NSS 信号线来寻址,当主机要选择从设备时,把该从设备的 NSS 信号线设置为低电平,该从设备即被选中,即片选有效,接着主机开始与被选中的从设备进行 SPI 通讯。所以SPI 通讯以 NSS 线置低电平为开始信号,以 NSS 线被拉高作为结束信号。(这里可以对比下和IIC的区别,iic需要我们手动写开始和停止信号)
  • SCK (Serial Clock): 时钟信号线,用于通讯数据同步。它由通讯主机产生,决定了通讯的速率,不同的设备支持的最高时钟频率不一样,如 STM32 的 SPI 时钟频率最大为fpclk/2,两个设备之间通讯时,通讯速率受限于低速设备。
  • MOSI (Master Output, Slave Input): 主设备输出/从设备输入引脚。主机的数据从这条信号线输出,从机由这条信号线读入主机发送的数据,即这条线上数据的方向为主机到从机。
  • MISO(Master Input,, Slave Output): 主设备输入/从设备输出引脚。主机从这条信号线读入数据,从机的数据由这条信号线输出到主机,即在这条线上数据的方向为从机到主机。

2、通讯时序

常见的SPI通信时序如下所示:


下面我们对这个协议里面的过程做逐一介绍:

  • 1处, NSS 信号线由高变低,是 SPI 通讯的起始信号。 NSS 是每个从机各自独占的信号线,当从机在自己的 NSS 线检测到起始信号后,就知道自己被主机选中了,开始准备与主机通讯。
  • 6处, NSS 信号由低变高,是 SPI 通讯的停止信号,表示本次通讯结束,从机的选中状态被取消。
  • 下面是数据线和时钟还是片选信号的设置,其实从图中也能看出了,SPI 使用 MOSI 及 MISO 信号线来传输数据,使用 SCK 信号线进行数据同步。 MOSI及 MISO 数据线在 SCK 的每个时钟周期传输一位数据,且数据输入输出是同时进行的。数据传输时, MSB 先行或 LSB 先行并没有作硬性规定,但要保证两个 SPI 通讯设备之间使用同样的协定,就是要么都用MSB先行,要么就都是LSB先行。

下面图中是我捕获了逻辑分析仪数据得出的MSB先行还是LSB先行的区别所在:

下面为MSB先行:

  • 图中的2、3、4、5标号处,MOSI 及 MISO 的数据在 SCK 的上升沿期间变化输出,在 SCK 的下降沿时被采样。即在 SCK 的下降沿时刻, MOSI 及 MISO 的数据有效,高电平时表示数据“1”,为低电平时表示数据“0”。在其它时刻,数据无效,MOSI 及 MISO为下一次表示数据做准备。

下面图中我也用逻辑分析仪捕获到的数据对这一现象作说明,首先是开始和结束的信号,可以看到时钟信号拉低后,设备就被使能了,就可以进行通信了!

下面我们来重点关注下我们的这个数据位,可以看到每次始终线变化八次进行数据改变,就对应我们一个字节的数据,在上升沿的时候数据开始变化,下降沿的时候读取数据,就是我们在通信过程中收发的数据了!

当然,SPI 每次数据传输可以 8 位或 16 位为单位,每次传输的单位数不受限制,这个是需要我们自己去设置的,这里我们只是用最常规的方法举个例子!

3、不同的通信模式

当然上面介绍的其实只是一种通信方式,SPI 一共有四种通讯模式,它们的主要区别是总线空闲时 SCK 的时钟状态以及数据采样时刻。为方便说明,在此引入时钟极性 CPOL”和“时钟相位 CPHA的概念。

  • 这个在我们CUBEMX的配置页面中很直观的展现出来了,如下所示:

  • 时钟极性 CPOL 是指 SPI 通讯设备处于空闲状态时, SCK 信号线的电平信号(即 SPI 通讯开始前、NSS 线为高电平时 SCK 的状态)。 CPOL=0 时, SCK 在空闲状态时为低电平,CPOL=1 时,则相反。

  • 时钟相位 CPHA 是指数据的采样的时刻,当 CPHA=0 时, MOSI 或 MISO 数据线上的信号将会在 SCK 时钟线的“奇数边沿” 被采样。当 CPHA=1 时,数据线在 SCK 的“偶数边沿” 采样。

CPHA=0的时候因为时钟极性变化不同数据传输的不同


无论 CPOL=0 还是=1,因为我们配置的时钟相位 CPHA=0,在图中可以看到, 采样时刻都是在 SCK 的奇数边沿。注意当 CPOL=0 的时候,时钟的奇数边沿是上升沿,而CPOL=1 的时候,时钟的奇数边沿是下降沿。所以 SPI 的采样时刻不是由上升/下降沿决定的。 MOSI 和 MISO 数据线的有效信号在 SCK 的奇数边沿保持不变,数据信号将在 SCK 奇数边沿时被采样,在非采样时刻, MOSI 和 MISO 的有效信号才发生切换。

CPHA=1的时候因为时钟极性变化不同数据传输的不同


同样的从上面的图中我们也可以看出就是CPHA=1 时,不受 CPOL 的影响,数据信号在 SCK 的偶数边沿被采样

下面这里我还是用逻辑分析仪对上面进行介绍,可以比较直观的看明白这个过程


因此随着这两个位的不同,SPI就会有四种模式,如下表所示:

SPI模式 CPOL CPHA 空闲时SCK时钟 采样时刻
0 0 0 低电平 奇数边沿
1 0 1 低电平 偶数边沿
2 1 0 高电平 奇数边沿
3 1 1 高电平 偶数边沿

对于STM32而言,基本上是移植了这个SPI所有的功能,然后还做了一些辅助功能,就比如我们有的时候不需要那个读取数据,只需要写数据什么的,或者只需要接收数据,这样的,stm32的硬件spi也都做了相应的适配,下图我对每个功能做了简单的说明

2、W25Q64介绍

好,那我们学了东西是要拿来用的对吧,不然学了没用啊对吧,这里就以一个比较经典的SPI设备为例,就是一般的开发板上都会有的W25Q64芯片。

这个是FLASH芯片,FLSAH 存储器又称闪存,它与 EEPROM 都是掉电后数据不丢失的存储器,但 FLASH存储器容量普遍大于 EEPROM,现在基本取代了它的地位。在存储控制上,EEPROM和最主要的区别是 FLASH 芯片只能一大片一大片地擦写,而 EEPROM 可以单个字节擦写。

这里我们再看下W25Q64的常用指令表


这里以读取设备ID为例,根据上面的指令表,发送9FH,就是向他要设备ID的意思:

他的返回情况如下所示:

主机FLASH 芯片发送第一个字节数据为“9F h” ,当 FLASH 芯片收到该数据后,它会解读成主机向它发送了“JEDEC 指令”,然后它就作出该命令的响应: 通过 MISO 线把它的厂商 ID(M7-M0)及芯片类型(ID15-0)发送给主机,主机接收到指令响应后可进行校验。

3、SPI读写驱动编写

首先我们看下他的这个原理图如下所示

在cubemx中进行对应的配置如下所示:

这里再根据原理图设置一个片选引脚

这样我们的基本配置工作就完成了,下面就是代码部分了,我们先看下我们上面提到的读取ID的部分,这里要注意就是片选信号这里如果选择了软件的方式,那就是每次读写之前都要把片选拉低,然后结束后再把片选拉高!

然后是检查是否繁忙,flash芯片提供了一个寄存器,我们主要是关心他的第0位,当这个位为“1”时,表明 FLASH芯片处于忙碌状态,它可能正在对内部的存储矩阵进行“擦除”或“数据写入”的操作。

之后就是读写函数了,大概就是先擦除,然后选好地址,然后在写入,之后我们在原来设定的地址读取就行了

之后我们在主函数初始化中加入下面的代码

将程序下载到开发板,效果如下所示:

4、源码

w25q64.c

/** w25q64.c**  Created on: Mar 25, 2022*      Author: LX*//* W25Q64的指令 */#include "w25q64.h"
#include "stdio.h"uint8_t w25x_read_id = 0x90;                    // 读ID
uint8_t m_addr[3]    = {0,0,0};                 // 测试地址0x000000
uint8_t check_addr   = 0x05;                    // 检查线路是否繁忙
uint8_t enable_write = 0x06;                    // 使能了才能改变芯片数据
uint8_t erase_addr   = 0x20;                    // 擦除命令
uint8_t write_addr   = 0x02;                    // 写数据命令
uint8_t read_addr    = 0x03;                    // 读数据命令#define CS_HIGH HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET)
#define CS_LOW HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET)extern SPI_HandleTypeDef hspi1;
#define W25Q64SPI hspi1void ReadID(void)
{uint8_t temp_ID[5] = {0,0,0,0,0};CS_LOW;HAL_SPI_Transmit(&W25Q64SPI, &w25x_read_id, 1, 100);HAL_SPI_Receive(&W25Q64SPI, temp_ID, 5, 100);CS_HIGH;printf("ID为 %x%x\n",temp_ID[3],temp_ID[4]);
}
void CheckBusy(void)
{uint8_t status=1;uint32_t timeCount=0;do{timeCount++;if(timeCount > 0xEFFFFFFF) //等待超时{}CS_LOW;HAL_SPI_Transmit(&W25Q64SPI, &check_addr, 1, 100);HAL_SPI_Receive(&W25Q64SPI, &status, 1, 100);CS_HIGH;}while((status&0x01)==0x01);
}/* 写入数据 */
void ReadData(void)
{uint8_t temp_wdata[] = "STM32串行FLASH读取";CheckBusy();CS_LOW;HAL_SPI_Transmit(&W25Q64SPI, &enable_write, 1, 100);//使能写入CS_HIGH;CS_LOW;HAL_SPI_Transmit(&W25Q64SPI, &erase_addr, 1, 100);//擦除命令HAL_SPI_Transmit(&W25Q64SPI, m_addr, 3, 100);//擦除的地址CS_HIGH;CheckBusy();CS_LOW;HAL_SPI_Transmit(&W25Q64SPI, &enable_write, 1, 100);//使能写入CS_HIGH;CS_LOW;HAL_SPI_Transmit(&W25Q64SPI, &write_addr, 1, 100);//写入命令HAL_SPI_Transmit(&W25Q64SPI, m_addr, 3, 100);//写入地址HAL_SPI_Transmit(&W25Q64SPI, temp_wdata, sizeof(temp_wdata), 100);//写入数据CS_HIGH;
}
void WriteData(void)
{uint8_t temp_rdata[128] = {0};CheckBusy();CS_LOW;HAL_SPI_Transmit(&W25Q64SPI, &read_addr, 1, 100);HAL_SPI_Transmit(&W25Q64SPI, m_addr, 3, 100);HAL_SPI_Receive(&W25Q64SPI, temp_rdata, sizeof(temp_rdata), 100);CS_HIGH;printf("写入的数据为:%s\n",temp_rdata);
}

w25q64.h

/** w25q64.h**  Created on: Mar 25, 2022*      Author: LX*/#ifndef W25Q64_H_
#define W25Q64_H_#include "main.h"void ReadID(void);
void ReadData(void);
void WriteData(void);#endif /* W25Q64_H_ */

SPI读写串行FLASH(W25Q64)相关推荐

  1. 第24章 SPI—读写串行FLASH—零死角玩转STM32-F429系列

    第24章     SPI-读写串行FLASH 全套200集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn 野火视频教程优酷观看网址:http://i.youku.com/ ...

  2. SPI—读写串行FLASH(时序中的无关项)

    SPI-读写串行FLASH 全套200集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn 野火视频教程优酷观看网址:http://i.youku.com/firege 本章 ...

  3. SPI—读写串行FLASH

    1 SPI协议简介 SPI协议是由摩托罗拉公司提出的通讯协议(SerialPeripheralInterface),即串行外围设备接口,是一种高速全双工的通信总线.它被广泛地使用在ADC.LCD等设备 ...

  4. 25章 SPI—读写串行FLASH

    SPI 协议简介 3 条总线分别为SCK(时钟).MOSI(主出从入).MISO(主入从出),片选线为SS1.2.3(从设备)(多少设备也就这三条ss) MOSI和MISO能看出是全双工(输入输出两条 ...

  5. 下载的内容:MSP430F149利用硬件SPI口读写串行Flash M25P64

    /*****************<SPI_Flash.C>**************************************/ #include "SPI_Flas ...

  6. STM32CUBEIDE之SPI读写FLASH进阶串行FLASH文件系统FatFs

    预备知识 >>W25Q128是16M spi flash,一共有256个block ,每个Block 64KB. >>一个Block可以分割为16个扇区(small secto ...

  7. SPI应用——W25Q128串行FLASH

    一.FLASH存储器介绍 FLASH存储器又称闪存,它与EEPROM都是掉电后数据不丢失的存储器,但FLASH存储器容量普遍大于EEPROM,现在基本取代了它的地位.在存储控制上,最主要的区别是FLA ...

  8. 3.3 SPI串行Flash配置模式

     SPI串行Flash配置模式 1.SPI串行配置介绍 串行Flash的特点是占用管脚比较少,作为系统的数据存贮非常合适,一般都是采用串行外设接口(SPI 总线接口).Flash 存贮器与EEPROM ...

  9. STM32 串行FLASH文件系统FatFs

    目录 一.Windows系统为例 二.文件系统的结构与特性 为什么要应用文件分配表? 三.FatFs文件系统 1- FatFs 文件系统源码介绍 2- FatFs在程序中的关系网 四.配置FatFs移 ...

  10. 【立创EDA开源推荐】001期 | 基于航顺HK32F030R8串行Flash烧录器

    工程名称: 串行Flash烧录器 工程作者: micespring 工程主页链接:https://oshwhub.com/micespring/hk32_serialflashprogrammer 开 ...

最新文章

  1. 避免35岁现象,我给技术人的建议永远是架构师!
  2. Orchard之模版开发
  3. lisp直线连接圆象限电_用小学数学知识解释,为什么井盖是圆的?
  4. GDI+ 学习记录(27): Bitmap
  5. 如何编写无法维护的代码_编写可维护的前端代码
  6. VS2015占内存大吗?_手机是6GB运行内存,何为后台却显示3G内存?
  7. STM32 进阶教程 20 - 串口+DMA实现OneWire总线
  8. 1.7 元注解作用及使用
  9. 讲讲Print里面还有什么参数可以设置
  10. Java千百问_05面向对象(004)_java接口到底是什么
  11. fota mcsync洛达检测_详细解析最新推出的顶配版二代悦虎主板洛达1562M数字音频长续航款...
  12. 记录工作中用到的日期转换方法
  13. pytorch在anaconda下安装
  14. sketchup 图片转模型_3d模型转su模型(如何将3D模型转化为sketchup)
  15. vue请求接口报错405(Method Not Allowed)
  16. 工业互联网环境下的工业控制系统安全防护
  17. 2016上半年高项项目经理考试培训考试感想
  18. python更改保存路径,Jupyter Notebook更改保存文件的默认路径(方法汇总,亲测有效)...
  19. 大数据【big data 4v】
  20. 多态的摸索之路( 甲 )

热门文章

  1. 【数学建模】CUMCM-2010A 储油罐的变位识别与罐容表标定 解题思路整理
  2. 有限元分析及运用课程笔记第一章:引论
  3. 航空机场三字码和航空公司二字码
  4. 笔试12:Bootstrap知识
  5. 微软补丁导致填制凭证右侧滚动条消失
  6. 屏蔽广告(广告终结者)-- CSDN 第一步
  7. 动画专题:属性动画:插值器AccelerateDecelerateInterpolator 加速插值器
  8. 函数极值最值凸性拐点渐近线总结
  9. 用 Alan 和 Neovis.js 实现全新的 Doctor.ai
  10. 数字电路与逻辑设计——加法器实现