• STM32之SPI和W25Q128


    目录

    SPI 介绍

    SPI 物理架构

    SPI 工作原理

    SPI 工作模式

     W25Q128 介绍

    W25Q128 存储架构

    W25Q128 常用指令

    W25Q128 状态寄存器

    W25Q128 常见操作流程

    实验:使用 SPI 通讯读写 W25Q128 模块 

    硬件接线

    cubeMX配置

    w25q128_write_nocheck流程图 

    代码:


    SPI 介绍

    SPI 是什么?
    SPI 是串行外设接口( Serial Peripheral Interface )的缩写,是一种高速的,全双工,同步的通信总
    线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚,同时为 PCB 的布局上节省空间,提
    供方便,正是出于这种简单易用的特性,越来越多的芯片集成了这种通信协议,比如
    AT91RM9200

    SPI 物理架构

    SPI 包含 4 条总线, SPI 总线包含 4 条总线,分别为 SS SCK MOSI MISO 。它们的作用介绍如
    下 :
    (1) MISO – Master Input Slave Output ,主设备数据输入,从设备数据输出 (2) MOSI – Master
    Output Slave Input ,主设备数据输出,从设备数据输入 (3) SCK – Serial Clock ,时钟信号,由主
    设备产生 (4) CS – Chip Select ,片选信号,由主设备控制

    SPI 工作原理

    SPI 工作模式

    时钟极性( CPOL
    没有数据传输时时钟线的空闲状态电平 0 SCK 在空闲状态保持低电平 1 SCK 在空闲状态保持高
    电平
    时钟相位( CPHA
    时钟线在第几个时钟边沿采样数据 0 SCK 的第一(奇数)边沿进行数据位采样,数据在第一个时
    钟边沿被锁存 1 SCK 的第二(偶数)边沿进行数据位采样,数据在第二个时钟边沿被锁存

     

    模式 0 和模式 3 最常用。
    模式 0 时序图:
    模式 3 时序图:

     W25Q128 介绍

    什么是 W25Q128
    W25Q128 是华邦公司推出的一款 SPI 接口的 NOR Flash 芯片,其存储空间为 128 Mbit ,相当于
    16M 字节。
    Flash 是常用的用于储存数据的半导体器件,它具有容量大,可重复擦写、按 扇区 / 擦除、掉
    电后数据可继续保存的特性。
    Flash 是有一个物理特性:只能写 0 ,不能写 1 ,写 1 靠擦除。

    W25Q128 存储架构

    一般按扇区( 4k )进行擦除。
    可以按 章 -- -- -- 字 进行理解。

    W25Q128 常用指令

     W25Q128 全部指令非常多,但常用的如下几个指令:

    写使能 (06H)
    执行页写,扇区擦除,块擦除,片擦除,写状态寄存器等指令前,需要写使能。
    拉低 CS 片选 发送 06H → 拉高 CS 片选
    读状态寄存器( 05H
    拉低 CS 片选 发送 05H→ 返回 SR1 的值 拉高 CS 片选
    读时序( 03H
    拉低 CS 片选 发送 03H→ 发送 24 位地址 读取数据( 1~n 拉高 CS 片选
    页写时序 (02H)
    页写命令最多可以向 FLASH 传输 256 个字节的数据。
    拉低 CS 片选 发送 02H→ 发送 24 位地址 发送数据( 1~n 拉高 CS 片选
    扇区擦除时序( 20H
    写入数据前,检查内存空间是否全部都是 0XFF ,不满足需擦除。
    拉低 CS 片选 发送 20H→ 发送 24 位地址 拉高 CS 片选

    W25Q128 状态寄存器

    W25Q128 一共有 3 个状态寄存器,它们的作用是跟踪芯片的状态。
    其中,状态寄存器 1 较为常用

    BUSY :指示当前的状态, 0 表示空闲, 1 表示忙碌 WEL :写使能锁定,为 1 时,可以操作页 /
    / 块。为 0 时,写禁止。

    W25Q128 常见操作流程

    以下流程省略了拉低/拉高片选信号CS

    读操作:

    擦除扇区:

    写操作

    实验:使用 SPI 通讯读写 W25Q128 模块 

    硬件接线

    VCC -- 3.3V
    CS -- PA4
    CLK -- PA5
    DO -- PA6
    DI -- PA7

    cubeMX配置

    w25q128_write_nocheck流程图 

    代码:

    spi.h

    1. /* USER CODE BEGIN Header */
    2. /**
    3. ******************************************************************************
    4. * @file spi.h
    5. * @brief This file contains all the function prototypes for
    6. * the spi.c file
    7. ******************************************************************************
    8. * @attention
    9. *
    10. * Copyright (c) 2023 STMicroelectronics.
    11. * All rights reserved.
    12. *
    13. * This software is licensed under terms that can be found in the LICENSE file
    14. * in the root directory of this software component.
    15. * If no LICENSE file comes with this software, it is provided AS-IS.
    16. *
    17. ******************************************************************************
    18. */
    19. /* USER CODE END Header */
    20. /* Define to prevent recursive inclusion -------------------------------------*/
    21. #ifndef __SPI_H__
    22. #define __SPI_H__
    23. #ifdef __cplusplus
    24. extern "C" {
    25. #endif
    26. /* Includes ------------------------------------------------------------------*/
    27. #include "main.h"
    28. /* USER CODE BEGIN Includes */
    29. /* USER CODE END Includes */
    30. extern SPI_HandleTypeDef hspi1;
    31. /* USER CODE BEGIN Private defines */
    32. /* USER CODE END Private defines */
    33. void MX_SPI1_Init(void);
    34. /* USER CODE BEGIN Prototypes */
    35. uint8_t spi1_read_write_byte(uint8_t data);
    36. /* USER CODE END Prototypes */
    37. #ifdef __cplusplus
    38. }
    39. #endif
    40. #endif /* __SPI_H__ */

    spi.c

    1. /* USER CODE BEGIN Header */
    2. /**
    3. ******************************************************************************
    4. * @file spi.c
    5. * @brief This file provides code for the configuration
    6. * of the SPI instances.
    7. ******************************************************************************
    8. * @attention
    9. *
    10. * Copyright (c) 2023 STMicroelectronics.
    11. * All rights reserved.
    12. *
    13. * This software is licensed under terms that can be found in the LICENSE file
    14. * in the root directory of this software component.
    15. * If no LICENSE file comes with this software, it is provided AS-IS.
    16. *
    17. ******************************************************************************
    18. */
    19. /* USER CODE END Header */
    20. /* Includes ------------------------------------------------------------------*/
    21. #include "spi.h"
    22. /* USER CODE BEGIN 0 */
    23. /* USER CODE END 0 */
    24. SPI_HandleTypeDef hspi1;
    25. /* SPI1 init function */
    26. void MX_SPI1_Init(void)
    27. {
    28. /* USER CODE BEGIN SPI1_Init 0 */
    29. /* USER CODE END SPI1_Init 0 */
    30. /* USER CODE BEGIN SPI1_Init 1 */
    31. /* USER CODE END SPI1_Init 1 */
    32. hspi1.Instance = SPI1;
    33. hspi1.Init.Mode = SPI_MODE_MASTER;
    34. hspi1.Init.Direction = SPI_DIRECTION_2LINES;
    35. hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
    36. hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
    37. hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
    38. hspi1.Init.NSS = SPI_NSS_SOFT;
    39. hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256;
    40. hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
    41. hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
    42. hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
    43. hspi1.Init.CRCPolynomial = 10;
    44. if (HAL_SPI_Init(&hspi1) != HAL_OK)
    45. {
    46. Error_Handler();
    47. }
    48. /* USER CODE BEGIN SPI1_Init 2 */
    49. /* USER CODE END SPI1_Init 2 */
    50. }
    51. void HAL_SPI_MspInit(SPI_HandleTypeDef* spiHandle)
    52. {
    53. GPIO_InitTypeDef GPIO_InitStruct = {0};
    54. if(spiHandle->Instance==SPI1)
    55. {
    56. /* USER CODE BEGIN SPI1_MspInit 0 */
    57. /* USER CODE END SPI1_MspInit 0 */
    58. /* SPI1 clock enable */
    59. __HAL_RCC_SPI1_CLK_ENABLE();
    60. __HAL_RCC_GPIOA_CLK_ENABLE();
    61. /**SPI1 GPIO Configuration
    62. PA5 ------> SPI1_SCK
    63. PA6 ------> SPI1_MISO
    64. PA7 ------> SPI1_MOSI
    65. */
    66. GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_7;
    67. GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    68. GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    69. HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    70. GPIO_InitStruct.Pin = GPIO_PIN_6;
    71. GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    72. GPIO_InitStruct.Pull = GPIO_NOPULL;
    73. HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    74. /* USER CODE BEGIN SPI1_MspInit 1 */
    75. /* USER CODE END SPI1_MspInit 1 */
    76. }
    77. }
    78. void HAL_SPI_MspDeInit(SPI_HandleTypeDef* spiHandle)
    79. {
    80. if(spiHandle->Instance==SPI1)
    81. {
    82. /* USER CODE BEGIN SPI1_MspDeInit 0 */
    83. /* USER CODE END SPI1_MspDeInit 0 */
    84. /* Peripheral clock disable */
    85. __HAL_RCC_SPI1_CLK_DISABLE();
    86. /**SPI1 GPIO Configuration
    87. PA5 ------> SPI1_SCK
    88. PA6 ------> SPI1_MISO
    89. PA7 ------> SPI1_MOSI
    90. */
    91. HAL_GPIO_DeInit(GPIOA, GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7);
    92. /* USER CODE BEGIN SPI1_MspDeInit 1 */
    93. /* USER CODE END SPI1_MspDeInit 1 */
    94. }
    95. }
    96. /* USER CODE BEGIN 1 */
    97. uint8_t spi1_read_write_byte(uint8_t data)
    98. {
    99. uint8_t rec_data = 0;
    100. HAL_SPI_TransmitReceive(&hspi1, &data, &rec_data, 1, 1000);
    101. return rec_data;
    102. }
    103. /* USER CODE END 1 */

    main.c

    1. /* USER CODE BEGIN Header */
    2. /**
    3. ******************************************************************************
    4. * @file : main.c
    5. * @brief : Main program body
    6. ******************************************************************************
    7. * @attention
    8. *
    9. * Copyright (c) 2023 STMicroelectronics.
    10. * All rights reserved.
    11. *
    12. * This software is licensed under terms that can be found in the LICENSE file
    13. * in the root directory of this software component.
    14. * If no LICENSE file comes with this software, it is provided AS-IS.
    15. *
    16. ******************************************************************************
    17. */
    18. /* USER CODE END Header */
    19. /* Includes ------------------------------------------------------------------*/
    20. #include "main.h"
    21. #include "spi.h"
    22. #include "usart.h"
    23. #include "gpio.h"
    24. /* Private includes ----------------------------------------------------------*/
    25. /* USER CODE BEGIN Includes */
    26. #include "stdio.h"
    27. #include "string.h"
    28. #include "w25q128.h"
    29. /* USER CODE END Includes */
    30. /* Private typedef -----------------------------------------------------------*/
    31. /* USER CODE BEGIN PTD */
    32. /* USER CODE END PTD */
    33. /* Private define ------------------------------------------------------------*/
    34. /* USER CODE BEGIN PD */
    35. /* USER CODE END PD */
    36. /* Private macro -------------------------------------------------------------*/
    37. /* USER CODE BEGIN PM */
    38. #define TEXT_SIZE 16
    39. #define FLASH_WriteAddress 0x00000
    40. #define FLASH_ReadAddress FLASH_WriteAddress
    41. /* USER CODE END PM */
    42. /* Private variables ---------------------------------------------------------*/
    43. /* USER CODE BEGIN PV */
    44. /* USER CODE END PV */
    45. /* Private function prototypes -----------------------------------------------*/
    46. void SystemClock_Config(void);
    47. /* USER CODE BEGIN PFP */
    48. /* USER CODE END PFP */
    49. /* Private user code ---------------------------------------------------------*/
    50. /* USER CODE BEGIN 0 */
    51. /* USER CODE END 0 */
    52. /**
    53. * @brief The application entry point.
    54. * @retval int
    55. */
    56. int main(void)
    57. {
    58. /* USER CODE BEGIN 1 */
    59. uint8_t datatemp[TEXT_SIZE];
    60. /* USER CODE END 1 */
    61. /* MCU Configuration--------------------------------------------------------*/
    62. /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
    63. HAL_Init();
    64. /* USER CODE BEGIN Init */
    65. /* USER CODE END Init */
    66. /* Configure the system clock */
    67. SystemClock_Config();
    68. /* USER CODE BEGIN SysInit */
    69. /* USER CODE END SysInit */
    70. /* Initialize all configured peripherals */
    71. MX_GPIO_Init();
    72. MX_SPI1_Init();
    73. MX_USART1_UART_Init();
    74. /* USER CODE BEGIN 2 */
    75. w25q128_init();
    76. /* 写入测试数据 */
    77. sprintf((char *)datatemp, "liangxu shuai");
    78. w25q128_write(datatemp, FLASH_WriteAddress, TEXT_SIZE);
    79. printf("数据写入完成!\r\n");
    80. /* 读出测试数据 */
    81. memset(datatemp, 0, TEXT_SIZE);
    82. w25q128_read(datatemp, FLASH_ReadAddress, TEXT_SIZE);
    83. printf("读出数据:%s\r\n", datatemp);
    84. /* USER CODE END 2 */
    85. /* Infinite loop */
    86. /* USER CODE BEGIN WHILE */
    87. while (1)
    88. {
    89. /* USER CODE END WHILE */
    90. /* USER CODE BEGIN 3 */
    91. }
    92. /* USER CODE END 3 */
    93. }
    94. /**
    95. * @brief System Clock Configuration
    96. * @retval None
    97. */
    98. void SystemClock_Config(void)
    99. {
    100. RCC_OscInitTypeDef RCC_OscInitStruct = {0};
    101. RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
    102. /** Initializes the RCC Oscillators according to the specified parameters
    103. * in the RCC_OscInitTypeDef structure.
    104. */
    105. RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
    106. RCC_OscInitStruct.HSEState = RCC_HSE_ON;
    107. RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
    108. RCC_OscInitStruct.HSIState = RCC_HSI_ON;
    109. RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
    110. RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
    111. RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
    112. if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
    113. {
    114. Error_Handler();
    115. }
    116. /** Initializes the CPU, AHB and APB buses clocks
    117. */
    118. RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
    119. |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
    120. RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
    121. RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
    122. RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
    123. RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
    124. if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
    125. {
    126. Error_Handler();
    127. }
    128. }
    129. /* USER CODE BEGIN 4 */
    130. /* USER CODE END 4 */
    131. /**
    132. * @brief This function is executed in case of error occurrence.
    133. * @retval None
    134. */
    135. void Error_Handler(void)
    136. {
    137. /* USER CODE BEGIN Error_Handler_Debug */
    138. /* User can add his own implementation to report the HAL error return state */
    139. __disable_irq();
    140. while (1)
    141. {
    142. }
    143. /* USER CODE END Error_Handler_Debug */
    144. }
    145. #ifdef USE_FULL_ASSERT
    146. /**
    147. * @brief Reports the name of the source file and the source line number
    148. * where the assert_param error has occurred.
    149. * @param file: pointer to the source file name
    150. * @param line: assert_param error line source number
    151. * @retval None
    152. */
    153. void assert_failed(uint8_t *file, uint32_t line)
    154. {
    155. /* USER CODE BEGIN 6 */
    156. /* User can add his own implementation to report the file name and line number,
    157. ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
    158. /* USER CODE END 6 */
    159. }
    160. #endif /* USE_FULL_ASSERT */

  • 相关阅读:
    CSDN App 2022上半年-栉风沐雨谨慎前行
    python永久配置pip下载镜像源方法(window版本)
    一行命令找出 Linux 中所有真实用户
    SEAndroid学习
    SqlServe存储过程中运用事务
    Blazor 在开发环境保存机密(User Secrets)
    java项目-第86期基于ssh的上门家教在线预约系统
    程序员的数学课08 加乘法则:如何计算复杂事件发生的概率?
    HJ33整数与IP地址间的转换
    365天挑战LeetCode1000题——Day 046 生成每种字符都是奇数个的字符串 + 两数相加 + 有效的括号
  • 原文地址:https://blog.csdn.net/weixin_49001476/article/details/130909856