[单片机芯片] [沁恒CH32V17测评]SPI功能测试读写W25Q64

[复制链接]
533|0
abner_ma 发表于 2025-8-31 18:09 | 显示全部楼层 |阅读模式
   CH32V307 是沁恒(WCH)推出的基于 RISCV 内核的高性能 MCU,其集成的 SPI(串行外设接口)模块具备高速、多主从模式、灵活数据格式等特性,可满足工业控制、通信传输、存储扩展等多种场景下的外设互联需求。
Q2.png
Q3.png

一、CH32V317 的 SPI核心功能。CH32V307 /317 的 SPI 模块支持 主模式(Master) 和 从模式(Slave),可实现 一主多从或多主多从的拓扑结构,核心功能包括:
1.数据同步传输:通过 SCK(串行时钟)、MOSI(主发从收)、MISO(主收从发)三线同步传输数据,时钟速率可灵活配置;
2.片选控制:支持硬件 NSS(从机选择)引脚或软件模拟片选,方便管理多个从设备(如多片 SPI 闪存、ADC 等);
3.数据帧灵活配置:支持 8 位或 16 位数据帧长度,满足不同外设的数据宽度需求;
4.全双工/半双工/ simplex 模式:默认全双工(MOSI/MISO 同时传输),可配置为半双工(单线路双向传输)或 simplex(仅发送/仅接收),适配不同通信场景
二、关键工作特性
1. 高速传输性能
   最高 SCK 时钟频率可达 45MHz(基于 CH32V307 最高 144MHz 系统主频,时钟分频系数可配置为 2/4/8/16/32/64/128);
   支持 SPI 模式 0~3(通过时钟极性 CPOL 和时钟相位 CPHA 组合配置),兼容绝大多数 SPI 外设(如 Flash、OLED、传感器等)。
2. 中断与 DMA 支持
    中断机制:支持发送缓冲区空、接收缓冲区满、传输完成、错误(如 CRC 错误、溢出错误)等中断,可通过中断服务函数实时处理数据传输;
    DMA 功能:SPI 可与片内 DMA 控制器联动,实现无 CPU 干预的高速数据传输,减少内核负担,适合大数据量连续传输场景(如高速 ADC 数据采集、批量数据存储)。
3. 数据安全性与校验
     集成 CRC 循环冗余校验 模块,支持对发送/接收数据自动计算 CRC 值,可用于校验数据传输完整性(如与具备 CRC 功能的外设配合,提升通信可靠性);
     支持 SSM(软件从机管理)模式:可通过软件控制 NSS 引脚电平,灵活管理从机使能/禁用,避免硬件 NSS 引脚的限制。
4. 多 SPI 实例与引脚复用
    CH32V307 通常集成 2~3 个独立 SPI 外设(具体数量需参考芯片手册,如 CH32V307VCT6 含 SPI1、SPI2、SPI3),可同时连接多个不同类型的 SPI 设备;
     支持 引脚复用:SPI 引脚(SCK、MOSI、MISO、NSS)可映射到不同 GPIO 引脚,方便 PCB 布局设计。
三、典型应用场景
1. 存储扩展:连接 SPI Flash(如 W25Q 系列)、SPI EEPROM,实现程序存储或数据缓存;
2. 显示控制:驱动 SPI 接口的 OLED 显示屏(如 128x64 OLED)、TFT 屏(需配合显示控制器);
3. 传感器通信:与 SPI 接口的传感器(如加速度计 ADXL345、温湿度传感器 SHT3x、ADC 芯片 ADS1256)通信,采集数据;
4. 工业控制:连接 SPI 接口的 PLC 模块、变频器、编码器,实现工业设备间的同步数据传输;
5. 外设桥接:通过 SPI 与其他通信模块(如 SPItoUART 芯片、SPItoCAN 芯片)配合,扩展通信接口。

  下面进行实际测试,读写SPI Flash( W25Q 系列)实现程序存储或数据缓存,链接图
Q7.png
程序编写流程如下:
1 .初始化:初始化系统时钟、延时函数、调试串口和 SPI 外设。
2.识别 Flash:读取 Flash 的器件 ID,并打印其型号。
3.擦除测试:擦除 Flash 的第 0 个扇区(4KB)。
4.读取验证:读取刚擦除的扇区,确认数据全为 0xFF。
5.写入数据:将字符串 "CH32F103 SPI FLASH W25Qxx" 写入 Flash 的起始地址。
6..读取验证:再次从 Flash 起始地址读取数据,并打印出来,以验证写入是否成功。
  1. /*
  2. Master:SPI1_SCK(PA5)、SPI1_MISO(PA6)、SPI1_MOSI(PA7)。
  3. 本例程演示 SPI 操作 Winbond W25Qxx SPIFLASH。
  4. 注:
  5. pins:
  6. CS —— PA2
  7. DO —— PA6(SPI1_MISO)
  8. WP —— 3.3V
  9. DI —— PA7(SPI1_MOSI)
  10. CLK —— PA5(SPI1_SCK)
  11. HOLD —— 3.3V

  12. */

  13. #include "debug.h"
  14. #include "string.h"

  15. /* Winbond SPIFalsh ID */
  16. #define W25Q80 0XEF13
  17. #define W25Q16 0XEF14
  18. #define W25Q32 0XEF15
  19. #define W25Q64 0XEF16
  20. #define W25Q128 0XEF17

  21. /* Winbond SPIFalsh Instruction List */
  22. #define W25X_WriteEnable 0x06
  23. #define W25X_WriteDisable 0x04
  24. #define W25X_ReadStatusReg 0x05
  25. #define W25X_WriteStatusReg 0x01
  26. #define W25X_ReadData 0x03
  27. #define W25X_FastReadData 0x0B
  28. #define W25X_FastReadDual 0x3B
  29. #define W25X_PageProgram 0x02
  30. #define W25X_BlockErase 0xD8
  31. #define W25X_SectorErase 0x20
  32. #define W25X_ChipErase 0xC7
  33. #define W25X_PowerDown 0xB9
  34. #define W25X_ReleasePowerDown 0xAB
  35. #define W25X_DeviceID 0xAB
  36. #define W25X_ManufactDeviceID 0x90
  37. #define W25X_JedecDeviceID 0x9F

  38. /* Global define */

  39. /* Global Variable */
  40. u8 SPI_FLASH_BUF[4096];
  41. const u8 TEXT_Buf[] = {"I LOVE CHINA,I LOVE bbs.21ic.com too! "};
  42. #define SIZE sizeof(TEXT_Buf)

  43. /*********************************************************************
  44. * @fn SPI1_ReadWriteByte
  45. *
  46. * [url=/u/brief]@brief[/url] SPI1 read or write one byte.
  47. *
  48. * @param TxData - write one byte data.
  49. *
  50. * [url=/u/return]@return[/url] Read one byte data.
  51. */
  52. u8 SPI1_ReadWriteByte(u8 TxData)
  53. {
  54. u8 i = 0;

  55. while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET)
  56. {
  57. i++;
  58. if(i > 200)
  59. return 0;
  60. }

  61. SPI_I2S_SendData(SPI1, TxData);
  62. i = 0;

  63. while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET)
  64. {
  65. i++;
  66. if(i > 200)
  67. return 0;
  68. }

  69. return SPI_I2S_ReceiveData(SPI1);
  70. }

  71. /*********************************************************************
  72. * @fn SPI_Flash_Init
  73. *
  74. * @brief Configuring the SPI for operation flash.
  75. *
  76. * @return none
  77. */
  78. void SPI_Flash_Init(void)
  79. {
  80. GPIO_InitTypeDef GPIO_InitStructure = {0};
  81. SPI_InitTypeDef SPI_InitStructure = {0};

  82. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_SPI1, ENABLE);

  83. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
  84. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  85. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  86. GPIO_Init(GPIOA, &GPIO_InitStructure);
  87. GPIO_SetBits(GPIOA, GPIO_Pin_2);

  88. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
  89. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  90. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  91. GPIO_Init(GPIOA, &GPIO_InitStructure);

  92. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
  93. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  94. GPIO_Init(GPIOA, &GPIO_InitStructure);

  95. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
  96. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  97. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  98. GPIO_Init(GPIOA, &GPIO_InitStructure);

  99. SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
  100. SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
  101. SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
  102. SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;
  103. SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
  104. SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
  105. SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;
  106. SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
  107. SPI_InitStructure.SPI_CRCPolynomial = 7;
  108. SPI_Init(SPI1, &SPI_InitStructure);

  109. SPI_Cmd(SPI1, ENABLE);
  110. }

  111. /*********************************************************************
  112. * @fn SPI_Flash_ReadSR
  113. *
  114. * @brief Read W25Qxx status register.
  115. * ——BIT7 6 5 4 3 2 1 0
  116. * ——SPR RV TB BP2 BP1 BP0 WEL BUSY
  117. *
  118. * @return byte - status register value.
  119. */
  120. u8 SPI_Flash_ReadSR(void)
  121. {
  122. u8 byte = 0;

  123. GPIO_WriteBit(GPIOA, GPIO_Pin_2, 0);
  124. SPI1_ReadWriteByte(W25X_ReadStatusReg);
  125. byte = SPI1_ReadWriteByte(0Xff);
  126. GPIO_WriteBit(GPIOA, GPIO_Pin_2, 1);

  127. return byte;
  128. }

  129. /*********************************************************************
  130. * @fn SPI_FLASH_Write_SR
  131. *
  132. * @brief Write W25Qxx status register.
  133. *
  134. * @param sr - status register value.
  135. *
  136. * @return none
  137. */
  138. void SPI_FLASH_Write_SR(u8 sr)
  139. {
  140. GPIO_WriteBit(GPIOA, GPIO_Pin_2, 0);
  141. SPI1_ReadWriteByte(W25X_WriteStatusReg);
  142. SPI1_ReadWriteByte(sr);
  143. GPIO_WriteBit(GPIOA, GPIO_Pin_2, 1);
  144. }

  145. /*********************************************************************
  146. * @fn SPI_Flash_Wait_Busy
  147. *
  148. * @brief Wait flash free.
  149. *
  150. * @return none
  151. */
  152. void SPI_Flash_Wait_Busy(void)
  153. {
  154. while((SPI_Flash_ReadSR() & 0x01) == 0x01)
  155. ;
  156. }

  157. /*********************************************************************
  158. * @fn SPI_FLASH_Write_Enable
  159. *
  160. * @brief Enable flash write.
  161. *
  162. * @return none
  163. */
  164. void SPI_FLASH_Write_Enable(void)
  165. {
  166. GPIO_WriteBit(GPIOA, GPIO_Pin_2, 0);
  167. SPI1_ReadWriteByte(W25X_WriteEnable);
  168. GPIO_WriteBit(GPIOA, GPIO_Pin_2, 1);
  169. }

  170. /*********************************************************************
  171. * @fn SPI_FLASH_Write_Disable
  172. *
  173. * @brief Disable flash write.
  174. *
  175. * @return none
  176. */
  177. void SPI_FLASH_Write_Disable(void)
  178. {
  179. GPIO_WriteBit(GPIOA, GPIO_Pin_2, 0);
  180. SPI1_ReadWriteByte(W25X_WriteDisable);
  181. GPIO_WriteBit(GPIOA, GPIO_Pin_2, 1);
  182. }

  183. /*********************************************************************
  184. * @fn SPI_Flash_ReadID
  185. *
  186. * @brief Read flash ID.
  187. *
  188. * @return Temp - FLASH ID.
  189. */
  190. u16 SPI_Flash_ReadID(void)
  191. {
  192. u16 Temp = 0;

  193. GPIO_WriteBit(GPIOA, GPIO_Pin_2, 0);
  194. SPI1_ReadWriteByte(W25X_ManufactDeviceID);
  195. SPI1_ReadWriteByte(0x00);
  196. SPI1_ReadWriteByte(0x00);
  197. SPI1_ReadWriteByte(0x00);
  198. Temp |= SPI1_ReadWriteByte(0xFF) << 8;
  199. Temp |= SPI1_ReadWriteByte(0xFF);
  200. GPIO_WriteBit(GPIOA, GPIO_Pin_2, 1);

  201. return Temp;
  202. }

  203. /*********************************************************************
  204. * @fn SPI_Flash_Erase_Sector
  205. *
  206. * @brief Erase one sector(4Kbyte).
  207. *
  208. * @param Dst_Addr - 0 —— 2047
  209. *
  210. * @return none
  211. */
  212. void SPI_Flash_Erase_Sector(u32 Dst_Addr)
  213. {
  214. Dst_Addr *= 4096;
  215. SPI_FLASH_Write_Enable();
  216. SPI_Flash_Wait_Busy();
  217. GPIO_WriteBit(GPIOA, GPIO_Pin_2, 0);
  218. SPI1_ReadWriteByte(W25X_SectorErase);
  219. SPI1_ReadWriteByte((u8)((Dst_Addr) >> 16));
  220. SPI1_ReadWriteByte((u8)((Dst_Addr) >> 8));
  221. SPI1_ReadWriteByte((u8)Dst_Addr);
  222. GPIO_WriteBit(GPIOA, GPIO_Pin_2, 1);
  223. SPI_Flash_Wait_Busy();
  224. }

  225. /*********************************************************************
  226. * @fn SPI_Flash_Read
  227. *
  228. * @brief Read data from flash.
  229. *
  230. * @param pBuffer -
  231. * ReadAddr -Initial address(24bit).
  232. * size - Data length.
  233. *
  234. * @return none
  235. */
  236. void SPI_Flash_Read(u8 *pBuffer, u32 ReadAddr, u16 size)
  237. {
  238. u16 i;

  239. GPIO_WriteBit(GPIOA, GPIO_Pin_2, 0);
  240. SPI1_ReadWriteByte(W25X_ReadData);
  241. SPI1_ReadWriteByte((u8)((ReadAddr) >> 16));
  242. SPI1_ReadWriteByte((u8)((ReadAddr) >> 8));
  243. SPI1_ReadWriteByte((u8)ReadAddr);

  244. for(i = 0; i < size; i++)
  245. {
  246. pBuffer[i] = SPI1_ReadWriteByte(0XFF);
  247. }

  248. GPIO_WriteBit(GPIOA, GPIO_Pin_2, 1);
  249. }

  250. /*********************************************************************
  251. * @fn SPI_Flash_Write_Page
  252. *
  253. * @brief Write data by one page.
  254. *
  255. * @param pBuffer -
  256. * WriteAddr - Initial address(24bit).
  257. * size - Data length.
  258. *
  259. * @return none
  260. */
  261. void SPI_Flash_Write_Page(u8 *pBuffer, u32 WriteAddr, u16 size)
  262. {
  263. u16 i;

  264. SPI_FLASH_Write_Enable();
  265. GPIO_WriteBit(GPIOA, GPIO_Pin_2, 0);
  266. SPI1_ReadWriteByte(W25X_PageProgram);
  267. SPI1_ReadWriteByte((u8)((WriteAddr) >> 16));
  268. SPI1_ReadWriteByte((u8)((WriteAddr) >> 8));
  269. SPI1_ReadWriteByte((u8)WriteAddr);

  270. for(i = 0; i < size; i++)
  271. {
  272. SPI1_ReadWriteByte(pBuffer[i]);
  273. }

  274. GPIO_WriteBit(GPIOA, GPIO_Pin_2, 1);
  275. SPI_Flash_Wait_Busy();
  276. }

  277. /*********************************************************************
  278. * @fn SPI_Flash_Write_NoCheck
  279. *
  280. * @brief Write data to flash.(need Erase)
  281. * All data in address rang is 0xFF.
  282. *
  283. * @param pBuffer -
  284. * WriteAddr - Initial address(24bit).
  285. * size - Data length.
  286. *
  287. * @return none
  288. */
  289. void SPI_Flash_Write_NoCheck(u8 *pBuffer, u32 WriteAddr, u16 size)
  290. {
  291. u16 pageremain;

  292. pageremain = 256 - WriteAddr % 256;

  293. if(size <= pageremain)
  294. pageremain = size;

  295. while(1)
  296. {
  297. SPI_Flash_Write_Page(pBuffer, WriteAddr, pageremain);

  298. if(size == pageremain)
  299. {
  300. break;
  301. }
  302. else
  303. {
  304. pBuffer += pageremain;
  305. WriteAddr += pageremain;
  306. size -= pageremain;

  307. if(size > 256)
  308. pageremain = 256;
  309. else
  310. pageremain = size;
  311. }
  312. }
  313. }

  314. /*********************************************************************
  315. * @fn SPI_Flash_Write
  316. *
  317. * @brief Write data to flash.(no need Erase)
  318. *
  319. * @param pBuffer -
  320. * WriteAddr - Initial address(24bit).
  321. * size - Data length.
  322. *
  323. * @return none
  324. */
  325. void SPI_Flash_Write(u8 *pBuffer, u32 WriteAddr, u16 size)
  326. {
  327. u32 secpos;
  328. u16 secoff;
  329. u16 secremain;
  330. u16 i;

  331. secpos = WriteAddr / 4096;
  332. secoff = WriteAddr % 4096;
  333. secremain = 4096 - secoff;

  334. if(size <= secremain)
  335. secremain = size;

  336. while(1)
  337. {
  338. SPI_Flash_Read(SPI_FLASH_BUF, secpos * 4096, 4096);

  339. for(i = 0; i < secremain; i++)
  340. {
  341. if(SPI_FLASH_BUF[secoff + i] != 0XFF)
  342. break;
  343. }

  344. if(i < secremain)
  345. {
  346. SPI_Flash_Erase_Sector(secpos);

  347. for(i = 0; i < secremain; i++)
  348. {
  349. SPI_FLASH_BUF[i + secoff] = pBuffer[i];
  350. }

  351. SPI_Flash_Write_NoCheck(SPI_FLASH_BUF, secpos * 4096, 4096);
  352. }
  353. else
  354. {
  355. SPI_Flash_Write_NoCheck(pBuffer, WriteAddr, secremain);
  356. }

  357. if(size == secremain)
  358. {
  359. break;
  360. }
  361. else
  362. {
  363. secpos++;
  364. secoff = 0;

  365. pBuffer += secremain;
  366. WriteAddr += secremain;
  367. size -= secremain;

  368. if(size > 4096)
  369. {
  370. secremain = 4096;
  371. }
  372. else
  373. {
  374. secremain = size;
  375. }
  376. }
  377. }
  378. }

  379. /*********************************************************************
  380. * @fn SPI_Flash_Erase_Chip
  381. *
  382. * @brief Erase all FLASH pages.
  383. *
  384. * @return none
  385. */
  386. void SPI_Flash_Erase_Chip(void)
  387. {
  388. SPI_FLASH_Write_Enable();
  389. SPI_Flash_Wait_Busy();
  390. GPIO_WriteBit(GPIOA, GPIO_Pin_2, 0);
  391. SPI1_ReadWriteByte(W25X_ChipErase);
  392. GPIO_WriteBit(GPIOA, GPIO_Pin_2, 1);
  393. SPI_Flash_Wait_Busy();
  394. }

  395. /*********************************************************************
  396. * @fn SPI_Flash_PowerDown
  397. *
  398. * @brief Enter power down mode.
  399. *
  400. * @return none
  401. */
  402. void SPI_Flash_PowerDown(void)
  403. {
  404. GPIO_WriteBit(GPIOA, GPIO_Pin_2, 0);
  405. SPI1_ReadWriteByte(W25X_PowerDown);
  406. GPIO_WriteBit(GPIOA, GPIO_Pin_2, 1);
  407. Delay_Us(3);
  408. }

  409. /*********************************************************************
  410. * @fn SPI_Flash_WAKEUP
  411. *
  412. * @brief Power down wake up.
  413. *
  414. * @return none
  415. */
  416. void SPI_Flash_WAKEUP(void)
  417. {
  418. GPIO_WriteBit(GPIOA, GPIO_Pin_2, 0);
  419. SPI1_ReadWriteByte(W25X_ReleasePowerDown);
  420. GPIO_WriteBit(GPIOA, GPIO_Pin_2, 1);
  421. Delay_Us(3);
  422. }
程序配置注意:
1. 时钟配置:需确保 SPI 时钟(SCK)频率不超过从设备的最大支持速率(如部分低速传感器仅支持 ≤10MHz SCK);
2. 模式匹配:主从设备的 SPI 模式(CPOL/CPHA)、数据帧长度必须一致,否则会导致数据传输错误;
3. 中断/DMA 优先级:若多个 SPI 同时使用中断或 DMA,需合理配置优先级,避免数据丢失或传输冲突;
4. 引脚电平:CH32V307 的 SPI 引脚默认为推挽输出,需确认与从设备的电平匹配(如 3.3V 与 5V 设备需考虑电平转换,避免损坏芯片)。
5.关键函数解析:
SPI_Flash_ReadSR(): 发送 0x05 命令读取状态寄存器,主要用来检查 BUSY 位。
SPI_Flash_Wait_Busy(): 循环读取状态寄存器,直到 BUSY 位为 0。任何写操作(擦除、编程)后都必须等待。
SPI_FLASH_Write_Enable(): 发送 0x06 命令。在执行任何修改存储单元的操作前,必须写使能。
SPI_Flash_ReadID(): 发送 0x90 命令, followed by 3 dummy bytes and then reads 2 bytes (Manufacturer ID, Device ID).
SPI_Flash_Erase_Sector(u32 Dst_Addr): 发送 0x20 命令 + 24位地址,擦除指定 4KB 扇区。Dst_Addr 是扇区号,函数内部会 *4096 转换为字节地址。
SPI_Flash_Read(): 发送 0x03 命令 + 24位地址,然后连续读取数据。
SPI_Flash_Write_Page(): 发送 0x02 命令 + 24位地址,然后连续写入数据。一次最多写入一页(256字节),且不能跨页。
SPI_Flash_Write_NoCheck(): 封装了跨页写入的逻辑,但它要求目标区域已被擦除(值为 0xFF)。
SPI_Flash_Write(): 最智能的写函数。它先检查目标地址所在的 4K 扇区是否需要擦除(是否有非 0xFF 的字节),如果需要,则先读取整个扇区到缓存 SPI_FLASH_BUF,修改缓存中对应的部分,然后擦除整个扇区,最后将整个缓存写回。这确保了数据的安全性。

main函数:
  1. int main(void)
  2. {
  3.     u8  datap[SIZE];
  4.     u16 Flash_Model;

  5.     Delay_Init();
  6.     USART_Printf_Init(115200);
  7.     printf("SystemClk:%d\r\n", SystemCoreClock);

  8.     SPI_Flash_Init();

  9.     Flash_Model = SPI_Flash_ReadID();

  10.     switch(Flash_Model)
  11.     {
  12.         case W25Q80:
  13.             printf("W25Q80 OK!\r\n");

  14.             break;

  15.         case W25Q16:
  16.             printf("W25Q16 OK!\r\n");

  17.             break;

  18.         case W25Q32:
  19.             printf("W25Q32 OK!\r\n");

  20.             break;

  21.         case W25Q64:
  22.             printf("W25Q64 OK!\r\n");

  23.             break;

  24.         case W25Q128:
  25.             printf("W25Q128 OK!\r\n");

  26.             break;

  27.         default:
  28.             printf("Fail!\r\n");

  29.             break;
  30.     }
  31.     printf("Start Erase W25Qxx....\r\n");
  32.     SPI_Flash_Erase_Sector(0);
  33.     printf("W25Qxx Erase Finished!\r\n");

  34.     Delay_Ms(500);
  35.     printf("Start Read W25Qxx....\r\n");
  36.     SPI_Flash_Read(datap, 0x0, SIZE);
  37.     printf("%s\r\n", datap);

  38.     Delay_Ms(500);
  39.     printf("Start Write W25Qxx....\r\n");
  40.     SPI_Flash_Write((u8 *)TEXT_Buf, 0, SIZE);
  41.     printf("W25Qxx Write Finished!\r\n");

  42.     Delay_Ms(500);
  43.     printf("Start Read W25Qxx....\r\n");
  44.     SPI_Flash_Read(datap, 0x0, SIZE);
  45.     printf("%s\r\n", datap);

  46.     while(1)
  47.         ;
  48. }
Q1.png

您需要登录后才可以回帖 登录 | 注册

本版积分规则

认证:项目经理
简介:资深嵌入式开发工程师

104

主题

190

帖子

3

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