微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > MCU和单片机设计讨论 > 第046例:SPI-串行Flash

第046例:SPI-串行Flash

时间:10-02 整理:3721RD 点击:

【HAL库每天一例】系列例程从今天开始持续更新。
我们将坚持每天至少发布一个基于YS-F1Pro开发板的HAL库例程,
该系列例程将带领大家从零开始使用HAL库,后面会持续添加模块应用例程。
同样的,我们还程序发布基于HAL库的指导文档和视频教程,欢迎持续关注,并提出改进意见。
例程下载:
资料包括程序、相关说明资料以及软件使用截图
链接:http://pan.baidu.com/s/1i574oPv
密码:r3s3
(硬石YS-F1Pro开发板HAL库例程持续更新\1. 软件设计之基本裸机例程(HAL库版本)\YSF1_HAL-046. SPI-串行Flash)
/**
  ******************************************************************************
  *                           硬石YS-F1Pro开发板例程功能说明
  *
  *  例程名称: 1. 串行Flash读写测试
  *   
  ******************************************************************************
  * 说明:
  * 本例程配套硬石stm32开发板YS-F1Pro使用。
  *
  * 淘宝:
  * 论坛:www ing10bbs com
  * 版权归硬石嵌入式开发团队所有,请勿商用。
  ******************************************************************************
  */
【1】例程简介
  串行Flash用于存储数据。YS-F1Pro开发板集成了一个16M字节的W25Q128串行Flash芯片,可以
用于存放数据。该芯片使用SPI1通信接口。
  
【2】跳线帽情况
******* 为保证例程正常运行,必须插入以下跳线帽 **********
丝印编号     IO端口      目标功能引脚        出厂默认设置
  JP1        PA10        TXD(CH340G)          已接入
  JP2        PA9         RXD(CH340G)          已接入
  JP3        PB0           LED1               已接入
  JP4        PG6           LED2               已接入
  JP5        PG7           LED3               已接入
  
【3】操作及现象
使用开发板配套的MINI USB线连接到开发板标示“调试串口”字样的MIMI USB接口(需要安装驱
动),在电脑端打开串口调试助手工具,设置参数为115200 8-N-1。下载完程序之后,在串口调试
助手窗口可接收到信息。只有LED1灯亮说明串行Flash读写测试正常。
/******************* (C) COPYRIGHT 2015-2020 硬石嵌入式开发团队 *****END OF FILE****/






bsp_flash.h文件内容

  1. #ifndef __BSP_SPIFLASH_H__
  2. #define __BSP_SPIFLASH_H__

  3. /* 包含头文件 ----------------------------------------------------------------*/
  4. #include "stm32f1xx_hal.h"

  5. /* 类型定义 ------------------------------------------------------------------*/
  6. /* 宏定义 --------------------------------------------------------------------*/
  7. //#define  SPI_FLASH_ID                       0xEF3015     //W25X16   2MB
  8. //#define  SPI_FLASH_ID                       0xEF4015           //W25Q16   4MB
  9. //#define  SPI_FLASH_ID                       0XEF4017     //W25Q64   8MB
  10. #define  SPI_FLASH_ID                       0XEF4018     //W25Q128  16MB YS-F1Pro开发默认使用

  11. #define FLASH_SPIx                                 SPI1
  12. #define FLASH_SPIx_RCC_CLK_ENABLE()                __HAL_RCC_SPI1_CLK_ENABLE()
  13. #define FLASH_SPIx_RCC_CLK_DISABLE()               __HAL_RCC_SPI1_CLK_DISABLE()

  14. #define FLASH_SPI_GPIO_ClK_ENABLE()                __HAL_RCC_GPIOA_CLK_ENABLE()
  15. #define FLASH_SPI_GPIO_PORT                        GPIOA
  16. #define FLASH_SPI_SCK_PIN                          GPIO_PIN_5
  17. #define FLASH_SPI_MISO_PIN                         GPIO_PIN_6
  18. #define FLASH_SPI_MOSI_PIN                         GPIO_PIN_7

  19. #define FLASH_SPI_CS_CLK_ENABLE()                  __HAL_RCC_GPIOA_CLK_ENABLE()   
  20. #define FLASH_SPI_CS_PORT                          GPIOA
  21. #define FLASH_SPI_CS_PIN                           GPIO_PIN_4

  22. #define FLASH_SPI_CS_ENABLE()                      HAL_GPIO_WritePin(FLASH_SPI_CS_PORT, FLASH_SPI_CS_PIN, GPIO_PIN_RESET)
  23. #define FLASH_SPI_CS_DISABLE()                     HAL_GPIO_WritePin(FLASH_SPI_CS_PORT, FLASH_SPI_CS_PIN, GPIO_PIN_SET)

  24. /* 扩展变量 ------------------------------------------------------------------*/
  25. extern SPI_HandleTypeDef hspiflash;

  26. /* 函数声明 ------------------------------------------------------------------*/

  27. void MX_SPIFlash_Init(void);
  28. void SPI_FLASH_SectorErase(uint32_t SectorAddr);
  29. void SPI_FLASH_BulkErase(void);
  30. void SPI_FLASH_PageWrite(uint8_t* pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite);
  31. void SPI_FLASH_BufferWrite(uint8_t* pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite);
  32. void SPI_FLASH_BufferRead(uint8_t* pBuffer, uint32_t ReadAddr, uint16_t NumByteToRead);
  33. uint32_t SPI_FLASH_ReadID(void);
  34. uint32_t SPI_FLASH_ReadDeviceID(void);
  35. void SPI_FLASH_StartReadSequence(uint32_t ReadAddr);
  36. void SPI_Flash_PowerDown(void);
  37. void SPI_Flash_WAKEUP(void);

  38. uint8_t SPI_FLASH_ReadByte(void);
  39. uint8_t SPI_FLASH_SendByte(uint8_t byte);
  40. void SPI_FLASH_WriteEnable(void);
  41. void SPI_FLASH_WaitForWriteEnd(void);

  42. #endif  /* __BSP_SPIFLASH_H__ */

  43. /******************* (C) COPYRIGHT 2015-2020 硬石嵌入式开发团队 *****END OF FILE****/

复制代码


main.c文件内容

  1. /**
  2.   ******************************************************************************
  3.   * 文件名程: main.c
  4.   * 作    者: 硬石嵌入式开发团队
  5.   * 版    本: V1.0
  6.   * 编写日期: 2015-10-04
  7.   * 功    能: 串行Flash驱动实现、读写测试
  8.   ******************************************************************************
  9.   * 说明:
  10.   * 本例程配套硬石stm32开发板YS-F1Pro使用。
  11.   *
  12.   * 淘宝:
  13.   * 论坛:http://www.ing10bbs.com
  14.   * 版权归硬石嵌入式开发团队所有,请勿商用。
  15.   ******************************************************************************
  16.   */
  17. /* 包含头文件 ----------------------------------------------------------------*/
  18. #include "stm32f1xx_hal.h"
  19. #include "usart/bsp_debug_usart.h"
  20. #include "spiflash/bsp_spiflash.h"
  21. #include "led/bsp_led.h"

  22. /* 私有类型定义 --------------------------------------------------------------*/
  23. typedef enum {FAILED = 0, PASSED = !FAILED} TestStatus;

  24. /* 私有宏定义 ----------------------------------------------------------------*/
  25. /* 获取缓冲区的长度 */
  26. #define countof(a)      (sizeof(a) / sizeof(*(a)))
  27. #define TxBufferSize1   (countof(TxBuffer1) - 1)
  28. #define RxBufferSize1   (countof(TxBuffer1) - 1)
  29. #define BufferSize      (countof(Tx_Buffer)-1)

  30. #define  FLASH_WriteAddress     0x00000
  31. #define  FLASH_ReadAddress      FLASH_WriteAddress
  32. #define  FLASH_SectorToErase    FLASH_WriteAddress

  33. /* 私有变量 ------------------------------------------------------------------*/
  34. uint8_t Tx_Buffer[] = " 感谢您选用硬石stm32开发板\n今天是个好日子";
  35. uint8_t Rx_Buffer[BufferSize];

  36. __IO uint32_t DeviceID = 0;
  37. __IO uint32_t FlashID = 0;
  38. __IO TestStatus TransferStatus1 = FAILED;

  39. /* 扩展变量 ------------------------------------------------------------------*/
  40. /* 私有函数原形 --------------------------------------------------------------*/
  41. static TestStatus Buffercmp(uint8_t* pBuffer1, uint8_t* pBuffer2, uint16_t BufferLength);

  42. /* 函数体 --------------------------------------------------------------------*/
  43. /**
  44.   * 函数功能: 系统时钟配置
  45.   * 输入参数: 无
  46.   * 返 回 值: 无
  47.   * 说    明: 无
  48.   */
  49. void SystemClock_Config(void)
  50. {
  51.   RCC_OscInitTypeDef RCC_OscInitStruct;
  52.   RCC_ClkInitTypeDef RCC_ClkInitStruct;

  53.   RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;  // 外部晶振,8MHz
  54.   RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  55.   RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREdiv_div1;
  56.   RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  57.   RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  58.   RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;  // 9倍频,得到72MHz主时钟
  59.   HAL_RCC_OscConfig(&RCC_OscInitStruct);

  60.   RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
  61.                               |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  62.   RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;       // 系统时钟:72MHz
  63.   RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_div1;              // AHB时钟:72MHz
  64.   RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_div2;               // APB1时钟:36MHz
  65.   RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_div1;               // APB2时钟:72MHz
  66.   HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2);

  67.          // HAL_RCC_GetHCLKFreq()/1000    1ms中断一次
  68.         // HAL_RCC_GetHCLKFreq()/100000         10us中断一次
  69.         // HAL_RCC_GetHCLKFreq()/1000000 1us中断一次
  70.   HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);  // 配置并启动系统滴答定时器
  71.   /* 系统滴答定时器时钟源 */
  72.   HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
  73.   /* 系统滴答定时器中断优先级配置 */
  74.   HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
  75. }

  76. /**
  77.   * 函数功能: 主函数.
  78.   * 输入参数: 无
  79.   * 返 回 值: 无
  80.   * 说    明: 无
  81.   */
  82. int main(void)
  83. {  
  84.   /* 复位所有外设,初始化Flash接口和系统滴答定时器 */
  85.   HAL_Init();
  86.   /* 配置系统时钟 */
  87.   SystemClock_Config();

  88.   /* LED灯初始化 */
  89.   LED_GPIO_Init();
  90.   
  91.   /* 初始化串口并配置串口中断优先级 */
  92.   MX_DEBUG_USART_Init();
  93.   /* 调用格式化输出函数打印输出数据 */
  94.   printf("这是一个16M byte串行flash(W25Q128)读写测试实验\n");
  95.   
  96.   MX_SPIFlash_Init();
  97.   
  98.   /* Get SPI Flash Device ID */
  99.         DeviceID = SPI_FLASH_ReadDeviceID();
  100.   
  101.   HAL_Delay(100);
  102.   
  103.   /* Get SPI Flash ID */
  104.         FlashID = SPI_FLASH_ReadID();
  105.   
  106.   printf("FlashID is 0x%X,  Manufacturer Device ID is 0x%X\n", FlashID, DeviceID);
  107.         
  108.         /* Check the SPI Flash ID */
  109.         if (FlashID == SPI_FLASH_ID)  /* #define  sFLASH_ID  0XEF4018 */
  110.         {        
  111.                 printf("检测到华邦串行flash W25Q128 !\n");
  112.                
  113.                 /* 擦除SPI的扇区以写入 */
  114.                 SPI_FLASH_SectorErase(FLASH_SectorToErase);                  
  115.                
  116.                 /* 将发送缓冲区的数据写到flash中 */         
  117.                 SPI_FLASH_BufferWrite(Tx_Buffer, FLASH_WriteAddress, BufferSize);
  118.                 SPI_FLASH_BufferWrite(Tx_Buffer, 252, BufferSize);
  119.                 printf("写入的数据为:\n%s \n", Tx_Buffer);
  120.                
  121.                 /* 将刚刚写入的数据读出来放到接收缓冲区中 */
  122.                 SPI_FLASH_BufferRead(Rx_Buffer, FLASH_ReadAddress, BufferSize);
  123.                 printf("读出的数据为:\n %s\n", Rx_Buffer);
  124.                
  125.                 /* 检查写入的数据与读出的数据是否相等 */
  126.                 TransferStatus1 = Buffercmp(Tx_Buffer, Rx_Buffer, BufferSize);
  127.                
  128.                 if( PASSED == TransferStatus1 )
  129.                 {   
  130.                         printf("16M串行flash(W25Q128)测试成功!\r");
  131.                         LED1_ON;
  132.                 }
  133.                 else
  134.                 {        
  135.                         printf("16M串行flash(W25Q128)测试失败!\r");
  136.                         LED2_ON;
  137.                 }
  138.         }
  139.         else
  140.         {   
  141.                 printf("获取不到 W25Q128 ID!\n");
  142.                 LED3_ON;
  143.         }
  144.   
  145.   /* 无限循环 */
  146.   while (1)
  147.   {
  148.   }
  149. }

  150. /**
  151.   * 函数功能: 比较两个缓冲区中的数据是否相等
  152.   * 输入参数: pBuffer1:要比较的缓冲区1的指针
  153.   *           pBuffer2:要比较的缓冲区2的指针
  154.   *           BufferLength:缓冲区长度
  155.   * 返 回 值: PASSED:相等
  156.   *           FAILED:不等
  157.   * 说    明: 无
  158.   */
  159. static TestStatus Buffercmp(uint8_t* pBuffer1, uint8_t* pBuffer2, uint16_t BufferLength)
  160. {
  161.   while(BufferLength--)
  162.   {
  163.     if(*pBuffer1 != *pBuffer2)
  164.     {
  165.       return FAILED;
  166.     }

  167.     pBuffer1++;
  168.     pBuffer2++;
  169.   }
  170.   return PASSED;
  171. }

  172. /******************* (C) COPYRIGHT 2015-2020 硬石嵌入式开发团队 *****END OF FILE****/

复制代码




Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top