天天看点

STM32F103访问W25Q64STM32F103的W25Q64的DMA高效数据访问实现

STM32F103的W25Q64的DMA高效数据访问实现

1. 关于DMA

首先任何FLASH的写操作都是非常耗时的,体现在擦除FLASH上,且写操作不能太频繁,故而用DMA方式实现写操作程序逻辑会非常复杂,程序逻辑在各种中断处理中容易乱,与之相反采用DMA读大批量数据时及具有优势. 比如36MHzSPI时种,采用轮询方式读一页数据需要花费250us时间,二用了DMA后只需要80us时间,提高了三倍还多,且启动DMA只需要5us,节省了245us时间.

2. W25Q64实用的函数

① 读ID号,用于确定芯片是否能正常访问 ② 轮询方式读数据 ③ 擦除指令 ④ 写一页数据指令,(事先要擦除) ⑤ DMA方式读取一块数据

3. 程序正文W25Q64.c

[cpp]  view plain  copy

  1. #include "w25q64.h"  
  2. uint8_t W25X_Buffer[W25X_SECTOR_SIZE];  
  3. volatile bool sem_W25X_DMA_Busy = true;  
  4. volatile bool sem_W25X_DMA_RxRdy= false;  
  5. static uint8_t  W25X_TX_Byte=0xFF;  
  6. void W25X_GPIO_Config(void)  
  7. {  
  8.     GPIO_InitTypeDef GPIO_InitStruct;  
  9.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);  
  10.     GPIO_InitStruct.GPIO_Pin = GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7;  
  11.     GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;  
  12.     GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;  
  13.     GPIO_Init(GPIOA, &GPIO_InitStruct);  
  14.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB, ENABLE);  
  15.     W25X_WP_EN();  
  16.     W25X_CS_H();  
  17.     GPIO_InitStruct.GPIO_Pin = GPIO_Pin_4;  
  18.     GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;  
  19.     GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;  
  20.     GPIO_Init(GPIOA, &GPIO_InitStruct);  
  21.     GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0;  
  22.     GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;  
  23.     GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;  
  24.     GPIO_Init(GPIOB, &GPIO_InitStruct);   
  25.     GPIO_PinLockConfig(GPIOA,GPIO_Pin_4);  
  26.     GPIO_PinLockConfig(GPIOB,GPIO_Pin_0);  
  27. }  
  28. void W25X_Init(void)  
  29. {  
  30.     SPI_InitTypeDef  SPI_InitStructure ;  
  31.     DMA_InitTypeDef  DMA_InitStructure;  
  32.     NVIC_InitTypeDef NVIC_InitStructure;  
  33.     //配置DMA通道,DMA1_CH2收  
  34.     //读取SPI FLASH时多数为空数据故而数据地址无需增加  
  35.     //启动DMA1的时钟  
  36.     RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);  
  37.     DMA_DeInit(DMA1_Channel2);  
  38.     DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&SPI1->DR);  
  39.     DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)W25X_Buffer;  
  40.     DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;  
  41.     DMA_InitStructure.DMA_BufferSize = 0;  
  42.     DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;  
  43.     DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;  
  44.     DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;  
  45.     DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;  
  46.     DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;  
  47.     DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;  
  48.     DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;  
  49.     DMA_Init(DMA1_Channel2, &DMA_InitStructure);  
  50.     //配置DMA通道,DMA1_CH3发送  
  51.     DMA_DeInit(DMA1_Channel3);  
  52.     DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&SPI1->DR);  
  53.     DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)(&W25X_TX_Byte);  
  54.     DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;  
  55.     DMA_InitStructure.DMA_BufferSize = 0;  
  56.     DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;  
  57.     DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;  
  58.     DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;  
  59.     DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;  
  60.     DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;  
  61.     DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;  
  62.     DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;  
  63.     DMA_Init(DMA1_Channel3, &DMA_InitStructure);  
  64.     //关闭DMA,清DMA标记,使能DMA1_CH2的传输完成中断  
  65.     DMA_Cmd(DMA1_Channel3, DISABLE);            //关闭发送DMA  
  66.     DMA_Cmd(DMA1_Channel2, DISABLE);            //关闭接收DMA  
  67.     DMA_ClearFlag(DMA1_FLAG_GL3|DMA1_FLAG_TC3|DMA1_FLAG_HT3|DMA1_FLAG_TE3);  
  68.     DMA_ClearFlag(DMA1_FLAG_GL2|DMA1_FLAG_TC2|DMA1_FLAG_HT2|DMA1_FLAG_TE2);  
  69.     DMA_ITConfig(DMA1_Channel2,DMA_IT_TC,ENABLE);  
  70.     //初始化SPI时钟    
  71.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1,ENABLE);  
  72.     // SPI配置  
  73.     SPI_Cmd(SPI1,DISABLE);  
  74.     SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex ;  
  75.     SPI_InitStructure.SPI_Mode = SPI_Mode_Master ;  
  76.     SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b ;  
  77.     SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low ;  
  78.     SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge ;  
  79.     SPI_InitStructure.SPI_NSS = SPI_NSS_Soft ;  
  80.     SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2 ;    //72MHz分频  
  81.     SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB ; //SPI设置成LSB模式  
  82.     SPI_InitStructure.SPI_CRCPolynomial = 7 ;  
  83.     SPI_Init( SPI1, &SPI_InitStructure ) ;  
  84.     SPI_Cmd(SPI1,ENABLE);           //启动SPI  
  85.     //打开SPI1的DMA发送接收请求  
  86.     SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Rx, ENABLE);  
  87.     SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Tx, ENABLE);  
  88.     //清DMA忙信号  
  89.     sem_W25X_DMA_Busy = false;  
  90.     //使能NVIC中断  
  91.     NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel2_IRQn;  
  92.     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  
  93.     NVIC_InitStructure.NVIC_IRQChannelSubPriority = W25X_DMA_TC_PRIO;  
  94.     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;  
  95.     NVIC_Init(&NVIC_InitStructure);  
  96. }  
  97. uint8_t W25X_ReadWriteByte(uint8_t dat)  
  98. {  
  99.     while ((SPI1->SR & SPI_I2S_FLAG_TXE) == (uint16_t)RESET);  
  100.     SPI1->DR = dat;  
  101.     while ((SPI1->SR & SPI_I2S_FLAG_RXNE) == (uint16_t)RESET);  
  102.     return (SPI1->DR);  
  103. }  
  104. uint8_t W25X_ReadSR(void)     
  105. {    
  106.     uint8_t byte=0;     
  107.     W25X_CS_L();                            //使能器件     
  108.     W25X_ReadWriteByte(W25X_ReadStatusReg); //发送读取状态寄存器命令      
  109.     byte=W25X_ReadWriteByte(0Xff);          //读取一个字节    
  110.     W25X_CS_H();                            //使能器件       
  111.     return byte;     
  112. }  
  113. uint16_t W25X_ReadID(void)  
  114. {  
  115.     uint16_t Temp = 0;  
  116.     W25X_CS_L();         
  117.     W25X_ReadWriteByte(0x90);       //发送读取ID命令       
  118.     W25X_ReadWriteByte(0x00);        
  119.     W25X_ReadWriteByte(0x00);        
  120.     W25X_ReadWriteByte(0x00);           
  121.     Temp|=W25X_ReadWriteByte(0xFF)<<8;    
  122.     Temp|=W25X_ReadWriteByte(0xFF);    
  123.     W25X_CS_H();          
  124.     return Temp;  
  125. }   
  126. void W25X_Wait_Busy(void)  
  127. {  
  128.     while((W25X_ReadSR()&0x01)==0x01);   // 等待BUSY位清空   
  129. }  
  130. bool W25X_Read_BusyState(void)  
  131. {  
  132.     if((W25X_ReadSR()&0x01))return true;  
  133.     else return false;    
  134. }  
  135. void W25X_Write_Enable(void)  
  136. {  
  137.     W25X_WP_EN();                           //打开硬件写使能  
  138.     W25X_CS_L();                            //使能器件     
  139.     W25X_ReadWriteByte(W25X_WriteEnable);   //发送写使能    
  140.     W25X_CS_H();                            //取消片选              
  141. }   
  142. void W25X_Write_Disable(void)     
  143. {    
  144.     W25X_WP_DIS();                          //关闭硬件写使能  
  145.     W25X_CS_L();                            //使能器件     
  146.     W25X_ReadWriteByte(W25X_WriteDisable);  //发送写禁止指令      
  147.     W25X_CS_H();                            //取消片选                  
  148. }  
  149. void SPI_Flash_PowerDown(void)     
  150. {   
  151.     uint16_t i;  
  152.     W25X_CS_L();                        //使能器件     
  153.     W25X_ReadWriteByte(W25X_PowerDown); //发送掉电命令    
  154.     W25X_CS_H();                        //取消片选              
  155.     i= (72)*3;while(i--);               //等待约3us  
  156. }  
  157. void SPI_Flash_WakeUp(void)     
  158. {   
  159.     uint16_t i;  
  160.     W25X_CS_L();                        //使能器件     
  161.     W25X_ReadWriteByte(W25X_ReleasePowerDown); //发送掉电命令    
  162.     W25X_CS_H();                        //取消片选  
  163.     i= (72)*3;while(i--);               //等待约3us  
  164. }  
  165. void W25X_Erase_Chip(bool bwait)     
  166. {                                     
  167.     W25X_Write_Enable();            //SET WEL   
  168.     W25X_Wait_Busy();     
  169.     W25X_CS_L();                    //使能器件     
  170.     W25X_ReadWriteByte(W25X_ChipErase);   //发送片擦除命令    
  171.     W25X_CS_H();                    //取消片选  
  172.     if(bwait)W25X_Wait_Busy();      //等待芯片擦除结束  
  173. }  
  174. void W25X_Erase_Sector(uint32_t Dst_Addr,bool bwait)     
  175. {    
  176.     W25X_Write_Enable();            //SET WEL     
  177.     W25X_Wait_Busy();     
  178.     W25X_CS_L();                    //使能器件      
  179.     W25X_ReadWriteByte(W25X_SectorErase);           //发送扇区擦除指令   
  180.     W25X_ReadWriteByte((uint8_t)((Dst_Addr)>>16));  //发送24bit地址      
  181.     W25X_ReadWriteByte((uint8_t)((Dst_Addr)>>8));     
  182.     W25X_ReadWriteByte((uint8_t)Dst_Addr);    
  183.     W25X_CS_H();                    //取消片选  
  184.     if(bwait)W25X_Wait_Busy();      //等待擦除完成  
  185. }   
  186. void W25X_Read_Page(uint8_t * pBuffer,uint32_t PageAddr)  
  187. {  
  188.     uint32_t    ReadAddr;  
  189.     uint16_t    i;  
  190.     if(PageAddr < W25X_PAGE_NUM)  
  191.     {                 
  192.         ReadAddr = PageAddr *W25X_PAGE_SIZE;  
  193.         W25X_CS_L();    
  194.         W25X_ReadWriteByte(W25X_ReadData);         //发送读取命令     
  195.         W25X_ReadWriteByte((uint8_t)((ReadAddr)>>16));  //发送24bit地址      
  196.         W25X_ReadWriteByte((uint8_t)((ReadAddr)>>8));     
  197.         W25X_ReadWriteByte((uint8_t)ReadAddr);     
  198.         for(i=0;i<W25X_PAGE_SIZE;i++)  
  199.         {   
  200.             pBuffer[i]=W25X_ReadWriteByte(0XFF);   //循环读数    
  201.         }  
  202.         W25X_CS_H();      
  203.     }  
  204. }  
  205. void W25X_Write_Page(uint8_t * pBuffer,uint32_t PageAddr)  
  206. {  
  207.     uint16_t    i;   
  208.     uint32_t    WriteAddr;  
  209.     //打开写状态,并等待上次写操作完成  
  210.     W25X_Write_Enable();  
  211.     W25X_Wait_Busy();      //等待擦除完成  
  212.     //将数据写入FLASH  
  213.     WriteAddr =PageAddr* W25X_PAGE_SIZE;  
  214.     W25X_CS_L();   
  215.     W25X_ReadWriteByte(W25X_PageProgram);      //发送写页命令     
  216.     W25X_ReadWriteByte((uint8_t)((WriteAddr)>>16)); //发送24bit地址      
  217.     W25X_ReadWriteByte((uint8_t)((WriteAddr)>>8));     
  218.     W25X_ReadWriteByte((uint8_t)WriteAddr);     
  219.     for(i=0;i<W25X_PAGE_SIZE;i++)W25X_ReadWriteByte(pBuffer[i]);//循环写数    
  220.     W25X_CS_H();  
  221.     //W25X_Wait_Busy();      //等待擦除完成  
  222. }  
  223. void W25X_Read_Data(uint8_t * pBuffer,uint32_t ReadAddr,uint16_t NumByteToRead)     
  224. {   
  225.     uint16_t i;                   
  226.     W25X_CS_L();    
  227.     W25X_ReadWriteByte(W25X_ReadData);         //发送读取命令     
  228.     W25X_ReadWriteByte((uint8_t)((ReadAddr)>>16));  //发送24bit地址      
  229.     W25X_ReadWriteByte((uint8_t)((ReadAddr)>>8));     
  230.     W25X_ReadWriteByte((uint8_t)ReadAddr);     
  231.     for(i=0;i<NumByteToRead;i++)  
  232.     {   
  233.         pBuffer[i]=W25X_ReadWriteByte(0XFF);   //循环读数    
  234.     }  
  235.     W25X_CS_H();                   
  236. }  
  237. void W25X_DMARead_Data(uint8_t * pBuffer,uint32_t ReadAddr,uint16_t NumByteToRead)  
  238. {  
  239.     //判断DMA是否仍处于工作状态,若是则等待传输完成,  
  240.     if( (DMA1_Channel2->CCR & DMA_CCR1_EN) || (DMA1_Channel3->CCR & DMA_CCR1_EN) )  
  241.     {  
  242.         //while( !DMA_GetFlagStatus(DMA1_FLAG_TC2));//高效写法如下  
  243.         while( !(DMA1->ISR & DMA1_FLAG_TC2));       //等待传送完成  
  244.         sem_W25X_DMA_RxRdy  = true;                 //标记DMA接收数据信号  
  245.         W25X_CS_H();                                //结束片选  
  246.         __NOP();__NOP();__NOP();__NOP();            //短延时,使CS有足够的拉高时间      
  247.     }  
  248.     //设置DMA数据载荷,并清DMA标记  
  249.     sem_W25X_DMA_Busy = true;               //标记为DMA忙  
  250.     DMA1_Channel3->CMAR = (uint32_t)(&W25X_TX_Byte);    //设置发送数据的源SRAM地址  
  251.     DMA1_Channel3->CNDTR= NumByteToRead;    //设置发送字节长度,发送SRAM地址不增加  
  252.     DMA1_Channel2->CMAR =(uint32_t)pBuffer; //设置接收数据个数  
  253.     DMA1_Channel2->CNDTR= NumByteToRead;    //设置接收数据的目标SRAM地址  
  254.     //发送前导字节  
  255.     W25X_CS_L();    
  256.     W25X_ReadWriteByte(W25X_ReadData);         //发送读取命令     
  257.     W25X_ReadWriteByte((uint8_t)((ReadAddr)>>16));  //发送24bit地址      
  258.     W25X_ReadWriteByte((uint8_t)((ReadAddr)>>8));     
  259.     W25X_ReadWriteByte((uint8_t)ReadAddr);  
  260.     SPI1->DR ;                                //接送前读一次SPI1->DR,保证接收缓冲区为空  
  261.     //清DMA标记  
  262.     DMA_ClearFlag(DMA1_FLAG_GL3|DMA1_FLAG_TC3|DMA1_FLAG_HT3|DMA1_FLAG_TE2);  
  263.     DMA_ClearFlag(DMA1_FLAG_GL2|DMA1_FLAG_TC2|DMA1_FLAG_HT2|DMA1_FLAG_TE2);  
  264.     //启动DMA发送数据  
  265.     while ((SPI1->SR & SPI_I2S_FLAG_TXE) == (uint16_t)RESET);  
  266.     DMA_Cmd(DMA1_Channel3, ENABLE);  
  267.     DMA_Cmd(DMA1_Channel2, ENABLE);     
  268.     //等待DMA传送数据完毕  
  269. }  
  270. void W25X_Read_UID(uint8_t * pBuffer)  
  271. {   
  272.     uint8_t i;  
  273.     W25X_CS_L();         
  274.     W25X_ReadWriteByte(W25X_ReadUniqueID);      
  275.     W25X_ReadWriteByte(0x00);        
  276.     W25X_ReadWriteByte(0x00);        
  277.     W25X_ReadWriteByte(0x00);  
  278.     W25X_ReadWriteByte(0x00);          
  279.     for(i=0;i<8;i++)  
  280.         pBuffer[i]=W25X_ReadWriteByte(0XFF);   //循环读数  
  281.     W25X_CS_H();  
  282. }  
  283. void DMA1_Channel2_IRQHandler(void)  
  284. {      
  285.     //空读ISR状态  
  286.     DMA1->ISR;                            
  287.     //关闭DMA通道  
  288.     //DMA_Cmd(DMA1_Channel2, DISABLE);//以下为等效写法  
  289.     //DMA_Cmd(DMA1_Channel3, DISABLE);//以下为等效写法  
  290.     DMA1_Channel2->CCR &= ~DMA_CCR1_EN;     //关闭DMA1_CH2  
  291.     DMA1_Channel3->CCR &= ~DMA_CCR1_EN;     //关闭DMA1_CH2  
  292.     //清DMA中断标记  
  293.     //DMA_ClearITPendingBit(DMA1_IT_GL2|DMA1_IT_TC2|DMA1_IT_HT2|DMA1_IT_TE2);//以下为等待模式  
  294.     DMA1->IFCR = DMA1_IT_GL2|DMA1_IT_TC2|DMA1_IT_HT2|DMA1_IT_TE2;  
  295.     //置信号量  
  296.     DMA_Cmd(DMA1_Channel3, DISABLE);            //关闭发送DMA  
  297.     DMA_Cmd(DMA1_Channel2, DISABLE);            //关闭接收DMA  
  298.     sem_W25X_DMA_Busy   = false;                //标记为DMA空闲  
  299.     sem_W25X_DMA_RxRdy  = true;                 //标记DMA接收数据信号  
  300.     W25X_CS_H();                                //结束片选        
  301. }  

4. 头文件W25Q64.h

[cpp]  view plain  copy

  1. #ifndef _W25Q64_H_  
  2. #define _W25Q64_H_  
  3. #include "stm32f10x.h"  
  4. #include "stm32f10x_gpio.h"  
  5. #include "stm32f10x_rcc.h"  
  6. #include "stm32f10x_spi.h"  
  7. #include "stm32f10x_dma.h"  
  8. #include <string.h>  
  9. #include <stdbool.h>  
  10. #include <stdint.h>  
  11. #define W25X_DMA_TC_PRIO    2             
  12. #define W25X_PAGE_SIZE      256           
  13. #define W25X_PAGE_NUM       32768         
  14. #define W25X_SECTOR_SIZE    4096              
  15. #define W25X_PAGES_PS       (W25X_SECTOR_SIZE/W25X_PAGE_SIZE)    
  16. #define W25X_BUFF_NUM       2             
  17. #define W25X_DUMMY_BYTE     0xFF          
  18. #define W25X_ReadStatusReg      0x05    //读状态寄存器1  
  19. #define W25X_ReadStatusReg2     0x35    //读状态寄存器2  
  20. #define W25X_WriteStatusReg     0x01    //写状态寄存器1  
  21. #define W25X_ReadUniqueID       0x4B    //读取唯一ID  
  22. #define W25X_WriteEnable        0x06    //写使能  
  23. #define W25X_WriteDisable       0x04    //写关闭  
  24. #define W25X_ReadData           0x03    //读数据  
  25. #define W25X_PageProgram        0x02    //写FLASH  
  26. #define W25X_ChipErase          0x60    //也可为0x60  
  27. #define W25X_SectorErase        0x20    //4KB擦除          
  28. #define W25X_PowerDown          0xB9    //掉电,低功耗  
  29. #define W25X_ReleasePowerDown   0xAB    //恢复上电  
  30. #define W25X_WP_DIS()        (GPIOB->BRR = GPIO_Pin_0)  
  31. #define W25X_WP_EN()         (GPIOB->BSRR  = GPIO_Pin_0)  
  32. #define W25X_CS_L()          (GPIOA->BRR  = GPIO_Pin_4)  
  33. #define W25X_CS_H()          (GPIOA->BSRR = GPIO_Pin_4)  
  34. extern uint8_t W25X_Buffer[W25X_SECTOR_SIZE];  
  35. extern volatile bool sem_W25X_DMA_Busy;         //用户只读  
  36. extern volatile bool sem_W25X_DMA_RxRdy;        //用户读取,清零  
  37. //初始化  
  38. extern void W25X_GPIO_Config(void);         //配置GPIO口  
  39. extern void W25X_Init(void);                //初始化SPI  
  40. //获取状态  
  41. extern uint8_t W25X_ReadSR(void);           //读取状态寄存器  
  42. extern uint16_t W25X_ReadID(void);          //读取ID号  
  43. extern void W25X_Wait_Busy(void);           //等待W25X直到空闲  
  44. extern bool W25X_Read_BusyState(void);      //读取W25X的忙状态(不等待)  
  45. //控制状态  
  46. extern void W25X_Write_Enable(void);        //写使能  
  47. extern void W25X_Write_Disable(void);       //写禁止  
  48. extern void SPI_Flash_PowerDown(void);      //掉电  
  49. extern void SPI_Flash_WakeUp(void);         //唤醒  
  50. //擦除相关(有等待选择)  
  51. extern void W25X_Erase_Chip(bool bwait);    //全片擦除,要等待写完成,需要21秒  
  52. extern void W25X_Erase_Sector(uint32_t Dst_Addr,bool bwait);    //扇区擦除,实际需要65ms  
  53. extern void W25X_Read_Data(uint8_t * pBuffer,uint32_t ReadAddr,uint16_t NumByteToRead);     //250us执行完毕  
  54. extern void W25X_DMARead_Data(uint8_t * pBuffer,uint32_t ReadAddr,uint16_t NumByteToRead);  //5us执行,75us后结束  
  55. extern void W25X_Read_Page(uint8_t * pBuffer,uint32_t PageAddr);    //读出一页,300us  
  56. extern void W25X_Write_Page(uint8_t * pBuffer,uint32_t PageAddr);   //写入一页,必先擦除,事先有些等待,600us  
  57. extern void W25X_Read_UID(uint8_t * pBuffer);   //读取W25X的唯一MAC,<5us  
  58. #endif  

继续阅读