查看: 1956|回复: 0
收起左侧

第八十四章:CH32V103应用教程——USB模拟U盘

[复制链接]

  离线 

  • TA的每日心情
    慵懒
    2021-7-23 17:16
  • 签到天数: 17 天

    [LV.4]

    发表于 2021-5-1 16:24:23 | 显示全部楼层 |阅读模式

    有人预言,RISC-V或将是继Intel和Arm之后的第三大主流处理器体系。欢迎访问全球首家只专注于RISC-V单片机行业应用的中文网站

    您需要 登录 才可以下载或查看,没有帐号?立即注册

    x
    本帖最后由 草帽王子 于 2021-9-10 18:21 编辑

    本章教程主要使用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、下载验证

    将编译好的程序下载到开发板并复位,打开串口调试助手,串口打印如下:
    CH32V CH573单片机芯片-第八十四章:CH32V103应用教程——USB模拟U盘risc-v单片机中文社区(1)
    用公对公USB线将开发板与电脑连接起来,打开磁盘驱动器可以看到多了一个U盘设备,如图所示:
    CH32V CH573单片机芯片-第八十四章:CH32V103应用教程——USB模拟U盘risc-v单片机中文社区(2)
    查看此电脑,可以看到多了一个U盘,如图所示:
    CH32V CH573单片机芯片-第八十四章:CH32V103应用教程——USB模拟U盘risc-v单片机中文社区(3)

    83、CH32V103 USB模拟U盘.rar
    CH32V CH573单片机芯片-第八十四章:CH32V103应用教程——USB模拟U盘risc-v单片机中文社区(4) 83、CH32V103 USB模拟U盘.rar (491.21 KB, 下载次数: 14)
    链接:https://pan.baidu.com/s/1NVWBRbfnxL2WLHEFdXFs1Q
    提取码:sw7n
    复制这段内容后打开百度网盘手机App,操作更方便哦







    上一篇:第八十三章:CH32V103应用教程——USB模拟鼠标键盘设备
    下一篇:第八十五章:CH32V103应用教程——USB Host
    RISCV作者优文
    全球首家只专注于RISC-V单片机行业应用的中文网站
    回复

    使用道具 举报

    高级模式
    B Color Image Link Quote Code Smilies

    本版积分规则

    关闭

    RISC-V单片机中文网上一条 /2 下一条



    版权及免责声明|RISC-V单片机中文网 |网站地图

    GMT+8, 2024-11-26 09:54 , Processed in 0.352767 second(s), 46 queries .

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