您现在的位置: 主页 > 嵌入式处理器 > ARM > STM32 > stm32应用 > stm32F0xx USB存储盘设计
本文所属标签:
#STM32F042#   
为本文创立个标签吧:

stm32F0xx USB存储盘设计

来源:网络整理 网络用户发布,如有版权联系网管删除 2017-11-30 

第一个USB工程例子:USB存储盘。因为手边没有SPI或I2C接口的Flash, 就权且用单片机的RAM虚拟一下吧。这个"U盘"容量标成160kB, 实际上有效的存储只有10kB,用一点扇区映射的技巧骗过操作系统,当然存放文件只能几kB了。

ST官方提供了一个 STM32F0 的USB固件库,(URL http://www.st.com/st-web-ui/static/active/en/st_prod_software_internet/resource/technical/software/firmware/stsw-stm32092.zip),包括了硬件库、核心库和类库的C头文件和源文件。我cruelfox琢磨了一整天,还是没搞清楚怎么调用这些函数,只好照着个Example改吧。

于是就用MassStorage类的例子来下手了,这个目录里面的主文件 app.c 非常简单

  1. /**
  2.   * @file    app.c
  3.   */ 
  4.  
  5. /* Includes ------------------------------------------------------------------*/ 
  6. #include  "usbd_msc_core.h"
  7. #include  "usbd_usr.h"
  8.  
  9. USB_CORE_HANDLE  USB_Device_dev ;
  10.  
  11. int main(void)
  12. {
  13.  
  14.   USBD_Init(&USB_Device_dev,
  15.             &USR_desc, 
  16.             &USBD_MSC_cb, 
  17.             &USR_cb);
  18.   
  19.   while (1)
  20.   {
  21.   }
  22.  
  23. #ifdef USE_FULL_ASSERT
  24. void assert_failed(uint8_t* file, uint32_t line)
  25. {
  26.   while (1)
  27.   {}
  28. }
  29. #endif
  30.  
复制代码
一切USB相关的东西都在 USBD_init() 这个函数里面了。追查源代码,可以发现这个函数调用其实是向库函数提供了一堆回调函数的接口,也就是说写一些子程序,让驱动程序在需要的时候调用。这样开发USB的我们就不用去管中断什么的了,要做的就是实现各种USB的请求——其实程序库里面已经把大部分的请求应答都实现了,而具体的类库(比如我这里用的MassStorage类)又处理了剩余的大部分,所以只剩下功能性的需要自己写。

在 usbd_desc.c 这个程序里面可以看到描述符是怎么创建和返回的
  1. /**
  2.   ******************************************************************************
  3.   * @file    usbd_desc.c
  4.   * @author  MCD Application Team
  5.   * @version V1.0.0
  6.   * @date    31-January-2014
  7.   * @brief   This file provides the USBD descriptors and string formating method.
  8.   ******************************************************************************
  9.   * @attention
  10.   *
  11.   * <h2><center>© COPYRIGHT 2014 STMicroelectronics</center></h2>
  12.   *
  13.   * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
  14.   * You may not use this file except in compliance with the License.
  15.   * You may obtain a copy of the License at:
  16.   *
  17.   *        http://www.st.com/software_license_agreement_liberty_v2
  18.   *
  19.   * Unless required by applicable law or agreed to in writing, software 
  20.   * distributed under the License is distributed on an "AS IS" BASIS, 
  21.   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  22.   * See the License for the specific language governing permissions and
  23.   * limitations under the License.
  24.   *
  25.   ******************************************************************************
  26.   */ 
  27.  
  28. /* Includes ------------------------------------------------------------------*/
  29. #include "usbd_desc.h"
  30.  
  31. /* Private typedef -----------------------------------------------------------*/
  32. /* Private define ------------------------------------------------------------*/
  33. #define USBD_VID                   0x0483
  34. #define USBD_PID                   0x5720
  35.  
  36. #define USBD_LANGID_STRING         0x409
  37. #define USBD_MANUFACTURER_STRING   "STMicroelectronics"
  38.  
  39. #define USBD_PRODUCT_FS_STRING     "Mass Storage in FS Mode"
  40.  
  41. #define USBD_CONFIGURATION_FS_STRING  "MSC Config"
  42. #define USBD_INTERFACE_FS_STRING      "MSC Interface"
  43. /* Private macro -------------------------------------------------------------*/
  44. /* Private variables ---------------------------------------------------------*/
  45. char USBD_SERIALNUMBER_FS_STRING[26];
  46.  
  47. USBD_DEVICE USR_desc =
  48. {
  49.   USBD_USR_DeviceDescriptor,
  50.   USBD_USR_LangIDStrDescriptor, 
  51.   USBD_USR_ManufacturerStrDescriptor,
  52.   USBD_USR_ProductStrDescriptor,
  53.   USBD_USR_SerialStrDescriptor,
  54.   USBD_USR_ConfigStrDescriptor,
  55.   USBD_USR_InterfaceStrDescriptor,
  56.   
  57. };
  58.  
  59. /* USB Standard Device Descriptor */
  60. const uint8_t USBD_DeviceDesc[USB_SIZ_DEVICE_DESC] =
  61. {
  62.   0x12,                       /*bLength */
  63.   USB_DEVICE_DEscriptOR_TYPE, /*bDescriptorType*/
  64.   0x00,                       /*bcdUSB */
  65.   0x02,
  66.   0x00,                       /*bDeviceClass*/
  67.   0x00,                       /*bDeviceSubClass*/
  68.   0x00,                       /*bDeviceProtocol*/
  69.   USB_MAX_EP0_SIZE,           /*bMaxPacketSize*/
  70.   LOBYTE(USBD_VID),           /*idVendor*/
  71.   HIBYTE(USBD_VID),           /*idVendor*/
  72.   LOBYTE(USBD_PID),           /*idVendor*/
  73.   HIBYTE(USBD_PID),           /*idVendor*/
  74.   0x00,                       /*bcdDevice rel. 2.00*/
  75.   0x02,
  76.   USBD_IDX_MFC_STR,           /*Index of manufacturer  string*/
  77.   USBD_IDX_PRODUCT_STR,       /*Index of product string*/
  78.   USBD_IDX_SERIAL_STR,        /*Index of serial number string*/
  79.   USBD_CFG_MAX_NUM            /*bNumConfigurations*/
  80. } ; /* USB_DeviceDescriptor */
  81.  
  82. /* USB Standard Device Descriptor */
  83. const uint8_t USBD_DeviceQualifierDesc[USB_LEN_DEV_QUALIFIER_DESC] =
  84. {
  85.   USB_LEN_DEV_QUALIFIER_DESC,
  86.   USB_DESC_TYPE_DEVICE_QUALIFIER,
  87.   0x00,
  88.   0x02,
  89.   0x00,
  90.   0x00,
  91.   0x00,
  92.   0x40,
  93.   0x01,
  94.   0x00,
  95. };
  96.  
  97. /* USB Standard Device Descriptor */
  98. const uint8_t USBD_LangIDDesc[USB_SIZ_STRING_LANGID] =
  99. {
  100.   USB_SIZ_STRING_LANGID,         
  101.   USB_DESC_TYPE_STRING,       
  102.   LOBYTE(USBD_LANGID_STRING),
  103.   HIBYTE(USBD_LANGID_STRING), 
  104. };
  105.  
  106. uint8_t USBD_StringSerial[USB_SIZ_STRING_SERIAL] =
  107. {
  108.   USB_SIZ_STRING_SERIAL,       /* bLength */
  109.   USB_STRING_DEscriptOR_TYPE,  /* bDescriptorType */
  110. };
  111.  
  112. /* Private function prototypes -----------------------------------------------*/
  113. /* Private functions ---------------------------------------------------------*/
  114. static void IntToUnicode (uint32_t value , uint8_t *pbuf , uint8_t len);
  115.  
  116. /**
  117.   * @brief return the device descriptor
  118.   * @param  speed : current device speed
  119.   * @param  length : pointer to data length variable
  120.   * @retval pointer to descriptor buffer
  121.   */
  122. uint8_t *  USBD_USR_DeviceDescriptor( uint8_t speed , uint16_t *length)
  123. {
  124.   *length = sizeof(USBD_DeviceDesc);
  125.   return (uint8_t*)USBD_DeviceDesc;
  126. }
  127.  
  128. /**
  129.   * @brief  return the LangID string descriptor
  130.   * @param  speed : current device speed
  131.   * @param  length : pointer to data length variable
  132.   * @retval pointer to descriptor buffer
  133.   */
  134. uint8_t *  USBD_USR_LangIDStrDescriptor( uint8_t speed , uint16_t *length)
  135. {
  136.   *length =  sizeof(USBD_LangIDDesc);  
  137.   return (uint8_t*)USBD_LangIDDesc;
  138. }
  139.  
  140.  
  141. /**
  142.   * @brief  return the product string descriptor
  143.   * @param  speed : current device speed
  144.   * @param  length : pointer to data length variable
  145.   * @retval pointer to descriptor buffer
  146.   */
  147. uint8_t *  USBD_USR_ProductStrDescriptor( uint8_t speed , uint16_t *length)
  148. {
  149.   USBD_GetString ( (uint8_t*)USBD_PRODUCT_FS_STRING, USBD_StrDesc, length);    
  150.   return USBD_StrDesc;
  151. }
  152.  
  153. /**
  154.   * @brief  return the manufacturer string descriptor
  155.   * @param  speed : current device speed
  156.   * @param  length : pointer to data length variable
  157.   * @retval pointer to descriptor buffer
  158.   */
  159. uint8_t *  USBD_USR_ManufacturerStrDescriptor( uint8_t speed , uint16_t *length)
  160. {
  161.   USBD_GetString ( (uint8_t*)USBD_MANUFACTURER_STRING, USBD_StrDesc, length);
  162.   return USBD_StrDesc;
  163. }
  164.  
  165. /**
  166.   * @brief  return the serial number string descriptor
  167.   * @param  speed : current device speed
  168.   * @param  length : pointer to data length variable
  169.   * @retval pointer to descriptor buffer
  170.   */
  171. uint8_t *  USBD_USR_SerialStrDescriptor( uint8_t speed , uint16_t *length)
  172. {
  173.   *length = USB_SIZ_STRING_SERIAL; 
  174.   return USBD_StringSerial;
  175. }
  176.  
  177. /**
  178.   * @brief return the configuration string descriptor
  179.   * @param  speed : current device speed
  180.   * @param  length : pointer to data length variable
  181.   * @retval pointer to descriptor buffer
  182.   */
  183. uint8_t *  USBD_USR_ConfigStrDescriptor( uint8_t speed , uint16_t *length)
  184. {
  185.   USBD_GetString ( (uint8_t*)USBD_CONFIGURATION_FS_STRING, USBD_StrDesc, length); 
  186.   return USBD_StrDesc;  
  187. }
  188.  
  189.  
  190. /**
  191.   * @brief  return the interface string descriptor
  192.   * @param  speed : current device speed
  193.   * @param  length : pointer to data length variable
  194.   * @retval pointer to descriptor buffer
  195.   */
  196. uint8_t *  USBD_USR_InterfaceStrDescriptor( uint8_t speed , uint16_t *length)
  197. {
  198.   USBD_GetString ( (uint8_t*)USBD_INTERFACE_FS_STRING, USBD_StrDesc, length);
  199.   return USBD_StrDesc;  
  200. }
  201.  
  202. /**
  203.   * @brief  Create the serial number string descriptor 
  204.   * @param  None 
  205.   * @retval None
  206.   */
  207. void Get_SerialNum(void)
  208. {
  209.   uint32_t Device_Serial0, Device_Serial1, Device_Serial2;
  210.   
  211.   Device_Serial0 = *(uint32_t*)Device1_Identifier;
  212.   Device_Serial1 = *(uint32_t*)Device2_Identifier;
  213.   Device_Serial2 = *(uint32_t*)Device3_Identifier;
  214.   
  215.   Device_Serial0 += Device_Serial2;
  216.   
  217.   if (Device_Serial0 != 0)
  218.   {
  219.     IntToUnicode (Device_Serial0, &USBD_StringSerial[2] ,8);
  220.     IntToUnicode (Device_Serial1, &USBD_StringSerial[18] ,4);
  221.   }
  222. }
  223.  
  224. /**
  225.   * @brief  Convert Hex 32Bits value into char 
  226.   * @param  value: value to convert
  227.   * @param  pbuf: pointer to the buffer 
  228.   * @param  len: buffer length
  229.   * @retval None
  230.   */
  231. static void IntToUnicode (uint32_t value , uint8_t *pbuf , uint8_t len)
  232. {
  233.   uint8_t idx = 0;
  234.   
  235.   for( idx = 0 ; idx < len ; idx ++)
  236.   {
  237.     if( ((value >> 28)) < 0xA )
  238.     {
  239.       pbuf[ 2* idx] = (value >> 28) + '0';
  240.     }
  241.     else
  242.     {
  243.       pbuf[2* idx] = (value >> 28) + 'A' - 10; 
  244.     }
  245.     
  246.     value = value << 4;
  247.     
  248.     pbuf[ 2* idx + 1] = 0;
  249.   }
  250. }
  251. /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
  252.  
复制代码
插一句: 开发USB设备,有很重要的一部分是编写描述符(当然也要借用已有的模板),设备叫什么,功能是什么等等都从描述符体现。只要设备向主机成功返回了描述符,主机就会提示找到硬件。

设计到U盘读写操作的部分在 usbd_storage_msd.c 里面,我就是在例子程序上改的
  1. /**
  2.   ******************************************************************************
  3.   * @file    usbd_storage_msd.c
  4.   * @author  MCD application Team
  5.   * @version V1.0.0
  6.   * @date    31-January-2014
  7.   * @brief   This file provides the disk operations functions.
  8.   ******************************************************************************
  9.   * @attention
  10.   *
  11.   * <h2><center>© COPYRIGHT 2014 STMicroelectronics</center></h2>
  12.   *
  13.   * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
  14.   * You may not use this file except in compliance with the License.
  15.   * You may obtain a copy of the License at:
  16.   *
  17.   *        http://www.st.com/software_license_agreement_liberty_v2
  18.   *
  19.   * Unless required by applicable law or agreed to in writing, software 
  20.   * distributed under the License is distributed on an "AS IS" BASIS, 
  21.   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  22.   * See the License for the specific language governing permissions and
  23.   * limitations under the License.
  24.   *
  25.   ******************************************************************************
  26.   */ 
  27. #include <string.h>
  28.  
  29. /* Includes ------------------------------------------------------------------*/
  30. #include "usbd_msc_mem.h"
  31.  
  32. /* Private typedef -----------------------------------------------------------*/
  33. /* Private define ------------------------------------------------------------*/
  34. #define STORAGE_LUN_NBR                  1 
  35.  
  36. /* Private macro -------------------------------------------------------------*/
  37. /* Private variables ---------------------------------------------------------*/
  38. /* USB Mass storage Standard Inquiry Data */
  39. const int8_t  STORAGE_Inquirydata[] = {
  40.   
  41.   /* LUN 0 */
  42.   0x00,     
  43.   0x80,     
  44.   0x02,     
  45.   0x02,
  46.   (USBD_STD_INQUIRY_LENGTH - 5),
  47.   0x00,
  48.   0x00, 
  49.   0x00,
  50.   'S', 'T', 'M', ' ', ' ', ' ', ' ', ' ', /* Manufacturer : 8 bytes */
  51.   'm', 'i', 'c', 'r', 'o', 'S', 'D', ' ', /* Product      : 16 Bytes */
  52.   'F', 'l', 'a', 's', 'h', ' ', ' ', ' ',
  53.   '1', '.', '0' ,'0',                     /* Version      : 4 Bytes */
  54. }; 
  55.  
  56. __IO uint32_t count = 0;
  57. /* Private function prototypes -----------------------------------------------*/
  58. int8_t STORAGE_Init (uint8_t lun);
  59.  
  60. int8_t STORAGE_GetCapacity (uint8_t lun, 
  61.                            uint32_t *block_num, 
  62.                            uint32_t *block_size);
  63.  
  64. int8_t  STORAGE_IsReady (uint8_t lun);
  65.  
  66. int8_t  STORAGE_IsWriteProtected (uint8_t lun);
  67.  
  68. int8_t STORAGE_Read (uint8_t lun, 
  69.                         uint8_t *buf, 
  70.                         uint32_t blk_addr,
  71.                         uint16_t blk_len);
  72.  
  73. int8_t STORAGE_Write (uint8_t lun, 
  74.                         uint8_t *buf, 
  75.                         uint32_t blk_addr,
  76.                         uint16_t blk_len);
  77.  
  78. int8_t STORAGE_GetMaxLun (void);
  79.  
  80.  
  81. USBD_STORAGE_cb_TypeDef USBD_MICRO_SDIO_fops =
  82. {
  83.   STORAGE_Init,
  84.   STORAGE_GetCapacity,
  85.   STORAGE_IsReady,
  86.   STORAGE_IsWriteProtected,
  87.   STORAGE_Read,
  88.   STORAGE_Write,
  89.   STORAGE_GetMaxLun,
  90.   (int8_t *)STORAGE_Inquirydata,
  91. };
  92.  
  93. USBD_STORAGE_cb_TypeDef  *USBD_STORAGE_fops = &USBD_MICRO_SDIO_fops;
  94.  
  95. /* Private functions ---------------------------------------------------------*/
  96.  
  97. /**
  98.   * @brief  Initialize the storage medium
  99.   * @param  lun : logical unit number
  100.   * @retval Status
  101.   */
  102.  
  103. uint8_t dummy_disk[20][512];
  104. uint16_t sec_index[20];     // sector usage
  105.  
  106. int8_t STORAGE_Init (uint8_t lun)
  107. {
  108.     static char init=0;
  109.     if(!init)
  110.     {
  111.         short int i;
  112.         for(i=0;i<20;i++)
  113.             sec_index[i]=0xffff;
  114.         init=1;
  115.     }
  116.   return (0);
  117. }
  118.  
  119. /**
  120.   * @brief  return medium capacity and block size
  121.   * @param  lun : logical unit number
  122.   * @param  block_num :  number of physical block
  123.   * @param  block_size : size of a physical block
  124.   * @retval Status
  125.   */
  126. int8_t STORAGE_GetCapacity (uint8_t lun, uint32_t *block_num, uint32_t *block_size)
  127.   
  128.   *block_size =  512;  
  129.   *block_num = 40*9;
  130.   
  131.   return (0);
  132. }
  133.  
  134. /**
  135.   * @brief  check whether the medium is ready
  136.   * @param  lun : logical unit number
  137.   * @retval Status
  138.   */
  139. int8_t  STORAGE_IsReady (uint8_t lun)
  140. {
  141.   static uint8_t status = 0;
  142.   
  143.   return (0);
  144. }
  145.  
  146. /**
  147.   * @brief  check whether the medium is write-protected
  148.   * @param  lun : logical unit number
  149.   * @retval Status
  150.   */
  151. int8_t  STORAGE_IsWriteProtected (uint8_t lun)
  152. {
  153.   return  0;
  154. }
  155.  
  156. /**
  157.   * @brief  Read data from the medium
  158.   * @param  lun : logical unit number
  159.   * @param  buf : Pointer to the buffer to save data
  160.   * @param  blk_addr :  address of 1st block to be read
  161.   * @param  blk_len : number of blocks to be read
  162.   * @retval Status
  163.   */
  164. int8_t STORAGE_Read (uint8_t lun, 
  165.                  uint8_t *buf, 
  166.                  uint32_t blk_addr,                       
  167.                  uint16_t blk_len)
  168. {
  169.     short int i;
  170.     for(i=0;i<blk_len;i++)
  171.     {
  172.         short int j;
  173.         for(j=0;j<20;j++)
  174.         {
  175.             if(sec_index[j]==blk_addr+i)
  176.             {
  177.                 memcpy(buf+i*512,dummy_disk[j],512);
  178.                 break;
  179.             }
  180.         }
  181.         if(j>=20)
  182.         {
  183.             for(j=0;j<512;j++)
  184.                 buf[i*512+j]=0x00;
  185.         }
  186.     }
  187. /*  if( SD_ReadMultiBlocks (buf, 
  188.                           blk_addr * 512, 
  189.                           512,
  190.                           blk_len) != 0)
  191.   {
  192.     return 5;
  193.   }
  194. */   
  195.   return 0;
  196. }
  197.  
  198. /**
  199.   * @brief  Write data to the medium
  200.   * @param  lun : logical unit number
  201.   * @param  buf : Pointer to the buffer to write from
  202.   * @param  blk_addr :  address of 1st block to be written
  203.   * @param  blk_len : number of blocks to be read
  204.   * @retval Status
  205.   */
  206. int8_t STORAGE_Write (uint8_t lun, 
  207.                   uint8_t *buf, 
  208.                   uint32_t blk_addr,
  209.                   uint16_t blk_len)
  210. {
  211.     short int i;
  212.     for(i=0;i<blk_len;i++)
  213.     {
  214.         short int j;
  215.         char zero=1;
  216.         unsigned char avail=0xff;
  217.         for(j=0;j<512;j++)
  218.             if(buf[j+i*512])
  219.                 zero=0;
  220.         for(j=0;j<20;j++)
  221.         {
  222.             if(sec_index[j]==blk_addr+i)
  223.                 break;
  224.             if(avail==0xff && sec_index[j]==0xffff)
  225.                 avail=j;
  226.         }
  227.         if(zero)
  228.         {
  229.             if(j<20)
  230.                 sec_index[j]=0xffff;    // free 
  231.             return 0;
  232.         }
  233.         if(j>=20)
  234.         {
  235.             if(avail<20)
  236.                 j=avail;
  237.             else    // No free sectors
  238.             {
  239.                 j=1+rand()%19;
  240.             }
  241.         }
  242.         memcpy(dummy_disk[j],buf+i*512,512);
  243.         sec_index[j]=blk_addr+i;
  244.     }
  245.   return (0);
  246. }
  247.  
  248. /**
  249.   * @brief  Return number of supported logical unit
  250.   * @param  None
  251.   * @retval number of logical unit
  252.   */
  253.  
  254. int8_t STORAGE_GetMaxLun (void)
  255. {
  256.   return (STORAGE_LUN_NBR - 1);
  257. }
  258. /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
  259.  
复制代码
主要是需要完成 报告容量、读、写 三个函数。如果有可实现存储的硬件,接口连起来即可。我上面是用了10kB的RAM来存放,动态分配20个扇区来存储。如果检测到要写的整个扇区都是0,那么就忽略。于是这样就做成了虚拟的U盘。

附件包含了所有需要的程序源代码,USB库的部分在lib子目录下面。build.bat 中是编译的命令。依靠这个USB函数库开发起来还算不难吧,只要看懂了例子,mass storage class还比较简单,因为硬件涉及就是读扇区、写扇区。 USB HID设备五花八门,就不是这么简单了,继续研究去。

              查看评论 回复

游客   2018-09-01 15:22:52
[color=#000000]stm32F042做usb价格高了一点。[/color]//回复:@匿名: 用stm32F042做usb接口还是很方便的,stm编译器的库很好用
1楼 回复本楼
匿名   2018-07-09 21:56:58
用stm32F042做usb接口还是很方便的,stm编译器的库很好用
2楼 回复本楼


嵌入式交流网主页 > 嵌入式处理器 > ARM > STM32 > stm32应用 > stm32F0xx USB存储盘设计
 

"stm32F0xx USB存储盘设计"的相关文章

网站地图

围观()