找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 11413|回复: 16
打印 上一主题 下一主题
收起左侧

STM32 USB虚拟U盘例程 spi w25q16 flash芯片源码

  [复制链接]
跳转到指定楼层
楼主
ID:415857 发表于 2018-10-26 16:17 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
发一个stm32 usb虚拟U盘的例程,采用spi w25q16 flash 芯片
1、该例程为USB-Mass_Storage-SD Card使用例程。

2、使用说明
   (1)工程文件路径:例程目录\USB-Mass_Storage-SD Card\MDK-ARM\Project.uvproj。
   (2)请使用MDK 4.0以上版本打开,MDK版本过低会导致无法识别工程。
   (3)下载调试工具为ULINK。
   (4)请将USB线插板子上。
   (6)HEX文件下载到板子后,打开我的电脑往新识别磁盘拷贝文件(LED为读写指示灯),成功拷贝表明例程运行正确。

3、注意事项
   请务必在下载、调试、运行过程中,保持板子上电、ULINK连接并插在电脑上。


USB-Mass_Storage-SPI_Flash(W25X16)

单片机源程序如下:
  1. #include  <stm32f10x.h>
  2. #include "W25X16.h"                          
  3. #include  <stdio.h>
  4.                                           
  5. #define MAX_ADDR 0x1fffff
  6. #define SEC_SIZE 4095          //byte
  7. #define SEC_MAX 511
  8. //以下是SPI模块的初始化代码,配置成主机模式,访问SD Card/W25X16/24L01/JF24C                                                          
  9. //SPI口初始化
  10. //这里针是对SPI1的初始化
  11. SPI_InitTypeDef  SPI_InitStructure;

  12. #define DF_CS_ENABLE()      GPIO_ResetBits(GPIOB,GPIO_Pin_6)   //选中SD卡
  13. #define DF_CS_DISABLE()     GPIO_SetBits(GPIOB,GPIO_Pin_6)     //不选中SD卡
  14. u8 SPIx_ReadWriteByte(u8 TxData);

  15. void SPIx_Init(void)
  16. {
  17.         GPIO_InitTypeDef GPIO_InitStructure;
  18.   
  19.         RCC_APB2PeriphClockCmd(        RCC_APB2Periph_GPIOA|RCC_APB2Periph_SPI1, ENABLE );       

  20.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
  21.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //复用推挽输出
  22.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  23.         GPIO_Init(GPIOA, &GPIO_InitStructure);

  24.         GPIO_SetBits(GPIOA,GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7);

  25.         SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;  //设置SPI单向或者双向的数据模式:SPI设置为双线双向全双工
  26.         SPI_InitStructure.SPI_Mode = SPI_Mode_Master;                //设置SPI工作模式:设置为主SPI
  27.         SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;                //设置SPI的数据大小:SPI发送接收8位帧结构
  28.         SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;                //选择了串行时钟的稳态:时钟悬空高
  29.         SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;        //数据捕获于第二个时钟沿
  30.         SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;                //NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理:内部NSS信号有SSI位控制
  31.         SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;                //定义波特率预分频的值:波特率预分频值为256
  32.         SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;        //指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始
  33.         SPI_InitStructure.SPI_CRCPolynomial = 7;        //CRC值计算的多项式
  34.         SPI_Init(SPI1, &SPI_InitStructure);  //根据SPI_InitStruct中指定的参数初始化外设SPIx寄存器

  35.         SPI_Cmd(SPI1, ENABLE); //使能SPI外设
  36.        
  37.         SPIx_ReadWriteByte(0xff);//启动传输                 
  38. }   

  39. //SPIx 读写一个字节
  40. //TxData:要写入的字节
  41. //返回值:读取到的字节
  42. u8 SPIx_ReadWriteByte(u8 TxData)
  43. {               
  44.         u8 retry=0;                                 
  45.         while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET) //检查指定的SPI标志位设置与否:发送缓存空标志位
  46.         {
  47.                 retry++;
  48.                 if(retry>200){printf("SPI Write TimeOut!\r\n");return 0;}
  49.         }                          

  50.         SPI_I2S_SendData(SPI1, TxData); //通过外设SPIx发送一个数据
  51.         retry=0;
  52.         while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET)//检查指定的SPI标志位设置与否:接受缓存非空标志位
  53.         {
  54.                 retry++;
  55.                 if(retry>200){printf("SPI Read TimeOut!\r\n");return 0;}
  56.         }                                                              
  57.         return SPI_I2S_ReceiveData(SPI1); //返回通过SPIx最近接收的数据                                            
  58. }

  59. //SPI硬件层初始化
  60. void Flash_SPI_Init(void)
  61. {
  62.     GPIO_InitTypeDef GPIO_InitStructure;
  63.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB, ENABLE );         

  64.     GPIO_InitStructure.GPIO_Pin =GPIO_Pin_4 | GPIO_Pin_6 | GPIO_Pin_7;
  65.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ;   //推挽输出
  66.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  67.         GPIO_Init(GPIOB, &GPIO_InitStructure);
  68.         GPIO_Init(GPIOA, &GPIO_InitStructure);
  69.         GPIO_SetBits(GPIOB,GPIO_Pin_6);
  70.         GPIO_SetBits(GPIOB,GPIO_Pin_7);
  71.         GPIO_SetBits(GPIOA,GPIO_Pin_4);
  72.         SPIx_Init();
  73. }

  74. // 读
  75. u8 W25X16_Read(u32 DstAdr, u8* RcvBufPt ,u32 NByte)
  76. {
  77.         u32 i = 0;
  78.         if ((DstAdr+NByte > MAX_ADDR)||(NByte == 0))        return (0);         /*        检查入口参数 */       

  79.                 DF_CS_ENABLE();                         
  80.                 SPIx_ReadWriteByte(0x05);        //
  81.                 while(SPIx_ReadWriteByte(0xff)&0x01)
  82.                 {}                         
  83.                 DF_CS_DISABLE();

  84.         DF_CS_ENABLE();
  85.         SPIx_ReadWriteByte(0x0B);        //read comand
  86.         SPIx_ReadWriteByte(((DstAdr & 0xFFFFFF) >> 16));        /* 发送地址信息:该地址由3个字节组成        */
  87.         SPIx_ReadWriteByte(((DstAdr & 0xFFFF) >> 8));
  88.         SPIx_ReadWriteByte(DstAdr & 0xFF);
  89.         SPIx_ReadWriteByte(0xff);        //哑字节
  90.         for (i = 0; i < NByte; i++)               
  91.         {
  92.        RcvBufPt[i] = SPIx_ReadWriteByte(0xFF);               
  93.         }

  94.         DF_CS_DISABLE();
  95.         return 1;
  96. }
  97. u8 W25X16_SectorRead(u32 sec,  u8* RcvBufPt)
  98. {
  99.         u16 i;
  100.         sec*=4096;


  101.         DF_CS_ENABLE();
  102.         SPIx_ReadWriteByte(0x03);        //read comand
  103.         SPIx_ReadWriteByte(((sec & 0xFFFFFF) >> 16));        /* 发送地址信息:该地址由3个字节组成        */
  104.         SPIx_ReadWriteByte(((sec & 0xFFFF) >> 8));
  105.         SPIx_ReadWriteByte(sec & 0xFF);
  106. //        SPIx_ReadWriteByte(0xff);        //哑字节
  107.         for (i = 0; i < 4096; i++)               
  108.         {
  109.        RcvBufPt[i] = SPIx_ReadWriteByte(0xFF);               
  110.         }
  111.         DF_CS_DISABLE();       
  112.         DF_CS_ENABLE();                         
  113.         SPIx_ReadWriteByte(0x05);        //
  114.         while(SPIx_ReadWriteByte(0xff)&0x01)
  115.         {}                         
  116.         DF_CS_DISABLE();
  117.        
  118.         return 1;
  119. }

  120. //写一个扇区
  121. //每个扇区有4096个字节
  122. u8 W25X16_SectorWrite(u32 sec,  u8* SndbufPt)
  123. {

  124.         u32 i = 0, j;
  125. //        u32 addr;
  126.         sec*=4096;
  127.         for(j=0;j<16;j++)
  128.         {       

  129.                

  130.                 DF_CS_ENABLE();
  131.                 SPIx_ReadWriteByte(0x06);        //write enable
  132.                 DF_CS_DISABLE();

  133.                 DF_CS_ENABLE();
  134.                 SPIx_ReadWriteByte(0x02);  //page program
  135.                 SPIx_ReadWriteByte((( sec& 0xFFFFFF) >> 16));  /* 发送3个字节的地址信息 */
  136.                 SPIx_ReadWriteByte(((sec& 0xFFFF) >> 8));
  137.                 SPIx_ReadWriteByte( sec& 0xFF);
  138.                 for(i=0;i<256;i++)
  139.                 {
  140.                         SPIx_ReadWriteByte(SndbufPt[i]);
  141.                 }
  142.                 DF_CS_DISABLE();        
  143.                 SndbufPt+=256;       
  144.                 sec+=256;                
  145.                 DF_CS_ENABLE();
  146.                 SPIx_ReadWriteByte(0x05);        //        等待  BUZY = 0
  147.                 while(SPIx_ReadWriteByte(0xff)&0x01)
  148.                 {}                         
  149.                 DF_CS_DISABLE();
  150.         }
  151.         return 1;               
  152. }
  153. //sec1,sec (0,511)
  154. u8 W25X16_SectorErase(u32 sec)
  155. {
  156.         sec *=4096;


  157.         DF_CS_ENABLE();
  158.         SPIx_ReadWriteByte(0x06);        //write enable        WEL = 1
  159.         DF_CS_DISABLE();

  160.         DF_CS_ENABLE();       
  161.         SPIx_ReadWriteByte(0x20); //  sector erase reg       
  162.         SPIx_ReadWriteByte((((sec) & 0xFFFFFF) >> 16));  /* 发送3个字节的地址信息 */
  163.         SPIx_ReadWriteByte((((sec) & 0xFFFF) >> 8));
  164.         SPIx_ReadWriteByte((sec) & 0xFF);
  165.         DF_CS_DISABLE();
  166.         DF_CS_ENABLE();
  167.         SPIx_ReadWriteByte(0x05);        //                        等待  BUZY = 0
  168.         while(SPIx_ReadWriteByte(0xff)&0x01)
  169.         {}                 
  170.         DF_CS_DISABLE();
  171.         return 1;
  172. }
复制代码

所有资料51hei提供下载:
USB-Mass_Storage-SPI_Flash(W25X16).rar (538.94 KB, 下载次数: 357)


分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏8 分享淘帖 顶2 踩
回复

使用道具 举报

沙发
ID:1 发表于 2018-11-1 17:01 | 只看该作者
好资料,51黑有你更精彩!!!
回复

使用道具 举报

板凳
ID:91469 发表于 2018-12-1 08:30 来自手机 | 只看该作者
感谢分享!为我所用
回复

使用道具 举报

地板
ID:285301 发表于 2019-1-16 16:35 | 只看该作者
下载了,不过不是CUBEMX工程
回复

使用道具 举报

5#
ID:90169 发表于 2019-3-5 22:36 | 只看该作者
不错,好好学习下
回复

使用道具 举报

6#
ID:64682 发表于 2019-3-29 21:17 | 只看该作者
STM32 USB虚拟U盘例程 spi w25q16 flash芯片源码
回复

使用道具 举报

7#
ID:156606 发表于 2019-5-1 17:39 | 只看该作者
不错,好好学习下。
回复

使用道具 举报

8#
ID:591015 发表于 2019-7-26 21:06 | 只看该作者
牛逼 怎么才能免费下载呢 这么好的东西
回复

使用道具 举报

9#
ID:377989 发表于 2019-11-18 17:23 | 只看该作者
好资料啊,正好需要
回复

使用道具 举报

10#
ID:280272 发表于 2019-12-5 17:49 | 只看该作者

好资料,51黑有你更精彩!!!
回复

使用道具 举报

11#
ID:61261 发表于 2019-12-6 10:44 | 只看该作者
感谢分享!无私奉献
回复

使用道具 举报

12#
ID:471251 发表于 2020-5-6 09:19 | 只看该作者
感谢分享!无私奉献
回复

使用道具 举报

13#
ID:629912 发表于 2021-1-26 14:20 | 只看该作者
好资料,51黑有你更精彩!!!!!!!!
回复

使用道具 举报

14#
ID:474637 发表于 2021-3-24 08:42 | 只看该作者
好资料,51黑有你更精彩!!!
回复

使用道具 举报

15#
ID:806655 发表于 2021-8-25 10:58 | 只看该作者
PC端不需要驱动吗????
回复

使用道具 举报

16#
ID:965170 发表于 2021-9-20 14:32 | 只看该作者
不错,感谢热心网友
回复

使用道具 举报

17#
ID:517951 发表于 2021-9-22 09:49 | 只看该作者
spi接口的U盘,读写是不是很慢啊?
回复

使用道具 举报

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

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表