[RISC-V MCU 应用开发] 第八十四章、CH32V103应用教程——USB模拟U盘

[复制链接]
 楼主| RISCVLAR 发表于 2021-3-19 20:53 | 显示全部楼层 |阅读模式
CH32V103应用教程——USB模拟U盘
本章教程主要使用CH32V103 USB模拟U盘设备,此程序是移植而来,仅供参考。

1、USB简介及相关函数介绍
关于USB具体介绍,可参考前面章节。

2、硬件设计
本章教程主要进行USB模拟U盘设备,仅需用到开发板USB口。

3软件设计
本章程序全在主函数中进行,具体程序如下:
main.c文件
  1. /********************************** (C) COPYRIGHT *******************************
  2. * File Name          : main.c
  3. * Author             : WCH
  4. * Version            : V1.0.0
  5. * Date               : 2019/10/15
  6. * Description        : Main program body.
  7. *******************************************************************************/
  8. #include "debug.h"
  9. #include "string.h"

  10. #define DevEP0SIZE  0x40

  11. /* Device Descriptor */
  12. const UINT8  MyDevDescr[] =
  13. {
  14.         0x12,              //设备描述符长度,18字节
  15.         0x01,              //描述符类型,0x01为设备描述符
  16.         0x10, 0x01,        //本设备所使用USB版本协议,因为是小端结构,所以低字节在前,即USB1.1版本为0x10,0x01,USB2.0为0x00,0x02
  17.         0x00,              //类代码,此处不在设备描述符中定义设备类,而在接口描述符中定义设备类。对于大多数标准的USB设备类,该字段通常设置为0,而在接口描述符中的bInterfaceClass中指定接口所实现的功能
  18.         0x00,              //子类代码,当类代码bDeviceClass为0时,下面的子类代码bDeviceSubClass也必须为0。
  19.         0x00,              //设备所使用的协议,协议代码由USB协会规定。当该字段为0时,表示设备不使用类所定义的协议。
  20.         DevEP0SIZE,        //端点0的最大包长,可以取值8、16、32、64,此处为64字节
  21.         0x86, 0x1A,        //厂商ID
  22.         0x22, 0x57,        //产品设备ID
  23.         0x00, 0x01,        //设备版本号
  24.         0x01,              //描述厂商的字符串索引值。当该值为0时,表示没有厂商字符串
  25.         0x02,              //描述产品的字符串索引值。当该值为0时,表示没有产品字符串
  26.         0x03,              //描述设备的序列号字符串索引值。当该值为0时,表示没有序列号字符串
  27.         0x01,              //可能的配置数,通常为1
  28. };

  29. /* Configration Descriptor */
  30. const UINT8  MyCfgDescr[] =
  31. {
  32.         //配置描述符
  33.         0x09,              //配置描述符长度,标准USB配置描述符长度为9字节
  34.         0x02,              //描述符类型,配置描述符为0x02
  35.         0x20, 0x00,        //配置描述符集合总长度,32字节
  36.         0x01,              //该配置所支持的接口数,1个接口
  37.         0x01,              //表示该配置的值
  38.         0x00,              //描述该配置的字符串的索引值,0x00表示没有字符串
  39.         0xA0,              //描述设备的一些属性,如供电方式和唤醒等,0xA0表示设备总线供电且支持远程唤醒
  40.         0x32,              //设备需要从总线获取的最大电流量,0x32表示最大电流100ma

  41.         //接口描述符,接口描述符不能单独返回,必须附着在配置描述符后一并返回
  42.         0x09,              //接口描述符长度,标准的USB接口描述符长度为9字节
  43.         0x04,              //描述符类型,接口描述符为0x04
  44.         0x00,              //该接口的编号,从0开始,此处为0x00
  45.         0x00,              //该接口的备用编号,通常设置为0
  46.         0x02,              //该接口所使用的端点数,0x02表示使用2个端点。如果该字段为0,则表示没有非0端点,只使用默认的控制端点
  47.         0x08,              //该接口所使用的类,0x08为大容量存储设备类
  48.         0x06,              //该接口所使用的子类,0x06,即SCSI透明命令集
  49.         0x50,              //该接口所使用的协议,协议代码有3种:0x00、0x01、0x50,前两种需要使用中断传输,最后一种仅使用批量传输
  50.         0x00,              //该接口的字符串的索引值,0x00表示没有字符串

  51.         //端点描述符,端点描述符不能单独返回,必须附着在配置描述符后一并返回
  52.         0x07,              //端点描述符长度,标准的USB端点描述符长度为7字节
  53.         0x05,              //描述符类型,端点描述符为0x05
  54.         0x01,              //该端点的地址,0x01表示端点1作为输出,最高位D7为该端点的传输方向,1为输入,0为输出。D3-D0为端点号,可设置为0-7,D6-4保留,设为0.
  55.         //关于端点属性,最低两位D1-0表示该端点的传输类型,0为控制传输,1为等时传输,2为批量传输,3为中断传输。
  56.         0x02,              //该端点的属性,此处为批量传输方式
  57.         DevEP0SIZE, 0x00,  //该端点支持的最大包长度,此处设置为64字节
  58.         0x00,              //端点的查询时间

  59.         //端点描述符,端点描述符不能单独返回,必须附着在配置描述符后一并返回
  60.         0x07,              //端点描述符长度,标准的USB端点描述符长度为7字节
  61.         0x05,              //描述符类型,端点描述符为0x05
  62.         0x81,              //该端点的地址,0x81表示端点1作为输入,最高位D7为该端点的传输方向,1为输入,0为输出。D3-D0为端点号,可设置为0-7,D6-4保留,设为0.
  63.         //关于端点属性,最低两位D1-0表示该端点的传输类型,0为控制传输,1为等时传输,2为批量传输,3为中断传输。
  64.         0x02,              //该端点的属性,此处为批量传输方式
  65.         DevEP0SIZE, 0x00,  //该端点支持的最大包长度,此处设置为64字节
  66.         0x00,              //端点的查询时间
  67. };

  68. const UINT8 MyProductIDInfo[] =
  69. {
  70.         0x14,0x03, 0x32,0x00,0x30,0x00,0x31,0x00,0x37,0x00,0x2D,0x00,0x32,0x00,0x2D,0x00,0x32,0x00,0x35,0x00
  71. };
  72. /* Language Descriptor */
  73. const UINT8  MyLangDescr[] = { 0x04, 0x03, 0x09, 0x04 };

  74. /* Manufactor Descriptor */
  75. const UINT8  MyManuInfo[] = { 0x0A,0x03,0x5F,0x6c,0xCF,0x82,0x81,0x6c,0x52,0x60 };

  76. /* Product Information */
  77. const UINT8  MyProdInfo[] = {0x14,0x03,0x43,0x00,0x48,0x00,0x35,0x00,0x35,0x00,0x34,0x00,0x5F,0x00,0x43,0x00,0x44,0x00,0x43,0x00, };

  78. //Get Max LUN 请求,该字节表示设备有多少个逻辑单元,值为0时表示有一个逻辑单元,值为1时表示有两个逻辑单元,以此类推,最大可以取15
  79. //定义一个最大逻辑单元的变量,跟描述符类型一样,使用数组的方式来定义,尽管他只有一个元素。
  80. const UINT8  MAX_LUN[] = {0};

  81. //INQUIRY inform
  82. const UINT8 DBINQUITY[]=
  83. {
  84.                         0x00,           //Peripheral Device Type
  85.                         0x80,           //
  86.                         0x02 ,          //ISO/ECMA
  87.                         0x02 ,          //
  88.                         0x1f ,          //Additional Length

  89.                         00 ,            //Reserved
  90.                         00 ,            //Reserved
  91.                         00 ,            //Reserved

  92.                         'w' ,           //Vendor Information
  93.                         'c' ,           //
  94.                         'h' ,           //
  95.                         '.' ,           //
  96.                         'c' ,           //
  97.                         'n' ,           //
  98.                         ' ' ,           //
  99.                         ' ' ,           //

  100.                         0xc7,           //Product Identification
  101.                         0xdf,           //
  102.                         0xba,           //
  103.                         0xe3,           //
  104.                         0xb5,           //
  105.                         0xe7,           //
  106.                         0xd7,           //
  107.                         0xd3,           //
  108.                         0x55,           //
  109.                         0xc5,           //
  110.                         0xcc,           //
  111.                         0xb7,           //
  112.                         0xbd,           //
  113.                         0xb0,           //
  114.                         0xb8,           //
  115.                         0x00,           //

  116.                         '1' ,           //Product Revision Level
  117.                         '.' ,           //
  118.                         '1' ,           //
  119.                         '0'             //
  120. };

  121. #define NUMOFBLOCK      0x40
  122. #define LASTLGCBLOCK    0x3f

  123. const UINT8 DBCAPACITY[]={(LASTLGCBLOCK>>24)&0xFF,(LASTLGCBLOCK>>16)&0xFF,(LASTLGCBLOCK>>8)&0xFF,LASTLGCBLOCK&0xFF,0x00,0x00,0x02,0x00};
  124. const UINT8 modesense3F[]={0x0b, 0x00, 0x00/*0x80*/, 0x08 , (NUMOFBLOCK>>24)&0xFF,(NUMOFBLOCK>>16)&0xFF,(NUMOFBLOCK>>8)&0xFF,NUMOFBLOCK&0xFF,0x00, 0x00, 0x02, 0x00 };   //写保护(0x80换成0x00可以去除写保护)

  125. //DBR(DOS Boot Record):磁盘操作系统引导记录
  126. //DBR是每个逻辑分区的一个引导记录,里面记录了该分区的众多重要信息以及引导代码,所以十分重要。在U盘系统中,必须有DBR
  127. //DBR占据逻辑分区的0扇区,大小通常为512字节,DBR各个部分的意义见《圈圈教你玩USB》
  128. const UINT8 DBR[512]=
  129. {
  130.                  0xeb,0x3c,0x90,0x4d,0x53,0x44,0x4f,0x53, 0x35,0x2e,0x30,0x00,0x02,0x01,0x06,0x00,
  131.                  0x02,0x00,0x02,NUMOFBLOCK&0xff,(NUMOFBLOCK>>8)&0xff,0xf8,0x01,0x00, 0x01,0x00,0x01,0x00,0x00,0x00,0x00,0x00,
  132.                  0x00,0x00,0x00,0x00,0x80,0x00,0x29,0xc3, 0xa5,0x20,0xd8,0x4e,0x4f,0x20,0x4e,0x41,
  133.                  0x4d,0x45,0x20,0x20,0x20,0x20,0x46,0x41, 0x54,0x31,0x32,0x20,0x20,0x20,0x00,0x00,
  134.                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  135.                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  136.                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  137.                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  138.                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  139.                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  140.                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  141.                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  142.                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  143.                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  144.                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  145.                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  146.                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  147.                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  148.                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  149.                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  150.                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  151.                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  152.                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  153.                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  154.                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  155.                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  156.                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  157.                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  158.                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  159.                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  160.                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  161.                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x55,0xaa,
  162. };

  163. //FAT(File Allocation Table):文件分配表
  164. //在DBR之后,就是FAT区(通常有两个,一个为副本)
  165. const UINT8 FAT[512]=
  166. {
  167.                  0xF8,0xFF,0xFF,0xFF,0x0F,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  168.                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  169.                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  170.                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  171.                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  172.                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  173.                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  174.                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  175.                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  176.                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  177.                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  178.                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  179.                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  180.                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  181.                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  182.                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  183.                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  184.                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  185.                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  186.                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  187.                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  188.                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  189.                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  190.                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  191.                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  192.                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  193.                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  194.                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  195.                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  196.                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  197.                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  198.                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  199. };

  200. const UINT8 ZERO[512]=
  201. {
  202.                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  203.                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  204.                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  205.                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  206.                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  207.                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  208.                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  209.                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  210.                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  211.                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  212.                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  213.                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  214.                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  215.                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  216.                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  217.                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  218.                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  219.                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  220.                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  221.                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  222.                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  223.                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  224.                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  225.                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  226.                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  227.                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  228.                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  229.                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  230.                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  231.                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  232.                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  233.                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  234. };

  235. //UFI通讯
  236. #define FORMAT_UNIT     0x04
  237. #define INQUIRY         0x12
  238. #define FORMATCAP       0x23
  239. #define MODE_SELECT     0x15
  240. #define MODE_SENSE5     0x5A
  241. #define MODE_SENSE      0x1A
  242. #define PER_RES_IN      0x5E
  243. #define PER_RES_OUT     0x5F
  244. #define PRE_OR_MED      0x1E
  245. #define READ            0x28
  246. #define READ_CAPACITY   0x25
  247. #define RELEASE         0x17
  248. #define REQUEST_SENSE   0x03
  249. #define RESERVE         0x16
  250. #define STA_STO_UNIT    0x1B
  251. #define SYN_CACHE       0x35
  252. #define TEST_UNIT       0x00
  253. #define VERIFY          0x2F
  254. #define WRITE           0x2A
  255. #define WRITE_BUFFER    0x3B

  256. typedef union _CBWCB
  257. {
  258.     unsigned char buf1[16];
  259. }CBWCB;
  260. typedef  union _MASS_PARA
  261. {
  262.     unsigned char buf[64];
  263.     struct  _SENSE
  264.     {
  265.         unsigned char ErrorCode;
  266.         unsigned char Reserved1;
  267.         unsigned char SenseKey;
  268.         unsigned char Information[4];
  269.         unsigned char AddSenseLength;
  270.         unsigned char Reserved2[4];
  271.         unsigned char AddSenseCode;
  272.         unsigned char AddSenseCodeQua;
  273.         unsigned char Reserved3[4];
  274.     }Sense;
  275.     struct  _CBW
  276.     {
  277.         unsigned char dCBWsig[4];
  278.         unsigned char dCBWTag[4];
  279.         unsigned long dCBWDatL;
  280.         unsigned char bmCBWFlags;
  281.         unsigned char bCBWLUN;
  282.         unsigned char bCBWCBLength;
  283.         CBWCB         cbwcb;
  284.     }cbw;
  285.     struct _CSW
  286.     {
  287.         unsigned char buf2[13];
  288.     }csw;
  289. }MASS_PARA;

  290. union {
  291. unsigned long mDataLength;                   //数据长度
  292. unsigned char mdataLen[4];                   //
  293. } UFI_Length;
  294. unsigned char mdCBWTag[4];                   //dCBWTag
  295. MASS_PARA  MassPara;
  296. UINT8 CH32BULKUP=0;                          //数据上传
  297. UINT8 CH32BULKDOWN = 0;                      //数据下传
  298. UINT8 CH32CSW=0;                             //CSW上传标志
  299. unsigned char  BcswStatus;                   //CSW状态
  300. unsigned char  mSenseKey;
  301. unsigned char  mASC;

  302. unsigned char *pBuf;

  303. unsigned long SecNum;                        //当前操作的扇区号

  304. unsigned char dat_tran_flag = 0;
  305. /**********************************************************/
  306. UINT8   Ready = 0;
  307. UINT8   UsbConfig;
  308. UINT8   SetupReqCode;
  309. UINT16  SetupReqLen;
  310. //cdc参数
  311. UINT8 LineCoding[7]={0x00,0xe1,0x00,0x00,0x00,0x00,0x08};   //初始化波特率为57600,1停止位,无校验,8数据位。

  312. #define  SET_LINE_CODING                0x20            // Configures DTE rate, stop-bits, parity, and number-of-character
  313. #define  GET_LINE_CODING                0x21            // This request allows the host to find out the currently configured line coding.
  314. #define  SET_CONTROL_LINE_STATE         0x22            // This request generates RS-232/V.24 style control signals.

  315. volatile UINT8 UpPoint2_Busy  = 0;    //上传端点是否忙标志

  316. const UINT8 *pDescr;

  317. /* Endpoint Buffer */
  318. __attribute__ ((aligned(4)))  UINT8 EP0_Databuf[64+64+64]; //ep0(64)+ep4_out(64)+ep4_in(64)
  319. __attribute__ ((aligned(4)))  UINT8 EP1_Databuf[64+64];    //ep1_out(64)+ep1_in(64)
  320. __attribute__ ((aligned(4)))  UINT8 EP2_Databuf[64+64];    //ep2_out(64)+ep2_in(64)
  321. __attribute__ ((aligned(4)))  UINT8 EP3_Databuf[64+64];    //ep3_out(64)+ep3_in(64)

  322. void USBHD_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));

  323. /*******************************************************************************
  324. * Function Name  : UFI_Hunding
  325. * Description    : 命令的分类与识别 UFI  CMD
  326. * Input          : None
  327. * Output         : None
  328. * Return         : None
  329. *******************************************************************************/
  330. void UFI_Hunding(void )
  331. {
  332.         switch(MassPara.cbw.cbwcb.buf1[0])
  333.         {
  334.             //查询命令 INQUIRY,操作代码为0x12
  335.             case INQUIRY:
  336.                 pBuf = (UINT8 *)DBINQUITY;                                                        //查询U盘信息
  337.                 if(UFI_Length.mDataLength>sizeof(DBINQUITY)) UFI_Length.mDataLength=sizeof(DBINQUITY);
  338.                 BcswStatus=0;
  339.                 mSenseKey=0;
  340.                 mASC=0;
  341.                 break;

  342.             //主机通常使用WRITE命令往设备写入实际的磁盘数据,操作代码为0x2A
  343.             case WRITE:
  344.                 UFI_Length.mDataLength=(((UINT32)MassPara.cbw.cbwcb.buf1[7]<<8) | (UINT32)MassPara.cbw.cbwcb.buf1[8])*512;  //发送长度
  345.                 SecNum = ((UINT32)MassPara.cbw.cbwcb.buf1[2]<<24) | ((UINT32)MassPara.cbw.cbwcb.buf1[3]<<16) | ((UINT32)MassPara.cbw.cbwcb.buf1[4]<<8) | (UINT32)MassPara.cbw.cbwcb.buf1[5];//起始扇区号
  346.                 dat_tran_flag = 1;
  347.                 BcswStatus=0;
  348.                 mSenseKey=0;
  349.                 mASC=0;
  350.                 break;
  351.             case PRE_OR_MED:

  352.             case TEST_UNIT:

  353.             case 0x3b:
  354.                 CH32BULKDOWN=0;
  355.                 CH32BULKUP=0;
  356.                 BcswStatus=0;
  357.                 mSenseKey=0;
  358.                 mASC=0;
  359.                 break;

  360.             //主机通常使用READ命令来读取实际的磁盘数据,操作代码为0x28
  361.             case READ:
  362.                 UFI_Length.mDataLength=(((UINT32)MassPara.cbw.cbwcb.buf1[7]<<8) | (UINT32)MassPara.cbw.cbwcb.buf1[8])*512;  //发送长度
  363.                 SecNum = ((UINT32)MassPara.cbw.cbwcb.buf1[2]<<24) | ((UINT32)MassPara.cbw.cbwcb.buf1[3]<<16) | ((UINT32)MassPara.cbw.cbwcb.buf1[4]<<8) | (UINT32)MassPara.cbw.cbwcb.buf1[5];//起始扇区号
  364.                 dat_tran_flag = 1;
  365.                 BcswStatus=0;
  366.                 mSenseKey=0;
  367.                 mASC=0;
  368.                 break;

  369.             //REQUEST SENSE命令用来探测上一个命令执行失败的原因,主机可在每个命令之后使用该命令来读取命令执行的情况,其命令代码为0x03
  370.             case REQUEST_SENSE:
  371.                 MassPara.Sense.ErrorCode=0x70;
  372.                 MassPara.Sense.Reserved1=0;
  373.                 MassPara.Sense.SenseKey=mSenseKey;
  374.                 MassPara.Sense.Information[0]=0;
  375.                 MassPara.Sense.Information[1]=0;
  376.                 MassPara.Sense.Information[2]=0;
  377.                 MassPara.Sense.Information[3]=0;
  378.                 MassPara.Sense.AddSenseLength=0x0a;
  379.                 MassPara.Sense.Reserved2[0]=0;
  380.                 MassPara.Sense.Reserved2[1]=0;
  381.                 MassPara.Sense.Reserved2[2]=0;
  382.                 MassPara.Sense.Reserved2[3]=0;
  383.                 MassPara.Sense.AddSenseCode=mASC;
  384.                 MassPara.Sense.AddSenseCodeQua=0;
  385.                 MassPara.Sense.Reserved3[0]=0;
  386.                 MassPara.Sense.Reserved3[1]=0;
  387.                 MassPara.Sense.Reserved3[2]=0;
  388.                 MassPara.Sense.Reserved3[3]=0;
  389.                 pBuf=MassPara.buf;
  390.                 if ( UFI_Length.mDataLength > 18 ) UFI_Length.mDataLength = 18;
  391.                 BcswStatus=0;
  392.                 mSenseKey=0;
  393.                 mASC=0;
  394.                 break;

  395.             //读容量命令,可以让主机读取到当前存储媒介的容量,此命令读到的才是实际的磁盘容量
  396.             case READ_CAPACITY:
  397.                 if ( UFI_Length.mDataLength > sizeof(DBCAPACITY) ) UFI_Length.mDataLength = sizeof(DBCAPACITY);
  398.                 pBuf=(unsigned char*)DBCAPACITY;
  399.                 BcswStatus=0;
  400.                 mSenseKey=0;
  401.                 mASC=0;
  402.                 break;

  403.             case MODE_SENSE:
  404.                 if ( UFI_Length.mDataLength > sizeof(modesense3F) ) UFI_Length.mDataLength = sizeof(modesense3F);
  405.                 pBuf=(unsigned char*)modesense3F;
  406.                 BcswStatus=0;
  407.                 mSenseKey=0;
  408.                 mASC=0;
  409.                 break;
  410.             default:
  411.                 mSenseKey=5;
  412.                 if (MassPara.cbw.cbwcb.buf1[0] == FORMATCAP)
  413.                     mASC=0x20;
  414.                 else
  415.                     mASC=0x24;
  416.                 BcswStatus=1;
  417.                 if(CH32BULKUP)
  418.                 {
  419.                     R8_UEP1_CTRL = R8_UEP1_CTRL | UEP_T_RES_STALL;
  420.                 }
  421.                 else
  422.                 {
  423.                     R8_UEP1_CTRL = R8_UEP1_CTRL | UEP_R_RES_STALL;
  424.                 }
  425.                 break;
  426.             }
  427. }
  428. /*******************************************************************************
  429. * Function Name  : mCH32UpCsw
  430. * Description    : 批量协议状态上传
  431. * Input          : None
  432. * Output         : None
  433. * Return         : None
  434. *******************************************************************************/
  435. void mCH32UpCsw()
  436. {
  437.     unsigned char i;                                                   //如果数据为0
  438.     pBuf=&MassPara.buf[0];
  439.     CH32CSW=0;                                                         //上传CSW
  440.     CH32BULKUP=0;                                                      //取消数据上传
  441.     MassPara.buf[0]=0x55;                                              //dCSWSignature
  442.     MassPara.buf[1]=0x53;
  443.     MassPara.buf[2]=0x42;
  444.     MassPara.buf[3]=0x53;
  445.     MassPara.buf[4]=mdCBWTag[0];
  446.     MassPara.buf[5]=mdCBWTag[1];
  447.     MassPara.buf[6]=mdCBWTag[2];
  448.     MassPara.buf[7]=mdCBWTag[3];
  449.     MassPara.buf[8]=UFI_Length.mdataLen[3];
  450.     MassPara.buf[9]=UFI_Length.mdataLen[2];
  451.     MassPara.buf[10]=UFI_Length.mdataLen[1];
  452.     MassPara.buf[11]=UFI_Length.mdataLen[0];
  453.     MassPara.buf[12]=BcswStatus;
  454.     for(i = 0;i<13;i++)
  455.     {
  456.         pEP1_RAM_Addr[MAX_PACKET_SIZE+i] = *pBuf;
  457.         pBuf++;
  458.     }
  459.     R8_UEP1_T_LEN = 13;
  460.     R8_UEP1_CTRL = (R8_UEP1_CTRL & ~ MASK_UEP_T_RES) | UEP_T_RES_ACK;          // 允许上传
  461. }
  462. /*******************************************************************************
  463. * Function Name  : mCH32BulkOnly
  464. * Description    : 批量协议处理
  465. * Input          : None
  466. * Output         : None
  467. * Return         : None
  468. *******************************************************************************/
  469. void mCH32BulkOnly(){
  470.     if(MassPara.buf[0]==0x55){
  471.         if(MassPara.buf[1]==0x53){
  472.            if(MassPara.buf[2]==0x42){
  473.                 if(MassPara.buf[3]==0x43){
  474.                     UFI_Length.mdataLen[3] = *(unsigned char *)(&MassPara.cbw.dCBWDatL);             /* 将PC机的低字节在前的16位字数据转换为C51的高字节在前的数据 */
  475.                     UFI_Length.mdataLen[2] = *( (unsigned char *)(&MassPara.cbw.dCBWDatL) + 1 );
  476.                     UFI_Length.mdataLen[1] = *( (unsigned char *)(&MassPara.cbw.dCBWDatL) + 2 );
  477.                     UFI_Length.mdataLen[0] = *( (unsigned char *)(&MassPara.cbw.dCBWDatL) + 3 );
  478.                     mdCBWTag[0]=MassPara.buf[4];
  479.                     mdCBWTag[1]=MassPara.buf[5];
  480.                     mdCBWTag[2]=MassPara.buf[6];
  481.                     mdCBWTag[3]=MassPara.buf[7];                                            //取出数据长度
  482.                     if(UFI_Length.mDataLength){
  483.                             CH32BULKDOWN=(MassPara.cbw.bmCBWFlags&0X80)?0:1;                //判断是上传还是下传数据
  484.                             CH32BULKUP=(MassPara.cbw.bmCBWFlags&0X80)?1:0;
  485.                         }
  486.                         CH32CSW=1;
  487.                         dat_tran_flag = 0; //数据传输标志位先清零
  488.                         UFI_Hunding();                                                      //调用UFI协议处理
  489.                }
  490.                 else
  491.                 R8_UEP1_CTRL = R8_UEP1_CTRL | UEP_T_RES_STALL ;
  492.           }
  493.            else
  494.             R8_UEP1_CTRL = R8_UEP1_CTRL | UEP_T_RES_STALL ;
  495.          }
  496.         else
  497.         R8_UEP1_CTRL = R8_UEP1_CTRL | UEP_T_RES_STALL ;
  498.      }
  499.     else
  500.     R8_UEP1_CTRL = R8_UEP1_CTRL | UEP_T_RES_STALL ;
  501. }

  502. /*******************************************************************************
  503. * Function Name  : CH32bulkUpData
  504. * Description    : 批量协议上传
  505. * Input          : None
  506. * Output         : None
  507. * Return         : None
  508. *******************************************************************************/
  509. unsigned char file_dat[64]; //文件大小固定64字节

  510. //文件前四个字节(16H 75H 73H 62H) //测试阶段暂用“fusb”

  511. void CH32bulkUpData()
  512. {                                //调用端点1上传数据
  513.     unsigned char len,i;
  514.     unsigned char rootdir = 0;   //当前读目录项标志
  515.     unsigned char datfield = 0;  //数据区标志
  516.     //根据读取的地址,分析是否切换pBuf
  517.     if(dat_tran_flag)
  518.     {
  519.         if((UFI_Length.mDataLength&0x1ff)==0)
  520.         {
  521.             if(SecNum==0)
  522.             {
  523.                 pBuf = (UINT8 *)DBR;
  524.             }
  525.             else if(SecNum==6 || SecNum==7)
  526.             {
  527.                 pBuf = (UINT8 *)FAT;
  528.             }
  529.             else
  530.             {
  531.                 pBuf = (UINT8 *)ZERO;
  532.             }
  533.             if(SecNum == 8)
  534.             {
  535.                 rootdir = 1;
  536.             }
  537.             if(SecNum==40)
  538.             {
  539.                 datfield = 1;
  540.             }
  541.             SecNum++;
  542.         }
  543.     }

  544.     if(UFI_Length.mDataLength>MAX_PACKET_SIZE)
  545.     {
  546.         len=MAX_PACKET_SIZE;
  547.         UFI_Length.mDataLength-=MAX_PACKET_SIZE;
  548.     }
  549.     else
  550.     {
  551.         len= (unsigned char) UFI_Length.mDataLength;
  552.         UFI_Length.mDataLength=0;
  553.         CH32BULKUP=0;
  554.     }

  555.     for(i = 0;i<len;i++)
  556.     {
  557.         pEP1_RAM_Addr[MAX_PACKET_SIZE+i] = *pBuf;
  558.         pBuf++;
  559.     }
  560.     /* 改写 */
  561.     if(rootdir)       /* 改写根目录 */
  562.     {
  563.         memcpy(&pEP1_RAM_Addr[MAX_PACKET_SIZE],"WCH_CFG TXT ",12);
  564.         pEP1_RAM_Addr[MAX_PACKET_SIZE+0x1A]=2;
  565.         pEP1_RAM_Addr[MAX_PACKET_SIZE+0x1C]= 64;
  566.     }
  567.     if(datfield)      /* 改写数据区 */
  568.     {
  569.         //ReadDataFlash(0,64,&pEP1_RAM_Addr[MAX_PACKET_SIZE]);
  570.     }
  571.     R8_UEP1_T_LEN = len;
  572.     R8_UEP1_CTRL = (R8_UEP1_CTRL & ~ MASK_UEP_T_RES) | UEP_T_RES_ACK;        // 允许上传
  573. }
  574. void mCH32BulkDownData()
  575. {
  576.     UINT8 len;
  577.     len = R8_USB_RX_LEN;
  578.     if(dat_tran_flag)   //传输数据
  579.     {
  580.         if((UFI_Length.mDataLength&0x1ff)==0)
  581.         {
  582.             if((pEP1_RAM_Addr[0]=='f') && (memcmp(&pEP1_RAM_Addr[1],"usb",3)==0))
  583.             {
  584.                 //FLASH_Write(0,&pEP1_RAM_Addr[0],64);   //同时写入Flash
  585.             }
  586.         }
  587.     }
  588.     UFI_Length.mDataLength-=len;
  589.     if(UFI_Length.mDataLength==0)
  590.     {
  591.         CH32BULKDOWN=0;
  592.         mCH32UpCsw();
  593.     }
  594. }
  595. /*******************************************************************************
  596. * Function Name  : USB_DevTransProcess
  597. * Description    : USB device transfer process.
  598. * Input          : None
  599. * Return         : None
  600. *******************************************************************************/
  601. void USB_DevTransProcess( void )
  602. {
  603.     UINT8  len, length, chtype;
  604.     UINT8  intflag, errflag = 0;

  605.     intflag = R8_USB_INT_FG;

  606.     if( intflag & RB_UIF_TRANSFER )
  607.     {
  608.         switch ( R8_USB_INT_ST & ( MASK_UIS_TOKEN | MASK_UIS_ENDP ) )
  609.         {
  610.             case UIS_TOKEN_SETUP:
  611.                 R8_UEP0_CTRL = RB_UEP_R_TOG | RB_UEP_T_TOG | UEP_R_RES_ACK | UEP_T_RES_NAK;
  612.                 len = R8_USB_RX_LEN;
  613.                 if ( len == sizeof( USB_SETUP_REQ ) )
  614.                 {
  615.                     SetupReqLen = pSetupReqPak->wLength;
  616.                     SetupReqCode = pSetupReqPak->bRequest;
  617.                     chtype = pSetupReqPak->bRequestType;
  618.                     len = 0;
  619.                     errflag = 0;
  620.                     if ( ( pSetupReqPak->bRequestType & USB_REQ_TYP_MASK ) != USB_REQ_TYP_STANDARD )
  621.                     {
  622.                         if(SetupReqCode == 0xFE)                                   //GET MAX LUN
  623.                         {
  624.                             pDescr = (PUINT8)( &MAX_LUN[0] );
  625.                             len = 1;
  626.                             if ( SetupReqLen > len )
  627.                             {
  628.                                 SetupReqLen = len;                                 // 限制总长度
  629.                             }
  630.                             len = SetupReqLen >= DEFAULT_ENDP0_SIZE ? DEFAULT_ENDP0_SIZE : SetupReqLen;  // 本次传输长度
  631.                             memcpy( pEP0_RAM_Addr, pDescr, len );                  /* 加载上传数据 */
  632.                             //SetupLen -= len;
  633.                             pDescr += len;
  634.                         }
  635.                         else
  636.                             errflag = 0xFF;
  637.                     }
  638.                     else
  639.                     {
  640.                         switch( SetupReqCode )
  641.                         {
  642.                             case USB_GET_DESCRIPTOR:
  643.                             {
  644.                                 switch( ((pSetupReqPak->wValue)>>8) )
  645.                                 {
  646.                                     case USB_DESCR_TYP_DEVICE:
  647.                                         pDescr = MyDevDescr;
  648.                                         len = MyDevDescr[0];
  649.                                         break;

  650.                                     case USB_DESCR_TYP_CONFIG:
  651.                                         pDescr = MyCfgDescr;
  652.                                         len = MyCfgDescr[2];
  653.                                         break;

  654.                                     case USB_DESCR_TYP_STRING:
  655.                                         switch( (pSetupReqPak->wValue)&0xff )
  656.                                         {
  657.                                             case 1:
  658.                                                 pDescr = MyManuInfo;
  659.                                                 len = MyManuInfo[0];
  660.                                                 break;

  661.                                             case 2:
  662.                                                 pDescr = MyProdInfo;
  663.                                                 len = MyProdInfo[0];
  664.                                                 break;

  665.                                             case 0:
  666.                                                 pDescr = MyLangDescr;
  667.                                                 len = MyLangDescr[0];
  668.                                                 break;

  669.                                             case 3:
  670.                                                 pDescr = (PUINT8)( &MyProductIDInfo[0] );
  671.                                                 len = sizeof( MyProductIDInfo );
  672.                                                 break;

  673.                                             default:
  674.                                                 errflag = 0xFF;
  675.                                                 break;
  676.                                         }
  677.                                         break;

  678.                                     default :
  679.                                         errflag = 0xff;
  680.                                         break;
  681.                                 }

  682.                                 if( SetupReqLen>len )   SetupReqLen = len;
  683.                                 len = (SetupReqLen >= DevEP0SIZE) ? DevEP0SIZE : SetupReqLen;
  684.                                 memcpy( pEP0_DataBuf, pDescr, len );
  685.                                 //SetupReqLen -= len;
  686.                                 pDescr += len;
  687.                             }
  688.                             break;

  689.                             case USB_SET_ADDRESS:
  690.                                 SetupReqLen = (pSetupReqPak->wValue)&0xff;
  691.                                 break;

  692.                             case USB_GET_CONFIGURATION:
  693.                                 pEP0_DataBuf[0] = UsbConfig;
  694.                                 if ( SetupReqLen > 1 ) SetupReqLen = 1;
  695.                                 break;

  696.                             case USB_SET_CONFIGURATION:
  697.                                 UsbConfig = (pSetupReqPak->wValue)&0xff;
  698.                                 break;

  699.                             case USB_CLEAR_FEATURE:
  700.                                 if( ( pSetupReqPak->bRequestType & 0x1F ) == USB_REQ_RECIP_DEVICE )                  /* 清除设备 */
  701.                                 {
  702.                                     if((pSetupReqPak->wValue) == 0x01 )
  703.                                     {
  704.                                         if( MyCfgDescr[ 7 ] & 0x20 )
  705.                                         {
  706.                                             /* 唤醒 */
  707.                                         }
  708.                                         else
  709.                                         {
  710.                                             errflag = 0xFF;                                        /* 操作失败 */
  711.                                         }
  712.                                     }
  713.                                     else
  714.                                     {
  715.                                         errflag = 0xFF;                                            /* 操作失败 */
  716.                                     }
  717.                                 }
  718.                                 else if ( ( pSetupReqPak->bRequestType & USB_REQ_RECIP_MASK ) == USB_REQ_RECIP_ENDP )
  719.                                 {
  720.                                     switch( (pSetupReqPak->wIndex)&0xff )
  721.                                     {
  722.                                         case 0x83:
  723.                                             R8_UEP3_CTRL = (R8_UEP3_CTRL & ~ ( RB_UEP_T_TOG | MASK_UEP_T_RES )) | UEP_T_RES_NAK;
  724.                                             break;

  725.                                         case 0x03:
  726.                                             R8_UEP3_CTRL = (R8_UEP3_CTRL & ~ ( RB_UEP_T_TOG | MASK_UEP_R_RES )) | UEP_R_RES_ACK;
  727.                                             break;

  728.                                         case 0x82:
  729.                                             R8_UEP2_CTRL = (R8_UEP2_CTRL & ~( RB_UEP_T_TOG|MASK_UEP_T_RES )) | UEP_T_RES_NAK;
  730.                                             break;

  731.                                         case 0x02:
  732.                                             R8_UEP2_CTRL = (R8_UEP2_CTRL & ~( RB_UEP_R_TOG|MASK_UEP_R_RES )) | UEP_R_RES_ACK;
  733.                                             break;

  734.                                         case 0x81:
  735.                                             R8_UEP1_CTRL = (R8_UEP1_CTRL & ~( RB_UEP_T_TOG|MASK_UEP_T_RES )) | UEP_T_RES_NAK;
  736.                                             if(CH32CSW)
  737.                                             {
  738.                                                 CH32CSW=0;
  739.                                                 mCH32UpCsw();
  740.                                             }
  741.                                             break;

  742.                                         case 0x01:
  743.                                             R8_UEP1_CTRL = (R8_UEP1_CTRL & ~( RB_UEP_R_TOG|MASK_UEP_R_RES )) | UEP_R_RES_ACK;
  744.                                             if(CH32CSW)
  745.                                             {
  746.                                                 CH32CSW = 0;
  747.                                                 mCH32UpCsw();
  748.                                             }
  749.                                             break;

  750.                                         default:
  751.                                             errflag = 0xFF;
  752.                                             break;

  753.                                     }
  754.                                 }
  755.                                 else    errflag = 0xFF;
  756.                                 break;

  757.                             case USB_SET_FEATURE:                                          /* Set Feature */
  758.                                 if( ( pSetupReqPak->bRequestType & 0x1F ) == USB_REQ_RECIP_DEVICE )                  /* 设置设备 */
  759.                                 {
  760.                                     if(( pSetupReqPak->wValue) == 0x01 )
  761.                                     {
  762.                                         if( MyCfgDescr[ 7 ] & 0x20 )
  763.                                         {
  764.                                             ;
  765.                                         }
  766.                                         else
  767.                                         {
  768.                                             errflag = 0xFF;                                        /* 操作失败 */
  769.                                         }
  770.                                     }
  771.                                     else
  772.                                     {
  773.                                         errflag = 0xFF;                                            /* 操作失败 */
  774.                                     }
  775.                                 }
  776.                                 else if( ( pSetupReqPak->bRequestType & 0x1F ) == USB_REQ_RECIP_ENDP )             /* 设置端点 */
  777.                                 {
  778.                                     if(( pSetupReqPak->wValue) == 0x00 )
  779.                                     {
  780.                                         switch(pSetupReqPak->wIndex)
  781.                                         {
  782.                                             case 0x83:
  783.                                                 R8_UEP3_CTRL = (R8_UEP3_CTRL & (~RB_UEP_R_TOG)) | UEP_T_RES_STALL;/* 设置端点3 IN STALL */
  784.                                                 break;
  785.                                             case 0x03:
  786.                                                 R8_UEP3_CTRL = (R8_UEP3_CTRL & (~RB_UEP_R_TOG)) | UEP_R_RES_STALL;/* 设置端点3 OUT Stall */
  787.                                                 break;
  788.                                             case 0x82:
  789.                                                 R8_UEP2_CTRL = (R8_UEP2_CTRL & (~RB_UEP_R_TOG)) | UEP_T_RES_STALL;/* 设置端点2 IN STALL */
  790.                                                 break;
  791.                                             case 0x02:
  792.                                                 R8_UEP2_CTRL = (R8_UEP2_CTRL & (~RB_UEP_R_TOG)) | UEP_R_RES_STALL;/* 设置端点2 OUT Stall */
  793.                                                 break;
  794.                                             case 0x81:
  795.                                                 R8_UEP1_CTRL = (R8_UEP1_CTRL & (~RB_UEP_R_TOG)) | UEP_T_RES_STALL;/* 设置端点1 IN STALL */
  796.                                                 break;
  797.                                             case 0x01:
  798.                                                 R8_UEP1_CTRL = (R8_UEP1_CTRL & (~RB_UEP_R_TOG)) | UEP_R_RES_STALL;/* 设置端点1 OUT Stall */
  799.                                                 break;
  800.                                             default:
  801.                                                 errflag = 0xFF;                                    /* 操作失败 */
  802.                                                 break;
  803.                                         }
  804.                                     }
  805.                                     else
  806.                                     {
  807.                                         errflag = 0xFF;                                      /* 操作失败 */
  808.                                     }
  809.                                 }
  810.                                 else
  811.                                 {
  812.                                     errflag = 0xFF;                                          /* 操作失败 */
  813.                                 }
  814.                                 break;

  815.                             case USB_GET_INTERFACE:
  816.                                 pEP0_DataBuf[0] = 0x00;
  817.                                 if ( SetupReqLen > 1 ) SetupReqLen = 1;
  818.                                 break;

  819.                             case USB_GET_STATUS:
  820.                                 pEP0_DataBuf[0] = 0x00;
  821.                                 pEP0_DataBuf[1] = 0x00;
  822.                                 if ( SetupReqLen > 2 ) SetupReqLen = 2;
  823.                                 break;

  824.                             default:
  825.                                 errflag = 0xff;
  826.                                 break;
  827.                         }
  828.                     }
  829.                 }
  830.                 else    errflag = 0xff;

  831.                 if( errflag == 0xff)
  832.                 {
  833. //                  SetupReqCode = 0xFF;
  834.                     R8_UEP0_CTRL = RB_UEP_R_TOG | RB_UEP_T_TOG | UEP_R_RES_STALL | UEP_T_RES_STALL;
  835.                 }
  836.                 else
  837.                 {
  838.                     if( chtype & 0x80 )
  839.                     {
  840.                         len = (SetupReqLen>DevEP0SIZE) ? DevEP0SIZE : SetupReqLen;
  841.                         SetupReqLen -= len;
  842.                     }
  843.                     else  len = 0;

  844.                     R8_UEP0_T_LEN = len;
  845.                     R8_UEP0_CTRL = RB_UEP_R_TOG | RB_UEP_T_TOG | UEP_R_RES_ACK | UEP_T_RES_ACK;
  846.                 }
  847.                 break;

  848.             case UIS_TOKEN_IN:
  849.                 switch( SetupReqCode )
  850.                 {
  851.                     case USB_GET_DESCRIPTOR:
  852.                         len = SetupReqLen >= DevEP0SIZE ? DevEP0SIZE : SetupReqLen;
  853.                         memcpy( pEP0_DataBuf, pDescr, len );
  854.                         SetupReqLen -= len;
  855.                         pDescr += len;
  856.                         R8_UEP0_T_LEN = len;
  857.                         R8_UEP0_CTRL ^= RB_UEP_T_TOG;
  858.                         break;

  859.                     case USB_SET_ADDRESS:
  860.                         R8_USB_DEV_AD = (R8_USB_DEV_AD&RB_UDA_GP_BIT) | SetupReqLen;
  861.                         R8_UEP0_CTRL = UEP_R_RES_ACK | UEP_T_RES_NAK;
  862.                         break;

  863.                     default:
  864.                         R8_UEP0_T_LEN = 0;
  865.                         R8_UEP0_CTRL = UEP_R_RES_ACK | UEP_T_RES_NAK;
  866.                         break;

  867.                 }
  868.                 break;

  869.             case UIS_TOKEN_OUT:
  870.                 R8_UEP0_T_LEN = 0;
  871.                 R8_UEP0_CTRL ^= RB_UEP_R_TOG;  //状态阶段,对IN响应NAK

  872.                 break;

  873.             case UIS_TOKEN_OUT | 1:
  874.                 if ( R8_USB_INT_ST & RB_UIS_TOG_OK )
  875.                 {
  876.                     if(CH32BULKDOWN)
  877.                     {
  878.                         mCH32BulkDownData();                              //如果上传数据阶段则调用数据上传
  879.                     }
  880.                     else
  881.                     {                                                      //不是数据下传则判断是否
  882.                         length = R8_USB_RX_LEN;
  883.                         if(!length)break;                                  //数据包长度为零则跳出
  884.                         for(len=0;len!=length;len++)
  885.                         {
  886.                             MassPara.buf[len]=pEP1_RAM_Addr[len];          //将数据读入到缓冲区
  887.                         }
  888.                         mCH32BulkOnly();
  889.                         if(BcswStatus ==0 )
  890.                         {
  891.                             if(!CH32BULKDOWN){
  892.                                 if(CH32BULKUP) CH32bulkUpData();         //调用批量数据上传
  893.                                 else mCH32UpCsw();                        //test
  894.                             }
  895.                         }
  896.                 }
  897.                 }
  898.                 break;

  899.             case UIS_TOKEN_IN | 1:
  900.                 if(CH32BULKUP)
  901.                 {
  902.                     CH32bulkUpData();                             //调用数据上传
  903.                 }
  904.                 else if(CH32CSW)
  905.                 {
  906.                     CH32CSW = 0;
  907.                     mCH32UpCsw();                                 //上传CSW
  908.                 }
  909.                 else
  910.                 {
  911.                     R8_UEP1_T_LEN = 0;
  912.                     R8_UEP1_CTRL = (R8_UEP1_CTRL & ~MASK_UEP_T_RES) | UEP_T_RES_NAK;
  913.                 }
  914.                 break;

  915.             case UIS_TOKEN_OUT | 2:
  916.                 break;

  917.             case UIS_TOKEN_IN | 2:
  918.                 R8_UEP2_T_LEN = 0;
  919.                 R8_UEP2_CTRL = (R8_UEP2_CTRL & ~MASK_UEP_T_RES) | UEP_T_RES_NAK;
  920.                 UpPoint2_Busy = 0;
  921.                 break;

  922.             case UIS_TOKEN_OUT | 3:
  923.                 if ( R8_USB_INT_ST & RB_UIS_TOG_OK )
  924.                 {
  925.                     len = R8_USB_RX_LEN;
  926.                     DevEP3_OUT_Deal( len );
  927.                 }
  928.                 break;

  929.             case UIS_TOKEN_IN | 3:
  930.                 R8_UEP3_T_LEN = 0;
  931.                 R8_UEP3_CTRL = (R8_UEP3_CTRL & ~MASK_UEP_T_RES) | UEP_T_RES_NAK;
  932.                 break;

  933.             case UIS_TOKEN_OUT | 4:
  934.                 if ( R8_USB_INT_ST & RB_UIS_TOG_OK )
  935.                 {
  936.                     R8_UEP4_CTRL ^= RB_UEP_R_TOG;
  937.                     len = R8_USB_RX_LEN;
  938.                     DevEP4_OUT_Deal( len );
  939.                 }
  940.                 break;

  941.             case UIS_TOKEN_IN | 4:
  942.                 R8_UEP4_T_LEN = 0;
  943.                 R8_UEP4_CTRL ^=  RB_UEP_T_TOG;
  944.                 R8_UEP4_CTRL = (R8_UEP4_CTRL & ~MASK_UEP_T_RES) | UEP_T_RES_NAK;
  945.                 break;

  946.             default:
  947.                 break;
  948.         }
  949.         R8_USB_INT_FG = RB_UIF_TRANSFER;
  950.     }
  951.     else if( intflag & RB_UIF_BUS_RST )
  952.     {
  953.         R8_USB_DEV_AD = 0;
  954.         R8_UEP0_CTRL = UEP_R_RES_ACK | UEP_T_RES_NAK;
  955.         R8_UEP1_CTRL = UEP_R_RES_ACK | UEP_T_RES_NAK | RB_UEP_AUTO_TOG;
  956.         R8_UEP2_CTRL = UEP_R_RES_ACK | UEP_T_RES_NAK | RB_UEP_AUTO_TOG;
  957.         R8_UEP3_CTRL = UEP_R_RES_ACK | UEP_T_RES_NAK | RB_UEP_AUTO_TOG;
  958.         R8_USB_INT_FG |= RB_UIF_BUS_RST;
  959.     }
  960.     else if( intflag & RB_UIF_SUSPEND )
  961.     {
  962.         if ( R8_USB_MIS_ST & RB_UMS_SUSPEND ) {;}
  963.         else{;}
  964.         R8_USB_INT_FG = RB_UIF_SUSPEND;
  965.     }
  966.     else
  967.     {
  968.         R8_USB_INT_FG = intflag;
  969.     }
  970. }
  971. /*******************************************************************************
  972. * Function Name  : Set_USBConfig
  973. * Description    : Set USB clock.
  974. * Input          : None
  975. * Return         : None
  976. *******************************************************************************/
  977. void USBHD_ClockCmd(UINT32 RCC_USBCLKSource,FunctionalState NewState)
  978. {
  979.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, NewState);
  980.     EXTEN->EXTEN_CTR |= EXTEN_USBHD_IO_EN;
  981.     RCC_USBCLKConfig(RCC_USBCLKSource);             //USBclk=PLLclk/1.5=48Mhz
  982.     RCC_AHBPeriphClockCmd(RCC_AHBPeriph_USBHD,NewState);
  983. }
  984. /*******************************************************************************
  985. * Function Name  : main
  986. * Description    : Main program.
  987. * Input          : None
  988. * Return         : None
  989. *******************************************************************************/
  990. int main(void)
  991. {
  992.     NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
  993.     Delay_Init();
  994.     USART_Printf_Init(115200);

  995.     printf("USBHD Device Test\r\n");

  996.     pEP0_RAM_Addr = EP0_Databuf;
  997.     pEP1_RAM_Addr = EP1_Databuf;
  998.     pEP2_RAM_Addr = EP2_Databuf;
  999.     pEP3_RAM_Addr = EP3_Databuf;
  1000.     USBHD_ClockCmd(RCC_USBCLKSource_PLLCLK_1Div5,ENABLE);
  1001.     USB_DeviceInit();
  1002.     NVIC_EnableIRQ( USBHD_IRQn );
  1003.     while(1)
  1004.     {
  1005.         ;
  1006.     }
  1007. }

  1008. /*******************************************************************************
  1009. * Function Name  : DevEP1_OUT_Deal
  1010. * Description    : Deal device Endpoint 1 OUT.
  1011. * Input          : l: Data length.
  1012. * Return         : None
  1013. *******************************************************************************/
  1014. void DevEP1_OUT_Deal( UINT8 l )
  1015. {
  1016.     ;
  1017. }

  1018. /*******************************************************************************
  1019. * Function Name  : DevEP2_OUT_Deal
  1020. * Description    : Deal device Endpoint 2 OUT.
  1021. * Input          : l: Data length.
  1022. * Return         : None
  1023. *******************************************************************************/
  1024. void DevEP2_OUT_Deal( UINT8 l )
  1025. {
  1026.     ;
  1027. }

  1028. /*******************************************************************************
  1029. * Function Name  : DevEP3_OUT_Deal
  1030. * Description    : Deal device Endpoint 3 OUT.
  1031. * Input          : l: Data length.
  1032. * Return         : None
  1033. *******************************************************************************/
  1034. void DevEP3_OUT_Deal( UINT8 l )
  1035. {
  1036.     ;
  1037. }

  1038. /*******************************************************************************
  1039. * Function Name  : DevEP4_OUT_Deal
  1040. * Description    : Deal device Endpoint 4 OUT.
  1041. * Input          : l: Data length.
  1042. * Return         : None
  1043. *******************************************************************************/
  1044. void DevEP4_OUT_Deal( UINT8 l )
  1045. {
  1046.     ;
  1047. }

  1048. /*******************************************************************************
  1049. * Function Name  : USB_IRQHandler
  1050. * Description    : This function handles USB exception.
  1051. * Input          : None
  1052. * Return         : None
  1053. *******************************************************************************/
  1054. void USBHD_IRQHandler (void)
  1055. {
  1056.     USB_DevTransProcess();
  1057. }
main.c文件中描述符部分都进行了注释,便于大家理解,其余部分可以参考《圈圈教你玩USB》。关于USB设备传输过程,可结合应用手册关于USB寄存器介绍进行理解学习。

4下载验证
将编译好的程序下载到开发板并复位,打开串口调试助手,串口打印如下:
图片1.png
用公对公USB线将开发板与电脑连接起来,打开磁盘驱动器可以看到多了一个U盘设备,如图所示:
图片2.png
查看此电脑,可以看到多了一个U盘,如图所示:
图片3.png

83、CH32V103 USB模拟U盘.rar

491.21 KB, 下载次数: 327

jheng 发表于 2022-4-28 15:10 | 显示全部楼层
请问下大佬,这个程序为什么不能进行存储
薅羊电子网 发表于 2022-4-29 10:00 | 显示全部楼层
大神,可以出个更详细的教程。学习学习
sadicy 发表于 2022-5-12 20:55 | 显示全部楼层
这一大串~~~
koala889 发表于 2022-5-27 20:36 | 显示全部楼层
下载试试,学习下
abotomson 发表于 2022-6-2 09:34 | 显示全部楼层
这个需要驱动吗?      
modesty3jonah 发表于 2022-6-2 09:43 | 显示全部楼层
USB模拟的速度能够到多少?     
jstgotodo 发表于 2022-6-2 14:56 | 显示全部楼层
最大支持多少内存的U盘呢?
ingramward 发表于 2022-7-9 13:28 | 显示全部楼层
这个读取速度怎么样  
DIY小幸福 发表于 2022-8-12 20:25 | 显示全部楼层
掉电后,数据会丢失。新建文本文档,写入数据后重新打开也会丢失
1988020566 发表于 2022-8-20 13:24 | 显示全部楼层
可以参考cherryusb吗   
jtracy3 发表于 2022-8-20 13:33 | 显示全部楼层
这个可以,使用什么通信协议呢  
kissdb 发表于 2022-10-10 09:34 | 显示全部楼层
能出个SPI存储器模拟U盘的就更好了
macpherson 发表于 2022-12-1 19:14 | 显示全部楼层
这个字符是如何确定的?              
modesty3jonah 发表于 2022-12-1 19:23 | 显示全部楼层
NANDFLASH模拟U盘,不错。
robertesth 发表于 2022-12-1 22:27 | 显示全部楼层
CH32V103 USB 内部FLASH模拟U盘可以吗?
pentruman 发表于 2022-12-2 22:58 | 显示全部楼层
之前用过USB单片机CH559模拟U盘应用实例
sesefadou 发表于 2022-12-3 14:24 | 显示全部楼层
CH32V103不是自带这个功能的吗
febgxu 发表于 2022-12-4 19:51 | 显示全部楼层
可以实现虚拟串口的功能吗?              
cemaj 发表于 2022-12-4 21:52 | 显示全部楼层
USB通fatfs模拟小U盘  
您需要登录后才可以回帖 登录 | 注册

本版积分规则

133

主题

296

帖子

45

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

133

主题

296

帖子

45

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