搜索

[RISC-V MCU 应用开发] 【RISC-V MCU CH32V103测评】W25Q16 Flash存储器 Raw数据读写

[复制链接]
254|2
 楼主 | 2020-12-3 22:07 | 显示全部楼层 |阅读模式
参考了不少前辈的例程,实践了一下。

测试效果如图所示:


主要更改3个源码文件,2个SPI Flash访问驱动,1个main函数,全部列在此处。
Hardware/spiflash.c
  1. /*****************************************
  2. *@Note
  3. Winbond W25Qxx SPIFLASH
  4. pins:
  5. CS   —— PA2
  6. DO   —— PA6(SPI1_MISO)
  7. WP   —— 3.3V
  8. DI   —— PA7(SPI1_MOSI)
  9. CLK  —— PA5(SPI1_SCK)
  10. HOLD —— 3.3V
  11. *******************************************/
  12. #include "debug.h"
  13. #include "string.h"
  14. #include "spiflash.h"

  15. /* Global define */

  16. /* Global Variable */
  17. u8 SPI_FLASH_BUF[4096];

  18. /*******************************************************************************
  19. * Function Name  : SPI1_ReadWriteByte
  20. * Description    : SPI1 read or write one byte.
  21. * Input          : TxData: write one byte data.
  22. * Return         : Read one byte data.
  23. *******************************************************************************/
  24. u8 SPI1_ReadWriteByte(u8 TxData)
  25. {
  26.     u8 i = 0;

  27.     while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET)
  28.     {
  29.         i++;
  30.         if (i > 200)
  31.             return 0;
  32.     }

  33.     SPI_I2S_SendData(SPI1, TxData);
  34.     i = 0;

  35.     while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET)
  36.     {
  37.         i++;
  38.         if (i > 200)
  39.             return 0;
  40.     }

  41.     return SPI_I2S_ReceiveData(SPI1);
  42. }

  43. /*******************************************************************************
  44. * Function Name  : SPI_Flash_Init
  45. * Description    : Configuring the SPI for operation flash.
  46. * Input          : None
  47. * Return         : None
  48. *******************************************************************************/
  49. void SPI_Flash_Init(void)
  50. {
  51.     GPIO_InitTypeDef GPIO_InitStructure;
  52.     SPI_InitTypeDef SPI_InitStructure;

  53.     RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA | RCC_APB2Periph_SPI1, ENABLE);

  54.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
  55.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  56.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  57.     GPIO_Init(GPIOA, &GPIO_InitStructure);
  58.     GPIO_SetBits(GPIOA, GPIO_Pin_2);

  59.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
  60.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  61.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  62.     GPIO_Init( GPIOA, &GPIO_InitStructure);

  63.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
  64.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  65.     GPIO_Init( GPIOA, &GPIO_InitStructure);

  66.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
  67.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  68.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  69.     GPIO_Init( GPIOA, &GPIO_InitStructure);

  70.     SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
  71.     SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
  72.     SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
  73.     SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;
  74.     SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
  75.     SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
  76.     SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;
  77.     SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
  78.     SPI_InitStructure.SPI_CRCPolynomial = 7;
  79.     SPI_Init(SPI1, &SPI_InitStructure);

  80.     SPI_Cmd(SPI1, ENABLE);
  81. }

  82. /*******************************************************************************
  83. * Function Name  : SPI_Flash_ReadSR
  84. * Description    : Read W25Qxx status register.
  85. *       ——BIT7  6   5   4   3   2   1   0
  86. *       ——SPR   RV  TB  BP2 BP1 BP0 WEL BUSY
  87. * Input          : None
  88. * Return         : byte: status register value.
  89. *******************************************************************************/
  90. u8 SPI_Flash_ReadSR(void)
  91. {
  92.     u8 byte = 0;

  93.     GPIO_WriteBit(GPIOA, GPIO_Pin_2, 0);
  94.     SPI1_ReadWriteByte(W25X_ReadStatusReg);
  95.     byte = SPI1_ReadWriteByte(0Xff);
  96.     GPIO_WriteBit(GPIOA, GPIO_Pin_2, 1);

  97.     return byte;
  98. }

  99. /*******************************************************************************
  100. * Function Name  : SPI_FLASH_Write_SR
  101. * Description    : Write W25Qxx status register.
  102. * Input          : sr:status register value.
  103. * Return         : None
  104. *******************************************************************************/
  105. void SPI_FLASH_Write_SR(u8 sr)
  106. {
  107.     GPIO_WriteBit(GPIOA, GPIO_Pin_2, 0);
  108.     SPI1_ReadWriteByte(W25X_WriteStatusReg);
  109.     SPI1_ReadWriteByte(sr);
  110.     GPIO_WriteBit(GPIOA, GPIO_Pin_2, 1);
  111. }

  112. /*******************************************************************************
  113. * Function Name  : SPI_Flash_Wait_Busy
  114. * Description    : Wait flash free.
  115. * Input          : None
  116. * Return         : None
  117. *******************************************************************************/
  118. void SPI_Flash_Wait_Busy(void)
  119. {
  120.     while ((SPI_Flash_ReadSR() & 0x01) == 0x01)
  121.         ;
  122. }

  123. /*******************************************************************************
  124. * Function Name  : SPI_FLASH_Write_Enable
  125. * Description    : Enable flash write.
  126. * Input          : None
  127. * Return         : None
  128. *******************************************************************************/
  129. void SPI_FLASH_Write_Enable(void)
  130. {
  131.     GPIO_WriteBit(GPIOA, GPIO_Pin_2, 0);
  132.     SPI1_ReadWriteByte(W25X_WriteEnable);
  133.     GPIO_WriteBit(GPIOA, GPIO_Pin_2, 1);
  134. }

  135. /*******************************************************************************
  136. * Function Name  : SPI_FLASH_Write_Disable
  137. * Description    : Disable flash write.
  138. * Input          : None
  139. * Return         : None
  140. *******************************************************************************/
  141. void SPI_FLASH_Write_Disable(void)
  142. {
  143.     GPIO_WriteBit(GPIOA, GPIO_Pin_2, 0);
  144.     SPI1_ReadWriteByte(W25X_WriteDisable);
  145.     GPIO_WriteBit(GPIOA, GPIO_Pin_2, 1);
  146. }

  147. /*******************************************************************************
  148. * Function Name  : SPI_Flash_ReadID
  149. * Description    : Read flash ID.
  150. * Input          : None
  151. * Return         : Temp: FLASH ID.
  152. *******************************************************************************/
  153. u16 SPI_Flash_ReadID(void)
  154. {
  155.     u16 Temp = 0;

  156.     GPIO_WriteBit(GPIOA, GPIO_Pin_2, 0);
  157.     SPI1_ReadWriteByte(W25X_ManufactDeviceID);
  158.     SPI1_ReadWriteByte(0x00);
  159.     SPI1_ReadWriteByte(0x00);
  160.     SPI1_ReadWriteByte(0x00);
  161.     Temp |= SPI1_ReadWriteByte(0xFF) << 8;
  162.     Temp |= SPI1_ReadWriteByte(0xFF);
  163.     GPIO_WriteBit(GPIOA, GPIO_Pin_2, 1);

  164.     return Temp;
  165. }

  166. /*******************************************************************************
  167. * Function Name  : SPI_Flash_Erase_Sector
  168. * Description    : Erase one sector(4Kbyte).
  169. * Input          : Dst_Addr:  0 —— 2047
  170. * Return         : None
  171. *******************************************************************************/
  172. void SPI_Flash_Erase_Sector(u32 Dst_Addr)
  173. {
  174.     Dst_Addr *= 4096;
  175.     SPI_FLASH_Write_Enable();
  176.     SPI_Flash_Wait_Busy();
  177.     GPIO_WriteBit(GPIOA, GPIO_Pin_2, 0);
  178.     SPI1_ReadWriteByte(W25X_SectorErase);
  179.     SPI1_ReadWriteByte((u8) ((Dst_Addr) >> 16));
  180.     SPI1_ReadWriteByte((u8) ((Dst_Addr) >> 8));
  181.     SPI1_ReadWriteByte((u8) Dst_Addr);
  182.     GPIO_WriteBit(GPIOA, GPIO_Pin_2, 1);
  183.     SPI_Flash_Wait_Busy();
  184. }

  185. /*******************************************************************************
  186. * Function Name  : SPI_Flash_Read
  187. * Description    : Read data from flash.
  188. * Input          : pBuffer:
  189. *                  ReadAddr:Initial address(24bit).
  190. *                  size: Data length.
  191. * Return         : None
  192. *******************************************************************************/
  193. void SPI_Flash_Read(u8* pBuffer, u32 ReadAddr, u16 size)
  194. {
  195.     u16 i;

  196.     GPIO_WriteBit(GPIOA, GPIO_Pin_2, 0);
  197.     SPI1_ReadWriteByte(W25X_ReadData);
  198.     SPI1_ReadWriteByte((u8) ((ReadAddr) >> 16));
  199.     SPI1_ReadWriteByte((u8) ((ReadAddr) >> 8));
  200.     SPI1_ReadWriteByte((u8) ReadAddr);

  201.     for (i = 0; i < size; i++)
  202.     {
  203.         pBuffer[i] = SPI1_ReadWriteByte(0XFF);
  204.     }

  205.     GPIO_WriteBit(GPIOA, GPIO_Pin_2, 1);
  206. }

  207. /*******************************************************************************
  208. * Function Name  : SPI_Flash_Write_Page
  209. * Description    : Write data by one page.
  210. * Input          : pBuffer:
  211. *                  WriteAddr:Initial address(24bit).
  212. *                  size:Data length.
  213. * Return         : None
  214. *******************************************************************************/
  215. void SPI_Flash_Write_Page(u8* pBuffer, u32 WriteAddr, u16 size)
  216. {
  217.     u16 i;

  218.     SPI_FLASH_Write_Enable();
  219.     GPIO_WriteBit(GPIOA, GPIO_Pin_2, 0);
  220.     SPI1_ReadWriteByte(W25X_PageProgram);
  221.     SPI1_ReadWriteByte((u8) ((WriteAddr) >> 16));
  222.     SPI1_ReadWriteByte((u8) ((WriteAddr) >> 8));
  223.     SPI1_ReadWriteByte((u8) WriteAddr);

  224.     for (i = 0; i < size; i++)
  225.     {
  226.         SPI1_ReadWriteByte(pBuffer[i]);
  227.     }

  228.     GPIO_WriteBit(GPIOA, GPIO_Pin_2, 1);
  229.     SPI_Flash_Wait_Busy();
  230. }

  231. /*******************************************************************************
  232. * Function Name  : SPI_Flash_Write_NoCheck
  233. * Description    : Write data to flash.(need Erase)
  234. *                  All data in address rang is 0xFF.
  235. * Input          : pBuffer:
  236. *                  WriteAddr: Initial address(24bit).
  237. *                  size: Data length.
  238. * Return         : None
  239. *******************************************************************************/
  240. void SPI_Flash_Write_NoCheck(u8* pBuffer, u32 WriteAddr, u16 size)
  241. {
  242.     u16 pageremain;

  243.     pageremain = 256 - WriteAddr % 256;

  244.     if (size <= pageremain)
  245.         pageremain = size;

  246.     while (1)
  247.     {
  248.         SPI_Flash_Write_Page(pBuffer, WriteAddr, pageremain);

  249.         if (size == pageremain)
  250.         {
  251.             break;
  252.         }
  253.         else
  254.         {
  255.             pBuffer += pageremain;
  256.             WriteAddr += pageremain;
  257.             size -= pageremain;

  258.             if (size > 256)
  259.                 pageremain = 256;
  260.             else
  261.                 pageremain = size;
  262.         }
  263.     }
  264. }

  265. /*******************************************************************************
  266. * Function Name  : SPI_Flash_Write
  267. * Description    : Write data to flash.(no need Erase)
  268. * Input          : pBuffer:
  269. *                  WriteAddr: Initial address(24bit).
  270. *                  size: Data length.
  271. * Return         : None
  272. *******************************************************************************/
  273. void SPI_Flash_Write(u8* pBuffer, u32 WriteAddr, u16 size)
  274. {
  275.     u32 secpos;
  276.     u16 secoff;
  277.     u16 secremain;
  278.     u16 i;

  279.     secpos = WriteAddr / 4096;
  280.     secoff = WriteAddr % 4096;
  281.     secremain = 4096 - secoff;

  282.     if (size <= secremain)
  283.         secremain = size;

  284.     while (1)
  285.     {
  286.         SPI_Flash_Read(SPI_FLASH_BUF, secpos * 4096, 4096);

  287.         for (i = 0; i < secremain; i++)
  288.         {
  289.             if (SPI_FLASH_BUF[secoff + i] != 0XFF)
  290.                 break;
  291.         }

  292.         if (i < secremain)
  293.         {
  294.             SPI_Flash_Erase_Sector(secpos);

  295.             for (i = 0; i < secremain; i++)
  296.             {
  297.                 SPI_FLASH_BUF[i + secoff] = pBuffer[i];
  298.             }

  299.             SPI_Flash_Write_NoCheck(SPI_FLASH_BUF, secpos * 4096, 4096);

  300.         }
  301.         else
  302.         {
  303.             SPI_Flash_Write_NoCheck(pBuffer, WriteAddr, secremain);
  304.         }

  305.         if (size == secremain)
  306.         {
  307.             break;
  308.         }
  309.         else
  310.         {
  311.             secpos++;
  312.             secoff = 0;

  313.             pBuffer += secremain;
  314.             WriteAddr += secremain;
  315.             size -= secremain;

  316.             if (size > 4096)
  317.             {
  318.                 secremain = 4096;
  319.             }
  320.             else
  321.             {
  322.                 secremain = size;
  323.             }
  324.         }
  325.     }
  326. }

  327. /*******************************************************************************
  328. * Function Name  : SPI_Flash_Erase_Chip
  329. * Description    : Erase all FLASH pages.
  330. * Input          : None
  331. * Return         : None
  332. *******************************************************************************/
  333. void SPI_Flash_Erase_Chip(void)
  334. {
  335.     SPI_FLASH_Write_Enable();
  336.     SPI_Flash_Wait_Busy();
  337.     GPIO_WriteBit(GPIOA, GPIO_Pin_2, 0);
  338.     SPI1_ReadWriteByte(W25X_ChipErase);
  339.     GPIO_WriteBit(GPIOA, GPIO_Pin_2, 1);
  340.     SPI_Flash_Wait_Busy();
  341. }

  342. /*******************************************************************************
  343. * Function Name  : SPI_Flash_PowerDown
  344. * Description    : Enter power down mode.
  345. * Input          : None
  346. * Return         : None
  347. *******************************************************************************/
  348. void SPI_Flash_PowerDown(void)
  349. {
  350.     GPIO_WriteBit(GPIOA, GPIO_Pin_2, 0);
  351.     SPI1_ReadWriteByte(W25X_PowerDown);
  352.     GPIO_WriteBit(GPIOA, GPIO_Pin_2, 1);
  353.     Delay_Us(3);
  354. }

  355. /*******************************************************************************
  356. * Function Name  : SPI_Flash_WAKEUP
  357. * Description    : Power down wake up.
  358. * Input          : None
  359. * Return         : None
  360. *******************************************************************************/
  361. void SPI_Flash_WAKEUP(void)
  362. {
  363.     GPIO_WriteBit(GPIOA, GPIO_Pin_2, 0);
  364.     SPI1_ReadWriteByte(W25X_ReleasePowerDown);
  365.     GPIO_WriteBit(GPIOA, GPIO_Pin_2, 1);
  366.     Delay_Us(3);
  367. }
复制代码


Hardware/spiflash.h
  1. #ifndef __SPIFLASH_H
  2. #define __SPIFLASH_H


  3. /* Winbond SPIFalsh ID */
  4. #define W25Q80  0XEF13
  5. #define W25Q16  0XEF14
  6. #define W25Q32  0XEF15
  7. #define W25Q64  0XEF16
  8. #define W25Q128 0XEF17

  9. /* Winbond SPIFalsh Instruction List */
  10. #define W25X_WriteEnable            0x06
  11. #define W25X_WriteDisable           0x04
  12. #define W25X_ReadStatusReg          0x05
  13. #define W25X_WriteStatusReg         0x01
  14. #define W25X_ReadData               0x03
  15. #define W25X_FastReadData           0x0B
  16. #define W25X_FastReadDual           0x3B
  17. #define W25X_PageProgram            0x02
  18. #define W25X_BlockErase             0xD8
  19. #define W25X_SectorErase            0x20
  20. #define W25X_ChipErase              0xC7
  21. #define W25X_PowerDown              0xB9
  22. #define W25X_ReleasePowerDown       0xAB
  23. #define W25X_DeviceID               0xAB
  24. #define W25X_ManufactDeviceID       0x90
  25. #define W25X_JedecDeviceID          0x9F

  26. u8 SPI1_ReadWriteByte(u8 TxData);
  27. void SPI_Flash_Init(void);
  28. u8 SPI_Flash_ReadSR(void);
  29. void SPI_FLASH_Write_SR(u8 sr);
  30. void SPI_Flash_Wait_Busy(void);
  31. void SPI_FLASH_Write_Enable(void);
  32. void SPI_FLASH_Write_Disable(void);
  33. u16 SPI_Flash_ReadID(void);
  34. void SPI_Flash_Erase_Sector(u32 Dst_Addr);
  35. void SPI_Flash_Read(u8* pBuffer,u32 ReadAddr,u16 size);
  36. void SPI_Flash_Write_Page(u8* pBuffer,u32 WriteAddr,u16 size);
  37. void SPI_Flash_Write_NoCheck(u8* pBuffer,u32 WriteAddr,u16 size);
  38. void SPI_Flash_Write(u8* pBuffer,u32 WriteAddr,u16 size);
  39. void SPI_Flash_Erase_Chip(void);
  40. void SPI_Flash_PowerDown(void);
  41. void SPI_Flash_WAKEUP(void);

  42. #endif

复制代码


main.c
  1. /********************************** (C) COPYRIGHT *******************************
  2. * File Name          : main.c
  3. * Author             : WCH
  4. * Version            : V1.0.0
  5. * Date               : 2020/04/30
  6. * Description        : Main program body.
  7. *******************************************************************************/

  8. /*
  9. *@Note
  10. W25Q16串行 Flash存储器 Raw数据读写测试例程。
  11. */

  12. #pragma message("short-cut R11 before programming")

  13. #include <string.h>
  14. #include "debug.h"
  15. #include "../Hardware/spiflash.h"

  16. /* Global typedef */

  17. /* Global define */

  18. /* Global Variable */
  19. const u8 TEXT_Buf[] =
  20. { "CH32F103C8T6 SPI FLASH W25Qxx Read/Write raw data buffer content" };

  21. #define SIZE sizeof(TEXT_Buf)

  22. /*******************************************************************************
  23. * Function Name  : main
  24. * Description    : Main program.
  25. * Input          : None
  26. * Return         : None
  27. *******************************************************************************/
  28. int main(void)
  29. {
  30.     u8 datap[SIZE] =
  31.     { };
  32.     u16 Flash_Model = 0;

  33.     Delay_Init();
  34.     USART_Printf_Init(115200);
  35.     printf("SystemClk: %d\r\n", SystemCoreClock);

  36.     SPI_Flash_Init();

  37.     Flash_Model = SPI_Flash_ReadID();
  38.     printf("Flash_Model:%x\r\n", Flash_Model);
  39.     switch (Flash_Model)
  40.     {
  41.     case W25Q80:
  42.         printf("W25Q80 OK!\r\n");
  43.         break;

  44.     case W25Q16:
  45.         printf("W25Q16 OK!\r\n");
  46.         break;

  47.     case W25Q32:
  48.         printf("W25Q32 OK!\r\n");
  49.         break;

  50.     case W25Q64:
  51.         printf("W25Q64 OK!\r\n");
  52.         break;

  53.     case W25Q128:
  54.         printf("W25Q128 OK!\r\n");
  55.         break;

  56.     default:
  57.         printf("Failed!\r\n");
  58.         break;
  59.     }

  60.     printf("Start Erase W25Qxx ...\r\n");
  61.     SPI_Flash_Erase_Sector(0);
  62.     printf("W25Qxx Erase Finished!\r\n");

  63.     Delay_Ms(500);
  64.     printf("Start Read W25Qxx ...\r\n");
  65.     SPI_Flash_Read(datap, 0x0, SIZE);
  66.     printf("%s\r\n", datap);

  67.     Delay_Ms(500);
  68.     printf("Start Write W25Qxx ...\r\n");
  69.     SPI_Flash_Write((u8*) TEXT_Buf, 0, SIZE);
  70.     printf("W25Qxx Write Finished!\r\n");

  71.     Delay_Ms(500);
  72.     printf("Start Read W25Qxx ...\r\n");
  73.     SPI_Flash_Read(datap, 0x0, SIZE);
  74.     printf("%s\r\n", datap);

  75.     while (1)
  76.     {
  77.         Delay_Ms(1000);

  78.         printf("Start Read W25Qxx ...\r\n");
  79.         SPI_Flash_Read(datap, 0x0, SIZE);
  80.         printf("%s\r\n", datap);
  81.     }

  82.     return 0;
  83. }

复制代码


完整代码打包在此:

W25Q16.png

W25Q16.zip

140.24 KB, 下载次数: 5

使用特权

评论回复
| 2020-12-4 22:23 | 显示全部楼层
赞一个,辛苦了楼主

使用特权

评论回复
| 2020-12-7 16:37 | 显示全部楼层
赞楼主,正准备试用在这个芯片

使用特权

评论回复
扫描二维码,随时随地手机跟帖
您需要登录后才可以回帖 登录 | 注册

本版积分规则

我要发帖 我要提问 投诉建议 申请版主

快速回复

您需要登录后才可以回帖
登录 | 注册
高级模式

论坛热帖

关闭

热门推荐上一条 /5 下一条

在线客服 快速回复 返回顶部 返回列表