文章目录

  • 一、SPI串行通信协议
    • 1.1 SPI通信协议简介
    • 1.2 SPI工作原理
    • 1.3 SPI特性
  • 二、W25Q128FV芯片介绍
    • 2.1 芯片基本参数介绍
    • 2.2 芯片管脚介绍
    • 2.3 技术手册等更多信息
  • 三、开发板的板载Flash的连接电路
  • 四、测试准备
  • 五、初始化片上外设SPI1
    • 5.1 初始化SPI1
    • 5.2 设置片选引脚PB14
    • 5.3 配置串口打印模式
    • 5.4 设置生成Keil- MDK代码文件
  • 六、读写芯片JEDEC ID
    • 6.1 芯片技术手册和读JEDEC ID流程
    • 6.2 编写读芯片JEDEC ID代码

一、SPI串行通信协议

1.1 SPI通信协议简介

SPI是串行外设接口,是Motorola首先在其MC68HCxx系列处理器上定义的。SPI是一种高速的、全双工,同步的通信总线,并且在芯片的管教上只占用四根线,节约了芯片的管脚,同时为PCB的布局上节省空间,提供方便。

1.2 SPI工作原理

SPI的通信原理很简单,它以主从的方式工作,这种模式通常有一个主设备和一个或者多个从设备,至少需要4根线,事实上3根也可以(片选信号可以直接接地,默认选中)。SPI的4根线是MOSI主设备输出从设备输入),MISO主设备输入从设备输出),CK(时钟信号),CS(片选信号,低电平有效)。

1.3 SPI特性

  • 三线全双工同步传输
  • 8位或16位传输帧格式选择
  • 主或从操作
  • 8个主模式波特率预分频系数
  • 可编程的时钟极性和相位
  • 可编程的数据顺序,MSB在前或者LSB在前
  • 可触发的中断的专用发送和接收标志
  • SPI总线忙状态标志
  • 支持DMA功能的1字节发送和接收缓冲器,产生发送和接收请求

二、W25Q128FV芯片介绍

2.1 芯片基本参数介绍

W25QXX系列存储芯片是基于SPI接口的串行Flash存储器,主要有W25Q64、W25Q128等。芯片支持工作电压在2.7~3.6V之间,在正常工作时电流小于5mA,掉电时低于1uA。最大支持104MHz的编程速度。支持SPI和QSPI读写方式。

  • W25Q128每页256个字节。页是最小的可读、可写单元,也是编程和擦除的最小单位。
  • W25Q128的块大小为64KB。块是由多个页组成的一个较大的存储单元,每个块通常包含256个页面。
  • 如果需要更改或者擦除某个页、块中的某个数据,那么就要将整个页或者块全部写入或者擦除。
  • W25Q128的扇区大小为4KB。扇区是块的子单元,每个块包含16个扇区。更改或者擦除一个扇区的数据不会影响其他的扇区的数据。
  • 字节是最小的可寻址单元,一个字节是由8个二进制位组成,可以存储一个字符或者数字。

2.2 芯片管脚介绍

  • 芯片管脚图
  • 管脚的名称
管脚编号 管脚名称 功能描述
1 /CS 片选输入,为低电平时选中,高电平时未选中
2 DO(IO1) 数据输出(数据输入输出1)
3 /WP(IO2) 写保护输入(数据输入输出2),低电平写保护
4 GND
5 DI(IO0) 输入输入(数据输入输出0)
6 CLK 串行时钟
7 /HOLD(IO3) 数据保持(数据输入输出3)低电平有效
8 VCC 电源正
  • 不同的SPI模式的引脚作用
标准SPI模式下管脚功能 CS DI DP WP HOLD
双倍SPI模式下管脚功能 CS IO0 IO1 WP HOLD
四倍SPI模式下管脚功能 CS IO0 IO1 IO2 IO3

2.3 技术手册等更多信息

点击访问官网

三、开发板的板载Flash的连接电路



1、从电路图中可以看出,芯片的供电电压为3.3V

2、芯片的数据线为4线,接在SPI1总线上

3、芯片读写使能用的是软件片选

  • 芯片和MCU引脚对应表
SPI1_SCK 时钟线 PB3
F_CS 片选(低电平选中)PB14
SPI1_MISO 主机输入从机输出 PB4
SPI1_MOSI 主机输出从机输入PB5

四、测试准备

  • 基于STM32F407ZET6的正点原子开发板(Flash芯片在左上角W25Q128FV)

  • 安装windows系统并安装CubemxKeil MDK的电脑

五、初始化片上外设SPI1

由于硬件原因需要修改成对应硬件的引脚

5.1 初始化SPI1

  • 初始化为全双工模式(因为要进行读写操作)

  • 直接无视软件自动配置的引脚,手动设置硬件对应的引脚为SPI1对应的引脚

  • 时钟源设置为外部高速时钟


【重要】查看开发板的板载晶振的频率(根据自己的开发板的晶振频率设置),因此设置输入的时钟的频率为8Hz,经过分频后最后设置频率为最大168MHz

  • 时钟树设置,经过分频、倍频后

  • 针对SPI1总线进行参数设置

  • 配置参数说明
Mode Full-Duplex Mater 全双工模式主模式
Frame Format Motorola(摩托罗拉)
Data Size 8 Bit( 查看芯片的技术手册可得)
First Bit 高位在前:MSB First ( 查看芯片的技术手册可得)
Prescaler(For BaudRate) 可设置为最高速率:2分频 42.0MBts/s ( 查看芯片的技术手册可得)
Clock Polarity 时钟极性为上升沿 : Low ( 查看芯片的技术手册可得)
Clock Phase 时钟相位为0 : 1 Edge( 查看芯片的技术手册可得)
CRC Calucation 不设置CRC校验:Disable
NSS Signal Type 设置软件片选:SoftWare
MSB MSB代表“Most Significant Bit”,即最高有效位,是二进制数中权值最高的位,通常位于左侧。在多字节数据传输时,MSB通常是首先传输的字节。
LSB LSB代表“Least Significant Bit”,即最低有效位,是二进制数中权值最低的位,通常位于右侧。在多字节数据传输时,LSB通常是最后传输的字节。

Clock Polarity和Clock Phase的具体设置方式需要依照设备和应用场景进行调整的
在本次测试中,由于W25Q128芯片的读写模式支持Mode 0(0,0)Mode3(1,1) 选择了模式0作为读写模式

芯片的数据手册第6.1章节

模式 CPOL(极性) CPHA(相位) 空闲时SCK时钟 采样时刻
模式0 0 0 低电平 奇数边沿
模式1 0 1 低电平 偶数边沿
模式2 1 0 高电平 奇数边沿
模式3 1 1 高电平 偶数边沿

一般经常用的就是模式0和模式3。经过测试,设置为模式0或者模式3均可进行正确的读写。

5.2 设置片选引脚PB14

5.3 配置串口打印模式

参考以前的配置文章进行设置

5.4 设置生成Keil- MDK代码文件

六、读写芯片JEDEC ID

6.1 芯片技术手册和读JEDEC ID流程

在SPI总线上接收三个字节的数据,分别表示制造商ID、设备类型、容量

芯片的Jedec ID指令

芯片的Jedec ID介绍

  • 常见的存储芯片的类型和它的Jedec ID
芯片类型 Jedec ID
SST25VF016B_ID 0xBF2541
MX25L1606E_ID 0xC22015
W25Q64BV_ID(BV JV FV) 0xEF4017
W25Q128_ID 0xEF4018

通过SPI总线读取W25Q128的JEDEC ID,并将JEDEC ID整合为一个32位的数值。具体流程如下:

  1. 通过调用sf_SetCS函数使能W25Q128芯片的片选信号。
  2. 将读取ID命令(0x9F)放入发送缓冲区g_spiTxBuf,并将发送缓冲区长度g_spiLen设置为4(包括一个读取ID命令和3个地址字节)。
  3. 调用bsp_spiTransfer函数发送读取ID命令,并从DO引脚接收3个字节的ID数据,并将接收到的数据存储在g_spiRxBuf接收缓冲区中。
  4. g_spiRxBuf接收缓冲区中读取3个字节的ID数据,并分别存储在id1、id2和id3变量中。
  5. 通过调用sf_SetCS函数禁用W25Q128芯片的片选信号。
  6. 将3个字节的ID数据整合成一个32位的数值uiID,其中id1占据高16位,id2占据中8位,id3占据低8位。
  7. 将整合后的32位ID数值返回。

6.2 编写读芯片JEDEC ID代码

代码来自安富莱电子

[bsp_flash.c]#include "bsp_flash.h"
SFLASH_T g_tSF;  //定义结构体/*
*********************************************************************************************************
*   函 数 名: sf_SetCS
*   功能说明: 串行FALSH片选控制函数
*   形    参: 无
*   返 回 值: 无
*********************************************************************************************************
*/
void sf_SetCS(uint8_t _Level)
{if (_Level == 0){bsp_SpiBusEnter();     SF_CS_0();}else{     SF_CS_1();  bsp_SpiBusExit();       }
}/*
*********************************************************************************************************
*   函 数 名: sf_ReadInfo
*   功能说明: 读取器件ID,并填充器件参数
*   形    参: 无
*   返 回 值: 无
*********************************************************************************************************
*/
void sf_ReadInfo(void)
{/* 自动识别串行Flash型号 */{g_tSF.ChipID = sf_ReadID();   /* 芯片ID */switch (g_tSF.ChipID){case SST25VF016B_ID:strcpy(g_tSF.ChipName, "SST25VF016B");g_tSF.TotalSize = 2 * 1024 * 1024; /* 总容量 = 2M */g_tSF.SectorSize = 4 * 1024;        /* 扇区大小 = 4K */break;case MX25L1606E_ID:strcpy(g_tSF.ChipName, "MX25L1606E");g_tSF.TotalSize = 2 * 1024 * 1024; /* 总容量 = 2M */g_tSF.SectorSize = 4 * 1024;        /* 扇区大小 = 4K */break;case W25Q64BV_ID:strcpy(g_tSF.ChipName, "W25Q64");g_tSF.TotalSize = 8 * 1024 * 1024;   /* 总容量 = 8M */g_tSF.SectorSize = 4 * 1024;        /* 扇区大小 = 4K */break;case W25Q128_ID:strcpy(g_tSF.ChipName, "W25Q128");g_tSF.TotalSize = 16 * 1024 * 1024;  /* 总容量 = 8M */g_tSF.SectorSize = 4 * 1024;        /* 扇区大小 = 4K */break;          default:strcpy(g_tSF.ChipName, "Unknow Flash");g_tSF.TotalSize = 2 * 1024 * 1024;g_tSF.SectorSize = 4 * 1024;break;}}
}/*
*********************************************************************************************************
*   函 数 名: sf_ReadID
*   功能说明: 读取器件ID
*   形    参:  无
*   返 回 值: 32bit的器件ID (最高8bit填0,有效ID位数为24bit)
*********************************************************************************************************
*/
uint32_t sf_ReadID(void)
{uint32_t uiID;uint8_t id1, id2, id3;sf_SetCS(0);                               /* 使能片选 */g_spiLen = 0;g_spiTxBuf[0] = (CMD_RDID);      /* 发送读ID命令 0x9F */g_spiLen = 4;bsp_spiTransfer();id1 = g_spiRxBuf[1];                   /* 读ID的第1个字节 */id2 = g_spiRxBuf[2];                    /* 读ID的第2个字节 */id3 = g_spiRxBuf[3];                    /* 读ID的第3个字节 */sf_SetCS(1);                             /* 禁能片选 */uiID = ((uint32_t)id1 << 16) | ((uint32_t)id2 << 8) | id3;   /*ID整合*/return uiID;
}
[bsp_flash.h]
#ifndef __BSP_FLASH_H_
#define __BSP_FLASH_H_#include "stm32f4xx_hal.h"
#include "main.h"
#include "spi.h"
#include "string.h"#define SF_CS_0()                  F_CS_GPIO_Port->BSRR = ((uint32_t)F_CS_Pin << 16U)
#define SF_CS_1()                   F_CS_GPIO_Port->BSRR = F_CS_Pin#define CMD_AAI       0xAD   /* AAI 连续编程指令(FOR SST25VF016B) */
#define CMD_DISWR       0x04        /* 禁止写, 退出AAI状态 */
#define CMD_EWRSR       0x50        /* 允许写状态寄存器的命令 */
#define CMD_WRSR      0x01      /* 写状态寄存器命令 */
#define CMD_WREN      0x06      /* 写使能命令 */
#define CMD_READ      0x03      /* 读数据区命令 */
#define CMD_RDSR      0x05      /* 读状态寄存器命令 */
#define CMD_RDID      0x9F      /* 读器件ID命令 */
#define CMD_SE        0x20      /* 擦除扇区命令 */
#define CMD_BE        0xC7      /* 批量擦除命令 */
#define DUMMY_BYTE    0xA5      /* 哑命令,可以为任意值,用于读操作 */#define WIP_FLAG      0x01      /* 状态寄存器中的正在编程标志(WIP) */typedef struct
{uint32_t ChipID;       /* 芯片ID */char ChipName[16];        /* 芯片型号字符串,主要用于显示 */uint32_t TotalSize;      /* 总容量 */uint16_t SectorSize;       /* 扇区大小 */
}SFLASH_T;/* 定义串行Flash ID */
enum
{SST25VF016B_ID = 0xBF2541,MX25L1606E_ID  = 0xC22015,W25Q64BV_ID    = 0xEF4017, /* BV, JV, FV */W25Q128_ID     = 0xEF4018
};void bsp_InitSFlash(void);
void sf_ReadInfo(void);
uint32_t sf_ReadID(void);
void sf_SetCS(uint8_t _Level);extern SFLASH_T g_tSF;#endif
[spi.c]
/* USER CODE BEGIN Header */
/********************************************************************************* @file    spi.c* @brief   This file provides code for the configuration*          of the SPI instances.******************************************************************************* @attention** Copyright (c) 2023 STMicroelectronics.* All rights reserved.** This software is licensed under terms that can be found in the LICENSE file* in the root directory of this software component.* If no LICENSE file comes with this software, it is provided AS-IS.********************************************************************************/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "spi.h"/* USER CODE BEGIN 0 */
enum {TRANSFER_WAIT,TRANSFER_COMPLETE,TRANSFER_ERROR
};uint32_t g_spiLen;
uint8_t  g_spi_busy; /* SPI忙状态,0表示不忙,1表示忙 */
__IO uint32_t wTransferState = TRANSFER_WAIT;uint8_t g_spiTxBuf[SPI_BUFFER_SIZE];
uint8_t g_spiRxBuf[SPI_BUFFER_SIZE];/*
*********************************************************************************************************
*                                选择DMA,中断或者查询方式
*********************************************************************************************************
*/
//#define USE_SPI_DMA    /* DMA方式  */
//#define USE_SPI_INT    /* 中断方式 */
#define USE_SPI_POLL   /* 查询方式 *//* USER CODE END 0 */SPI_HandleTypeDef hspi1;/* SPI1 init function */
void MX_SPI1_Init(void)
{/* USER CODE BEGIN SPI1_Init 0 *//* USER CODE END SPI1_Init 0 *//* USER CODE BEGIN SPI1_Init 1 *//* USER CODE END SPI1_Init 1 */hspi1.Instance = SPI1;hspi1.Init.Mode = SPI_MODE_MASTER;hspi1.Init.Direction = SPI_DIRECTION_2LINES;hspi1.Init.DataSize = SPI_DATASIZE_8BIT;hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;hspi1.Init.NSS = SPI_NSS_SOFT;hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;hspi1.Init.TIMode = SPI_TIMODE_DISABLE;hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;hspi1.Init.CRCPolynomial = 10;if (HAL_SPI_Init(&hspi1) != HAL_OK){Error_Handler();}/* USER CODE BEGIN SPI1_Init 2 *//* USER CODE END SPI1_Init 2 */}void HAL_SPI_MspInit(SPI_HandleTypeDef* spiHandle)
{GPIO_InitTypeDef GPIO_InitStruct = {0};if(spiHandle->Instance==SPI1){/* USER CODE BEGIN SPI1_MspInit 0 *//* USER CODE END SPI1_MspInit 0 *//* SPI1 clock enable */__HAL_RCC_SPI1_CLK_ENABLE();__HAL_RCC_GPIOB_CLK_ENABLE();/**SPI1 GPIO ConfigurationPB3     ------> SPI1_SCKPB4     ------> SPI1_MISOPB5     ------> SPI1_MOSI*/GPIO_InitStruct.Pin = GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5;GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);/* USER CODE BEGIN SPI1_MspInit 1 *//* USER CODE END SPI1_MspInit 1 */}
}void HAL_SPI_MspDeInit(SPI_HandleTypeDef* spiHandle)
{if(spiHandle->Instance==SPI1){/* USER CODE BEGIN SPI1_MspDeInit 0 *//* USER CODE END SPI1_MspDeInit 0 *//* Peripheral clock disable */__HAL_RCC_SPI1_CLK_DISABLE();/**SPI1 GPIO ConfigurationPB3     ------> SPI1_SCKPB4     ------> SPI1_MISOPB5     ------> SPI1_MOSI*/HAL_GPIO_DeInit(GPIOB, GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5);/* USER CODE BEGIN SPI1_MspDeInit 1 *//* USER CODE END SPI1_MspDeInit 1 */}
}/* USER CODE BEGIN 1 */
/*
*********************************************************************************************************
*   函 数 名: HAL_SPI_TxRxCpltCallback,HAL_SPI_ErrorCallback
*   功能说明: SPI数据传输完成回调和传输错误回调
*   形    参: SPI_HandleTypeDef 类型指针变量
*   返 回 值: 无
*********************************************************************************************************
*/
void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi)
{wTransferState = TRANSFER_COMPLETE;
}void HAL_SPI_ErrorCallback(SPI_HandleTypeDef *hspi)
{wTransferState = TRANSFER_ERROR;
}/*
*********************************************************************************************************
*   函 数 名: bsp_SpiBusEnter
*   功能说明: 占用SPI总线
*   形    参: 无
*   返 回 值: 0 表示不忙  1表示忙
*********************************************************************************************************
*/
void bsp_SpiBusEnter(void)
{g_spi_busy = 1;
}/*
*********************************************************************************************************
*   函 数 名: bsp_SpiBusExit
*   功能说明: 释放占用的SPI总线
*   形    参: 无
*   返 回 值: 0 表示不忙  1表示忙
*********************************************************************************************************
*/
void bsp_SpiBusExit(void)
{g_spi_busy = 0;
}/*
*********************************************************************************************************
*   函 数 名: bsp_SpiBusBusy
*   功能说明: 判断SPI总线忙,方法是检测其他SPI芯片的片选信号是否为1
*   形    参: 无
*   返 回 值: 0 表示不忙  1表示忙
*********************************************************************************************************
*/
uint8_t bsp_SpiBusBusy(void)
{return g_spi_busy;
}/*
*********************************************************************************************************
*   函 数 名: bsp_spiTransfer
*   功能说明: 启动数据传输
*   形    参: 无
*   返 回 值: 无
*********************************************************************************************************
*/
void bsp_spiTransfer(void)
{if (g_spiLen > SPI_BUFFER_SIZE){return;}/* DMA方式传输 */
#ifdef USE_SPI_DMAwTransferState = TRANSFER_WAIT;if(HAL_SPI_TransmitReceive_DMA(&hspi, (uint8_t*)g_spiTxBuf, (uint8_t *)g_spiRxBuf, g_spiLen) != HAL_OK)  {Error_Handler();}while (wTransferState == TRANSFER_WAIT){;}
#endif/* 中断方式传输 */
#ifdef USE_SPI_INTwTransferState = TRANSFER_WAIT;if(HAL_SPI_TransmitReceive_IT(&hspi, (uint8_t*)g_spiTxBuf, (uint8_t *)g_spiRxBuf, g_spiLen) != HAL_OK)   {Error_Handler();}while (wTransferState == TRANSFER_WAIT){;}
#endif/* 查询方式传输 */
#ifdef USE_SPI_POLLif(HAL_SPI_TransmitReceive(&hspi1, (uint8_t*)g_spiTxBuf, (uint8_t *)g_spiRxBuf, g_spiLen, 1000000) != HAL_OK)   {Error_Handler();}
#endif
}/* USER CODE END 1 */
[spi.h]
/* USER CODE BEGIN Header */
/********************************************************************************* @file    spi.h* @brief   This file contains all the function prototypes for*          the spi.c file******************************************************************************* @attention** Copyright (c) 2023 STMicroelectronics.* All rights reserved.** This software is licensed under terms that can be found in the LICENSE file* in the root directory of this software component.* If no LICENSE file comes with this software, it is provided AS-IS.********************************************************************************/
/* USER CODE END Header */
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __SPI_H__
#define __SPI_H__#ifdef __cplusplus
extern "C" {#endif/* Includes ------------------------------------------------------------------*/
#include "main.h"/* USER CODE BEGIN Includes */
#define SPI_BUFFER_SIZE     (4 * 1024)
extern uint8_t g_spiTxBuf[SPI_BUFFER_SIZE];
extern uint8_t g_spiRxBuf[SPI_BUFFER_SIZE];
extern uint32_t g_spiLen;
extern uint8_t g_spi_busy;/* USER CODE END Includes */extern SPI_HandleTypeDef hspi1;/* USER CODE BEGIN Private defines *//* USER CODE END Private defines */void MX_SPI1_Init(void);/* USER CODE BEGIN Prototypes */
void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi);
void HAL_SPI_ErrorCallback(SPI_HandleTypeDef *hspi);
void bsp_SpiBusEnter(void);
void bsp_SpiBusExit(void);
uint8_t bsp_SpiBusBusy(void);
void bsp_spiTransfer(void);/* USER CODE END Prototypes */#ifdef __cplusplus
}
#endif#endif /* __SPI_H__ */
[main.c]/* USER CODE BEGIN Includes */
#include "stdio.h"
#include "bsp_flash.h"
/* USER CODE END Includes *//* USER CODE BEGIN 2 */
sf_ReadInfo();//读取芯片的ID
/* 检测串行Flash OK */
printf("检测到串行Flash, ID = %08X, 型号: %s \r\n", g_tSF.ChipID , g_tSF.ChipName);
printf("    容量 : %dM字节, 扇区大小 : %d字节\r\n", g_tSF.TotalSize/(1024*1024), g_tSF.SectorSize);
/* USER CODE END 2 */[result]检测到串行Flash, ID = 00EF4018, 型号: W25Q128
容量 : 16M字节, 扇区大小 : 4096字节

STM32-HAL-SPI-读写W25Q128FV-JEDEC ID(1)相关推荐

  1. STM32利用SPI读写SD卡的程序详解

    STM32利用SPI读写SD卡的一些程序详解 关于SD卡的基础知识这里不做过多陈述,如果有对这方面感兴趣的朋友可以直接百度一下,有很多讲SD卡的文章,这里主要是针对SD卡的读写程序实现做一些详细说明. ...

  2. stm32中spi可以随便接吗_STM32的SPI模式读写FLASH芯片全面讲解

    例程完整代码: SPI协议简介 SPI协议,即串行外围设备接口,是一种告诉全双工的通信总线,它被广泛地使用在ADC,LCD等设备与MCU间通信的场合. SPI信号线 SPI包含4条总线,分别为SS,S ...

  3. STM32的SPI模式读写FLASH芯片全面讲解

    SPI协议简介 SPI协议,即串行外围设备接口,是一种告诉全双工的通信总线,它被广泛地使用在ADC,LCD等设备与MCU间通信的场合. SPI信号线 SPI包含4条总线,分别为SS,SCK,MOSI, ...

  4. STM32笔记(十二)---SPI读写FLASH

    SPI读写FLASH 文章目录 SPI读写FLASH 一.SPI协议简介 1.1 SPI 物理层 1.2 协议层 1.2.1 SPI 基本通讯过程 1.2.2 通讯的起始和停止信号 1.2.3 数据有 ...

  5. STM32 SPI读写FLASH

    文章目录 一.SPI协议 1.物理层 2.协议层 总体讲解 具体讲解 二.STM32 SPI外设 1.通讯引脚 2.时钟控制逻辑 3.数据控制 4.整体控制逻辑 三.通信过程 四.固件库编程 1.结构 ...

  6. [学习笔记]STM32F1硬件SPI读写W25Qx(寄存器、标准库、HAL库)

    目录 10. 硬件SPI读写W25Qx 0. 博主调侃: 1. 实验内容及步骤: 2. 硬件说明 3. 步骤详细讲解 3.1 RCC 3.2 配置GPIO 3.3 硬件SPI配置 3.4 发送和接收过 ...

  7. STM32学习笔记之硬件SPI读写与极性设置

    废话不多说讲重点!!! [软件中如何设置SPI的极性和相位]  SPI分主设备和从设备,两者通过SPI协议通讯. 而设置SPI的模式,是从设备的模式,决定了主设备的模式.  所以要先去搞懂从设备的SP ...

  8. 《STM32从零开始学习历程》——SPI读写FLASH

    <STM32从零开始学习历程>@EnzoReventon SPI读写FLASH 相关链接: SPI物理层及FLASH芯片介绍 SPI协议层 SPI特性及架构 参考资料: [野火EmbedF ...

  9. stm32 SPI读写储存卡(MicroSD TF卡)

    stm32 SPI读写储存卡(MicroSD TF卡) 简述 操作分析及实现 0.整个流程 1.上电以后储存卡的初始化 2.如何进行读写 3.下面是具体的过程 博客原址:http://www.code ...

  10. [学习笔记]STM32F1软件SPI读写W25Qx(寄存器、标准库、HAL库)

    目录 9. 软件SPI读写W25Qx 0. 博主调侃: 1. 实验内容及步骤: 2. 硬件说明 3. 步骤详细讲解 3.1 配置GPIO 3.2 软件SPI读写Byte(模式0或模式3) 3.3 读取 ...

最新文章

  1. 轻松破解NewzCrawler时间限制
  2. Thinkpad SL400 issue
  3. The Singleton of Design Pattern单态模式
  4. SpringBoot - 统一格式封装及高阶全局异常处理
  5. 简单java socket_基于Java Socket实现一个简易在线聊天功能(一)
  6. 20应用统计考研复试要点(part34)--简答题
  7. Linux 环境下 jdk1.8 maven3.2.3 Git2.8.0 安装脚本
  8. junit规则_JUnit规则
  9. python里面的函数
  10. 2018生活消费趋势:越来越多95后开始泡枸杞
  11. pdftk — PDF万用命令行工具
  12. Debug学习资源汇总
  13. 如何将两个php超链接,php超链接跳转
  14. 重走JAVA之路(四):ThreadLocal源码解析
  15. UVA - 10129 Play on Words(欧拉回路)
  16. 个人技术博客的选择:CSDN、博客园、简书、知乎专栏、Github、新浪、个人建站等?
  17. 初识C语言及开始跨考计算机的心路历程
  18. 弱网条件下基于阻抗小扰动稳定性分析,小信号模型,阻抗扫描(电容电流反馈有源阻尼),单逆变器SRF-PLL
  19. 静态网站和动态网站的区别
  20. 俞敏洪:度过有意义的生命

热门文章

  1. Java批量修改文件名
  2. 犯错误很正常,可怕的是同样的错误重复在犯!
  3. 树莓派搭建微信小程序服务器传音频(局域网)
  4. IE浏览器无法联网的解决办法
  5. MySQL数据库——备份与恢复
  6. NMI 代码实现步骤
  7. dnf加物理攻击的卡片有哪些_dnf物理攻击宝珠_dnf2019物理攻击宝珠大全_快吧游戏...
  8. 所有ICO项目100%都会归零!STO证券型代币才是区块链融资正确打开方式
  9. 相位相关计算两张图片的平移量
  10. 十、什么是临界资源及如何访问临界资源