找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 28757|回复: 47
收起左侧

用51单片机模拟USB键盘源程序及原理图

  [复制链接]
ID:190834 发表于 2017-4-26 11:26 | 显示全部楼层 |阅读模式
使用51单片机模拟USB键盘原理图(附件里面可以下载清晰版的电路图及完整源码):
0.png 0.png


单片机源程序:
  1. /******************************************************************
  2.    本程序只供学习使用,未经作者许可,不得用于其它任何用途
  3.       我的邮箱:computer-lov@tom.com

  4. USBKeyBoard.C  file

  5. 作者:Computer-lov
  6. 建立日期: 2007.03.20
  7. 修改日期: 2007.03.23
  8. 版本:V1.1
  9. 版权所有,盗版必究。
  10. Copyright(C) Computer-lov 2007-2017
  11. All rights reserved            
  12. *******************************************************************/

  13. #include <AT89x52.H>
  14. #include "USB.H"
  15. #include "PDIUSBD12.H"
  16. #include "My_type.h"
  17. #include "UART.H"
  18. #include "key.h"
  19. #include "keyboard.h"

  20. #define USB_COMMAND_ADD           1
  21. #define USB_DATA_ADD              0

  22. //USB芯片连接引脚
  23. #define USB_DATA                  P0
  24. #define USB_A0                    P3_5
  25. #define USB_WR                    P3_6
  26. #define USB_RD                    P3_7
  27. #define USB_INT                   P3_2


  28. #define ENDPOINT_NUMBER           2
  29. #define MAX_CONTROL_DATA_SIZE     16


  30. //控制传输时保存数据
  31. CONTROL_DATA_BUFF Control_Data;

  32. //缓冲
  33. uint8 idata buffer[64];

  34. //交换数据时用的指针
  35. uint8 *pData;

  36. uint8 idle;     //空闲状态
  37. uint8 protocol; //当前协议

  38. //高低字节交换

  39. #define SWAP16(x)  ((((uint16)(x))<<8)|(((uint16)(x))>>8))

  40. //取一个整数的低字节
  41. #define LSB(x) ((uint8)(x))

  42. //取一个整数的高字节
  43. #define MSB(x) ((uint8)(((uint16)(x))>>8))                              

  44. //字符串描述符所用的语言种类
  45. code uint8 LANGUAGE_ID[4]={0x04,0x03,0x09,0x04};                  

  46. //设备序列号                                                                                
  47. code uint8 device_serial_number[]=
  48. {22,STRING_DESCRIPTOR,'2',0,'0',0,'0',0,'7',0,'-',0,'0',0,'3',0,'-',0,'2',0,'3',0};

  49. //厂商字符串
  50. code uint8 ManufacturerString[80]=
  51. {80,STRING_DESCRIPTOR,0x35,0x75,0x11,0x81,0x08,0x57,0x08,0x57,0x84,0x76,0xB6,0x5B,
  52. 0x53,0x5F,'-',0x00,'-',0x00,'-',0x00,'-',0x00,'@',0,0x20,0x00,'H',0,'t',0,'t',0,
  53. 'p',0,':',0,'/',0,'/',0,'C',0,'o',0,'m',0,'p',0,'u',0,'t',0,'e',0,'r',0,'0',0,
  54. '0',0,'.',0,'2',0,'1',0,'i',0,'c',0,'.',0,'o',0,'r',0,'g',0};

  55. //产品字符串
  56. code uint8 ProducterString[80]=
  57. {80,STRING_DESCRIPTOR,0x35,0x75,0x11,0x81,0x08,0x57,0x08,0x57,0x5A,0x50,0x84,0x76,
  58. 'U',0,'S',0,'B',0,0x2E,0x95,0xD8,0x76,'@',0,0x20,0x00,'H',0,'t',0,'t',0,
  59. 'p',0,':',0,'/',0,'/',0,'C',0,'o',0,'m',0,'p',0,'u',0,'t',0,'e',0,'r',0,'0',0,
  60. '0',0,'.',0,'2',0,'1',0,'i',0,'c',0,'.',0,'o',0,'r',0,'g',0};


  61. code DEVICE_DESCRIPTOR_STRUCT device_descriptor=     //设备描述符
  62. {
  63. sizeof(DEVICE_DESCRIPTOR_STRUCT),                   //设备描述符的字节数大小
  64. DEVICE_DESCRIPTOR,                                         //设备描述符类型编号
  65. 0x1001,                                             //USB版本号
  66. 0x00,                                               //USB分配的设备类代码
  67. 0x00,                                               //USB分配的子类代码
  68. 0x00,                                               //USB分配的设备协议代码
  69. 0x10,                                               //端点0的最大包大小
  70. 0x3412,                                             //厂商编号VID,这里只是作为测试用,请使用自己的VID
  71. 0x7856,                                             //产品编号PID,这里只是作为测试用,请使用自己的PID
  72. 0x0100,                                             //设备出厂编号
  73. 0x01,                                               //设备厂商字符串的索引
  74. 0x02,                                               //描述产品字符串的索引
  75. 0x03,                                               //描述设备序列号字符串的索引
  76. 0x01                                                //可能的配置数量
  77. };

  78. //定义配置,接口,端点等描述符结构体,因为它们是随配置描述符一起返回的
  79. typedef struct _CON_INT_ENDP_DESCRIPTOR_STRUCT
  80. {
  81. CONFIGURATION_DESCRIPTOR_STRUCT configuration_descriptor;
  82. INTERFACE_DESCRIPTOR_STRUCT  interface_descriptor;
  83. HID_DESCRIPTOR_STRUCT hid_descriptor;
  84. ENDPOINT_DESCRIPTOR_STRUCT  endpoint_descriptor[ENDPOINT_NUMBER];
  85. }CON_INT_ENDP_DESCRIPTOR_STRUCT;

  86. code CON_INT_ENDP_DESCRIPTOR_STRUCT con_int_endp_descriptor=
  87. {
  88. //configuration_descriptor                                          //配置描述符
  89. {
  90. sizeof(CONFIGURATION_DESCRIPTOR_STRUCT),                           //配置描述符的字节数大小
  91. CONFIGURATION_DESCRIPTOR,                                          //配置描述符类型编号
  92. SWAP16(sizeof(CON_INT_ENDP_DESCRIPTOR_STRUCT)),
  93. 0x01,                                                            //只包含一个接口
  94. 0x01,                                                            //该配置的编号
  95. 0x00,                                                            //iConfiguration字段
  96. 0xA0,                                                            //采用总线供电,支持远程唤醒
  97. 0xC8                                                            //从总线获取最大电流400mA
  98. },
  99. //interface_descritor                                             //接口描述符
  100. {
  101. sizeof(INTERFACE_DESCRIPTOR_STRUCT),                             //接口描述符的字节数大小
  102. INTERFACE_DESCRIPTOR,                                            //接口描述符类型编号
  103. 0x00,                                                            //接口编号为0
  104. 0x00,                                                            //该接口描述符的编号
  105. ENDPOINT_NUMBER,                                                 //非0端点数量为2,只使用端点主端点输入和输出
  106. 0x03,                                                            //人机接口设备(HID)类
  107. 0x01,                                                            //使用的子类:支持BIOS根启动Boot的子类
  108. 0x01,                                                            //使用的协议:键盘
  109. 0x00                                                             //接口描述符字符串索引
  110. },
  111. //hid_descriptor
  112. {
  113. sizeof(HID_DESCRIPTOR_STRUCT),                                   //HID描述符的字节数大小
  114. HID_DESCRIPTOR,                                                  //HID描述符类型编号
  115. 0x1001,                                                          //HID类协议版本号,为1.1
  116. 0x21,                                                            //固件的国家地区代号,0x21为美国
  117. NUM_SUB_DESCRIPTORS,                                             //下级描述符的数量
  118. {
  119.   {
  120.    REPORT_DESCRIPTOR,                                             //下级描述符为报告描述符
  121.    SWAP16(sizeof(KeyBoardReportDescriptor))                       //下级描述符的长度
  122.   }
  123. },
  124. },
  125. //endpoint_descriptor[]
  126. {
  127. {                                                                //主端点输入描述
  128.   sizeof(ENDPOINT_DESCRIPTOR_STRUCT),                             //端点描述符的字节数大小
  129.   ENDPOINT_DESCRIPTOR,                                            //端点描述符类型编号
  130.   MAIN_POINT_IN,                                                  //端点号,主输入端点
  131.   ENDPOINT_TYPE_INTERRUPT,                                        //使用的传输类型:中断传输
  132.   0x4000,                                                         //该端点支持的最大包尺寸,64字节
  133.   0x0A                                                            //中断扫描时间:设置为10ms
  134. },
  135.   
  136. {                                                                //主端点输出描述
  137.   sizeof(ENDPOINT_DESCRIPTOR_STRUCT),                             //端点描述符的字节数大小
  138.   ENDPOINT_DESCRIPTOR,                                            //端点描述符类型编号
  139.   MAIN_POINT_OUT,                                                 //端点号,主输出端点
  140.   ENDPOINT_TYPE_INTERRUPT,                                        //使用的传输类型:中断传输
  141.   0x4000,                                                         //该端点支持的最大包尺寸,64字节
  142.   0x0A                                                            //中断扫描时间:设置为10ms
  143. }
  144. }
  145. };

  146. union                                          //程序标志位
  147. {
  148. uint16 Register;
  149. struct
  150. {
  151. uint8 bus_reset        :1;
  152. uint8 suspend          :1;
  153. uint8 remote_wakeup    :1;
  154. uint8 int_isr          :1;
  155. uint8 not_end          :1;
  156. uint8 usb_idle         :1;
  157. uint8 usb_busy         :1;
  158. uint8 setup_packet_in  :1;
  159. uint8 setup_packet_out :1;
  160. uint8 set_addr         :1;
  161. uint8 usb_endp0_in     :1;
  162. uint8 usb_endp2_in     :1;
  163. uint8 usb_endp2_out    :1;
  164. }flags;
  165. }usb_flags;

  166. union                                         //中断寄存器
  167. {
  168. uint8 Register[2];
  169. struct
  170.   {
  171.    uint8 control_out_port  :1;
  172.    uint8 control_in_port   :1;
  173.    uint8 port_out_1        :1;
  174.    uint8 port_in_1         :1;
  175.    uint8 main_out_port     :1;
  176.    uint8 main_in_port      :1;
  177.    uint8 bus_reset         :1;
  178.    uint8 suspend_change    :1;
  179.    uint8 DMA_EOT           :1;
  180.    uint8 not_use           :7;
  181.   }Interrupt;
  182. }Interrupt_Register;


  183. union                                    //端点最后处理状态
  184. {
  185. uint8 Register;
  186. struct
  187. {
  188.   uint8 successful          :1;
  189.   uint8 error_code          :4;
  190.   uint8 setup_packet        :1;
  191.   uint8 data_1              :1;
  192.   uint8 prestatus_not_read  :1;
  193. }Status;
  194. }Last_Status;


  195. /*****************   延时x毫秒函数 ***********/
  196. void delay(uint16 x)               
  197. {
  198. uint16 i;
  199. uint16 j;
  200. for(i=0;i<x;i++)
  201. for(j=0;j<230;j++);
  202. }
  203. /********************************************/

  204. /*******************************写USB命令******************************************/
  205. void write_usb_command(uint8 usb_command)
  206. {
  207. USB_A0=USB_COMMAND_ADD;
  208. USB_DATA=usb_command;
  209. USB_WR=0;
  210. USB_WR=1;
  211. USB_DATA=0xFF;
  212. }
  213. /******************************************************************************/

  214. /*********************写一字节USB数据*******************************************/
  215. void write_a_usb_data(uint8 usb_data)      
  216. {
  217. USB_A0=USB_DATA_ADD;
  218. USB_DATA=usb_data;
  219. USB_WR=0;
  220. USB_WR=1;
  221. USB_DATA=0XFF;
  222. }
  223. /******************************************************************************/

  224. /****************************读一字节USB数据************************************/
  225. uint8 read_a_usb_data(void)
  226. {
  227. uint8 temp;
  228. USB_A0=USB_DATA_ADD;
  229. USB_RD=0;
  230. temp=USB_DATA;
  231. USB_RD=1;
  232. return temp;
  233. }
  234. /******************************************************************************/

  235. /************************读USB中断寄存器**************************************/
  236. void read_interrupt_register(void)
  237. {
  238. write_usb_command(Read_Interrupt_Register);
  239. Interrupt_Register.Register[0]=read_a_usb_data();
  240. Interrupt_Register.Register[1]=read_a_usb_data();
  241. }
  242. /******************************************************************************/

  243. /************************设置USB地址*******************************************/
  244. void set_usb_addr(uint8 addr)
  245. {

  246. write_usb_command(Set_Address);
  247. write_a_usb_data(0x80|addr);
  248. Prints("   设置地址.....................",1);
  249. Prints("       地址为:  ",0);
  250. PrintLongInt(addr);
  251. Prints("",1);
  252. }
  253. /******************************************************************************/

  254. /*************************端点使能******************************************/
  255. void set_endpoint_enable(void)
  256. {
  257. write_usb_command(Set_Endpoint_Enable);
  258. write_a_usb_data(0x01);
  259. }
  260. /******************************************************************************/

  261. /****************************选择终端点*************************************/
  262. uint8 select_endpoint(uint8 endp)
  263. {
  264. write_usb_command(Select_EndPoint+endp);
  265. return read_a_usb_data();
  266. }
  267. /******************************************************************************/

  268. /****************************读端点最后状态**********************************/
  269. uint8  read_last_status(uint8 endp)
  270. {
  271. write_usb_command(Read_Last_Status+endp);
  272. return read_a_usb_data();
  273. }
  274. /******************************************************************************/

  275. /****************************设置端点状态**************************************/
  276. void set_endpoint_status(uint8 endp,uint8 status)  
  277. {
  278. write_usb_command(0x40+endp);
  279. write_a_usb_data(!status);
  280. }
  281. /******************************************************************************/

  282. /*****************************读端点状态**************************************/
  283. uint8 read_endpoint_status(uint8 endp)
  284. {
  285. write_usb_command(0x80+endp);
  286. return read_a_usb_data();
  287. }
  288. /******************************************************************************/

  289. /************************清缓冲,在读取缓冲数据后调用**************************/
  290. void clear_buffer(void)
  291. {
  292. write_usb_command(Clear_Buffer);
  293. }
  294. /******************************************************************************/

  295. /***********************缓冲区数据有效,在写缓冲后调用**************************/
  296. void validate_buffer(void)
  297. {
  298. write_usb_command(Validate_Buffer);
  299. }
  300. /******************************************************************************/

  301. /***************************应答建立包************************************/
  302. void ack_setup(uint8 endp)
  303. {
  304. select_endpoint(endp);
  305. write_usb_command(Ack_Setup);
  306. }
  307. /******************************************************************************/

  308. /***********************出错处理******************************************/
  309. void error(uint8 number)
  310. {
  311. Prints("有错误发生!!!",1);
  312. number=0;
  313. }
  314. /******************************************************************************/

  315. /*************************读终端点缓冲****************************************/
  316. uint8 read_endpoint_buff(uint8 endp,uint8 len,uint8 * buff)
  317. {
  318. uint8 i,j;
  319. read_last_status(endp);
  320. if(!(select_endpoint(endp))&0x01){error(0); return 0;}
  321. read_endpoint_status(endp);
  322. write_usb_command(Read_Buffer);
  323. read_a_usb_data();
  324. j=read_a_usb_data();
  325. if(j>len)
  326.   j=len;
  327. for(i=0;i<j;i++)
  328.   {
  329.    USB_RD=0;
  330.    *(buff+i)=USB_DATA;
  331.    USB_RD=1;
  332.   }
  333. clear_buffer();
  334. return j;
  335. }
  336. /******************************************************************************/

  337. /*************************写终端点缓冲*****************************************/
  338. uint8 write_endpoint_buff(uint8 endp,uint8 len,uint8 * buff)
  339. {
  340. uint8 i;
  341. read_last_status(endp);
  342. select_endpoint(endp);
  343. write_usb_command(Write_Buffer);
  344. write_a_usb_data(0);
  345. write_a_usb_data(len);
  346. for(i=0;i<len;i++)
  347.   {
  348.    USB_DATA=*(buff+i);
  349.    USB_WR=0;
  350.    USB_WR=1;
  351.   }
  352. USB_DATA=0XFF;
  353. validate_buffer();
  354. return len;
  355. }
  356. /******************************************************************************/

  357. /***************************断开USB连接****************************************/
  358. void disconnect_usb(void)
  359. {
  360. Prints("断开USB连接........................",1);
  361. write_usb_command(0xf3);
  362. write_a_usb_data(0x0e);
  363. write_a_usb_data(0x47);
  364. delay(100);
  365. }
  366. /******************************************************************************/

  367. /*******************************连接USB**************************************/
  368. void connect_usb(void)
  369. {
  370. Prints("连接USB...............",1);
  371. write_usb_command(0xf3);                         //初始化USBD12
  372. write_a_usb_data(0x1e);                          //连接USB
  373. write_a_usb_data(0x47);                          //设置频率
  374. }
  375. /******************************************************************************/

  376. /***************************初始化USB***************************************************/
  377. void init_usb(void)               
  378. {
  379. Prints("USBD12芯片初始化",1);
  380. set_usb_addr(0);
  381. set_endpoint_enable();
  382. }
  383. /******************************************************************************/

  384. /****************************USB总线复位处理***********************************/
  385. void usb_bus_reset(void)
  386. {
  387. Prints("USB总线复位................................",1);
  388. usb_flags.Register=0;
  389. set_endpoint_enable();
  390. }
  391. /******************************************************************************/

  392. /*****************************USB总线挂起处理**********************************/
  393. void usb_bus_suspend(void)
  394. {
  395. Prints("USB总线挂起................................",1);
  396. }
  397. /******************************************************************************/

  398. /***************************设置地址***************************************/
  399. void set_usb_address(void)
  400. {
  401. usb_flags.flags.set_addr=1;
  402. while(select_endpoint(1)&0x01);
  403. write_endpoint_buff(1,0,0);
  404. set_usb_addr(Control_Data.DeviceRequest.wValue);
  405. usb_flags.flags.usb_endp0_in=0;
  406. usb_flags.flags.setup_packet_out=0;
  407. }
  408. /******************************************************************************/

  409. /**************************获取状态响应*****************************************/
  410. void get_status(uint8 receiver)
  411. {
  412. uint8 status[2];
  413. switch (receiver)
  414.   {
  415.    case 0:                        //获取设备状态
  416.     status[0]=0x00;
  417.     status[1]=0x00;
  418.     break;
  419.    case 1:                        //获取接口状态
  420.     status[0]=0x00;
  421.     status[0]=0x00;
  422.     break;
  423.    case 2:                        //获取端点状态
  424.     status[0]=0x00;
  425.     status[1]=0x00;
  426.     break;
  427.    }
  428.   write_endpoint_buff(1,2,status);
  429.   usb_flags.flags.usb_endp0_in=0;
  430. }
  431. /******************************************************************************/

  432. /*********************清除特性*******************************************/
  433. void clear_feature(uint8 receiver)   
  434. {
  435. Prints("    清除特性................................",1);
  436. receiver=0;
  437. write_endpoint_buff(1,0,0);
  438. usb_flags.flags.usb_endp0_in=0;
  439. usb_flags.flags.setup_packet_out=0;
  440. }
  441. /******************************************************************************/

  442. /*******************设置特性**************************************************/
  443. void set_feature(uint8 receiver)
  444. {
  445. Prints("    设置特性................................",1);
  446. receiver=0;
  447. write_endpoint_buff(1,0,0);
  448. usb_flags.flags.usb_endp0_in=0;
  449. usb_flags.flags.setup_packet_out=0;
  450. }
  451. /******************************************************************************/

  452. /*****************************设置描述*****************************************/
  453. void set_descriptor(void)
  454. {
  455. Prints("    设置描述符................................",1);
  456. usb_flags.flags.usb_endp0_in=0;
  457. usb_flags.flags.setup_packet_out=0;
  458. }
  459. /******************************************************************************/

  460. /***************************设置配置*******************************************/
  461. void set_configuration(void)
  462. {
  463. Prints("    设置配置................................",1);
  464. write_endpoint_buff(1,0,0);
  465. usb_flags.flags.usb_endp0_in=0;
  466. usb_flags.flags.setup_packet_out=0;
  467. }
  468. /******************************************************************************/

  469. /************************获取配置状态******************************************/
  470. void get_configuration(void)
  471. {
  472. uint8 value=0x01;
  473. Prints("    获取配置................................",1);
  474. write_endpoint_buff(1,1,&value);
  475. usb_flags.flags.usb_endp0_in=0;
  476. }
  477. /******************************************************************************/

  478. /****************************设置接口************************************/
  479. void set_interface(void)
  480. {
  481. Prints("    设置接口................................",1);
  482. write_endpoint_buff(1,0,0);
  483. usb_flags.flags.usb_endp0_in=0;
  484. usb_flags.flags.setup_packet_out=0;
  485. }
  486. /******************************************************************************/

  487. /***************************获取接口状态***************************************/
  488. void get_interface(void)
  489. {
  490. uint8 value=0x01;
  491. Prints("    获取接口................................",1);
  492. write_endpoint_buff(1,1,&value);
  493. usb_flags.flags.usb_endp0_in=0;
  494. }
  495. /******************************************************************************/

  496. /***********************获取描述符*********************************************/
  497. void get_descriptor(void)
  498. {
  499. Prints("    获取描述符................................",1);
  500.   if(!usb_flags.flags.not_end)
  501.      {
  502.       switch(MSB(Control_Data.DeviceRequest.wValue))
  503.            {
  504.         case DEVICE_DESCRIPTOR:
  505.                      Prints("        获取设备描述符................................",1);
  506.                  Control_Data.wCount=sizeof(DEVICE_DESCRIPTOR_STRUCT);
  507.                   Control_Data.pData=(uint8 *)(&device_descriptor);
  508.              break;
  509.         case CONFIGURATION_DESCRIPTOR:
  510.                          Prints("        获取配置描述符................................",1);
  511.              Control_Data.wCount=SWAP16(con_int_endp_descriptor.configuration_descriptor.wTotalLength);
  512.                          Control_Data.pData=(uint8 *)(&con_int_endp_descriptor);
  513.              if(Control_Data.wLength<Control_Data.wCount)Control_Data.wCount=Control_Data.wLength;
  514.              break;
  515.                 case STRING_DESCRIPTOR:
  516.                      Prints("        获取字符串描述符................................",1);
  517.                          switch(LSB(Control_Data.DeviceRequest.wValue))
  518.                           {
  519.                            case 0:
  520.                             Prints("            获取语言ID................................",1);
  521.                             Control_Data.wCount=LANGUAGE_ID[0];
  522.                 Control_Data.pData=LANGUAGE_ID;
  523.                                break;

  524.                            case 1:
  525.                             Prints("            获取厂商字符串................................",1);
  526.                             Control_Data.wCount=ManufacturerString[0];
  527.                 Control_Data.pData=ManufacturerString;
  528.                             break;

  529.                            case 2:
  530.                             Prints("            获取产品字符串................................",1);
  531.                             Control_Data.wCount=ProducterString[0];
  532.                 Control_Data.pData=ProducterString;
  533.                             break;

  534.                            case 3:
  535.                  Prints("            获取设备序列号................................",1);
  536.                              Control_Data.wCount=device_serial_number[0];
  537.                              Control_Data.pData=device_serial_number;
  538.                            break;

  539.                            default: break;
  540.                           }
  541.                          break;
  542.                  default:
  543.                      Prints("       获取其它描述符..................描述符索引为:",0);
  544.                          PrintLongInt(MSB(Control_Data.DeviceRequest.wValue));
  545.                          Prints("",1);
  546.                   break;
  547.                    }
  548.       if(Control_Data.wLength<Control_Data.wCount)Control_Data.wCount=Control_Data.wLength;
  549.          }
  550.         //写数据到D12输入端点
  551.     if(Control_Data.wCount>=MAX_CONTROL_DATA_SIZE)
  552.      {
  553.           write_endpoint_buff(1,MAX_CONTROL_DATA_SIZE,Control_Data.pData);
  554.           Control_Data.pData+=MAX_CONTROL_DATA_SIZE;
  555.       Control_Data.wCount-=MAX_CONTROL_DATA_SIZE;
  556.           if(usb_flags.flags.set_addr)usb_flags.flags.not_end=1;
  557.            else usb_flags.flags.usb_endp0_in=0;
  558.           return;
  559.          }
  560.     else
  561.      {
  562.           write_endpoint_buff(1,Control_Data.wCount,Control_Data.pData);
  563.       usb_flags.flags.setup_packet_in=0;
  564.           usb_flags.flags.usb_endp0_in=0;
  565.           return;
  566.          }      
  567. }
  568. /******************************************************************************/

  569. /*********************发到接口的获取描述符**************************************/
  570. void get_descriptor_interface(void)
  571. {
  572. Prints("    获取描述符(从接口)..............................",1);
  573.   if(!usb_flags.flags.not_end)
  574.      {
  575.       switch(MSB(Control_Data.DeviceRequest.wValue))
  576.            {
  577.         case HID_DESCRIPTOR:
  578.                      Prints("        获取HID描述符................................",1);
  579.                  Control_Data.wCount=sizeof(HID_DESCRIPTOR_STRUCT);
  580.                   //Control_Data.pData=(uint8 *)(&hid_descriptor);
  581.              break;
  582.         case REPORT_DESCRIPTOR:
  583.                          Prints("        获取报告描述符................................",1);
  584.              Control_Data.wCount=SWAP16(sizeof(KeyBoardReportDescriptor));
  585.                          Control_Data.pData=(uint8 *)(KeyBoardReportDescriptor);
  586.              if(Control_Data.wLength<Control_Data.wCount)Control_Data.wCount=Control_Data.wLength;
  587.              break;
  588.                 case PHYSICAL_DESCRIPTOR:
  589.                      Prints("        获取物理描述符................................",1);
  590.                          break;
  591.                  default:
  592.                      Prints("       获取其它描述符..................描述符索引为:",0);
  593.                          PrintLongInt(MSB(Control_Data.DeviceRequest.wValue));
  594.                          Prints("",1);
  595.                   break;
  596.                    }
  597.       if(Control_Data.wLength<Control_Data.wCount)Control_Data.wCount=Control_Data.wLength;
  598.          }
  599.         //写数据到D12输入端点
  600.     if(Control_Data.wCount>=MAX_CONTROL_DATA_SIZE)
  601.      {
  602.           write_endpoint_buff(1,MAX_CONTROL_DATA_SIZE,Control_Data.pData);
  603.           Control_Data.pData+=MAX_CONTROL_DATA_SIZE;
  604.       Control_Data.wCount-=MAX_CONTROL_DATA_SIZE;
  605.           if(usb_flags.flags.set_addr)usb_flags.flags.not_end=1;
  606.            else usb_flags.flags.usb_endp0_in=0;
  607.           return;
  608.          }
  609.     else
  610.      {
  611.           write_endpoint_buff(1,Control_Data.wCount,Control_Data.pData);
  612.       usb_flags.flags.setup_packet_in=0;
  613.           usb_flags.flags.usb_endp0_in=0;
  614.           return;
  615.          }      
  616. }
  617. /******************************************************************************/

  618. /************************终端点0输出中断处理************************************/
  619. void endp0_out(void)
  620. {
  621. Last_Status.Register=read_last_status(0);
  622. if(Last_Status.Status.setup_packet)
  623.   {
  624.    Control_Data.wLength=0;
  625.    Control_Data.wCount=0;
  626.    if(read_endpoint_buff(0,sizeof(Control_Data.DeviceRequest),(uint8 *)(&(Control_Data.DeviceRequest)))!=sizeof(REQUESTCMD))
  627.     {
  628.          set_endpoint_status(0,0);
  629.          set_endpoint_status(1,0);
  630.          return;
  631.         }
  632.   Control_Data.DeviceRequest.wValue=SWAP16(Control_Data.DeviceRequest.wValue);
  633.   Control_Data.DeviceRequest.wIndex=SWAP16(Control_Data.DeviceRequest.wIndex);
  634.   Control_Data.DeviceRequest.wLength=SWAP16(Control_Data.DeviceRequest.wLength);

  635.   ack_setup(0);
  636.   ack_setup(1);
  637.   Control_Data.wLength=Control_Data.DeviceRequest.wLength;
  638.   usb_flags.flags.not_end=0;
  639.   usb_flags.flags.usb_endp0_in=1;
  640.   usb_flags.flags.setup_packet_in=0;
  641.   usb_flags.flags.setup_packet_out=0;
  642.   if(Control_Data.DeviceRequest.bmRequestType&0x80){usb_flags.flags.setup_packet_in=1;return;}
  643.   else {usb_flags.flags.setup_packet_out=1;return;}
  644. }
  645. else
  646.   {
  647.    select_endpoint(0);
  648.    clear_buffer();
  649.   }
  650. }
  651. /******************************************************************************/

  652. /***********************获取报告*********************************************/
  653. void get_report(void)
  654. {
  655. Prints("        获取报告................................",1);
  656. }
  657. /******************************************************************************/

  658. /**********************获取空闲状态*********************************************/
  659. void get_idle(void)
  660. {
  661. Prints("    获取空闲................................",1);
  662. write_endpoint_buff(1,1,&idle);
  663. usb_flags.flags.usb_endp0_in=0;
  664. }
  665. /******************************************************************************/

  666. /*************************获取协议**********************************************/
  667. void get_protocol(void)
  668. {
  669. Prints("    获取协议................................",1);
  670. write_endpoint_buff(1,1,&protocol);
  671. usb_flags.flags.usb_endp0_in=0;
  672. }
  673. /******************************************************************************/

  674. /***********************设置报告***********************************************/
  675. void set_report(void)
  676. {
  677. Prints("    设置报告................................",1);
  678. }
  679. /******************************************************************************/

  680. /***********************设置空闲***********************************************/
  681. void set_idle(void)
  682. {
  683. Prints("    设置空闲................................",1);
  684. while(select_endpoint(1)&0x01);
  685. write_endpoint_buff(1,0,0);
  686. idle=Control_Data.DeviceRequest.wValue;
  687. usb_flags.flags.usb_endp0_in=0;
  688. usb_flags.flags.setup_packet_out=0;
  689. }
  690. /******************************************************************************/

  691. /**********************设置协议**************************************************/
  692. void set_protocol(void)
  693. {
  694. Prints("    设置协议................................",1);
  695. while(select_endpoint(1)&0x01);
  696. write_endpoint_buff(1,0,0);
  697. protocol=Control_Data.DeviceRequest.wValue;
  698. usb_flags.flags.usb_endp0_in=0;
  699. usb_flags.flags.setup_packet_out=0;
  700. }
  701. /******************************************************************************/

  702. /****************************终端点0输入处理**************************************/
  703. void endp0_in(void)
  704. {
  705. read_last_status(1);
  706. //如果是输入请求包
  707. if(usb_flags.flags.setup_packet_in||usb_flags.flags.not_end)
  708.   {
  709.     switch(Control_Data.DeviceRequest.bmRequestType&0x60)
  710.          {
  711.            case 0x00:  //标准请求
  712.            Prints("USB标准请求................................",1);
  713.            switch(Control_Data.DeviceRequest.bmRequestType&0x1F)
  714.             {
  715.                  case 0: //到设备
  716.                    switch (Control_Data.DeviceRequest.bRequest)
  717.                     {
  718.                      case 0: get_status(0);break;
  719.                      case 6: get_descriptor();break;
  720.                      case 8: get_configuration();break;
  721.                          default:break;
  722.                     }
  723.                  break;

  724.                  case 1:  //到接口
  725.                    switch (Control_Data.DeviceRequest.bRequest)
  726.                     {
  727.                  case  0: get_status(1);break;
  728.                           case 6: get_descriptor_interface();break;
  729.                      case 10: get_interface();break;
  730.                  default: break;
  731.                         }
  732.                  break;

  733.                  case 2:  //到端点
  734.                   {
  735.                if(Control_Data.DeviceRequest.bRequest==0)get_status(2);  
  736.                   }
  737.                  default: break;
  738.             }
  739.            break;

  740.            case 0x20:  //类请求
  741.        Prints("USB类请求................................",1);
  742.            switch(Control_Data.DeviceRequest.bmRequestType&0x1F)
  743.             {
  744.                  case 0:  //到设备
  745.                    switch (Control_Data.DeviceRequest.bRequest)
  746.                     {
  747.                          default:break;
  748.                     }
  749.                  break;

  750.                  case 1:  //到接口
  751.                    switch (Control_Data.DeviceRequest.bRequest)
  752.                     {

  753.                            case   GET_REPORT: get_report();   break; //获取报告
  754.              case     GET_IDLE: get_idle();     break; //获取空闲状态
  755.              case GET_PROTOCOL: get_protocol(); break; //获取协议
  756.                  default: break;
  757.                         }
  758.                  break;

  759.                  case 2:  //到端点
  760.                   {
  761.                    switch (Control_Data.DeviceRequest.bRequest)
  762.                     {
  763.                  default: break;
  764.                         }  
  765.                   }
  766.                  default: break;
  767.             }
  768.            break;

  769.            case 0x40:  //用户请求
  770.        Prints("USB用户请求................................",1);
  771.            switch(Control_Data.DeviceRequest.bmRequestType&0x1F)
  772.             {
  773.                  case 0:  //到设备
  774.                    switch (Control_Data.DeviceRequest.bRequest)
  775.                     {
  776.                          default: break;
  777.                     }
  778.              break;

  779.                  case 1:   //到接口
  780.                    switch (Control_Data.DeviceRequest.bRequest)
  781.                     {
  782.                  default: break;
  783.                         }
  784.          break;

  785.                  case 2:  //到端点
  786.                   {
  787.                    switch (Control_Data.DeviceRequest.bRequest)
  788.                     {
  789.                  default: break;
  790.                         }  
  791.                   }
  792.                  default: break;
  793.             }
  794.         }
  795.     return;
  796.   }

  797.   //如果是输出请求包
  798. if(usb_flags.flags.setup_packet_out)
  799.   {
  800.     switch(Control_Data.DeviceRequest.bmRequestType&0x60)
  801.          {
  802.            case 0x00:  //标准请求
  803.            Prints("USB标准请求................................",1);
  804.            switch(Control_Data.DeviceRequest.bmRequestType&0x1F)
  805.             {
  806.                  case 0:   //到设备
  807.              switch (Control_Data.DeviceRequest.bRequest)
  808.               {
  809.                    case     CLEAR_FEATURE: clear_feature(0);break;
  810.                    case       SET_FEATURE: set_feature(0);break;
  811.                    case       SET_ADDRESS: set_usb_address();break;          //set_address                  
  812.                    case    SET_DESCRIPTOR: set_descriptor();break;           //set_descriptor
  813.                    case SET_CONFIGURATION: set_configuration(); break;       //set_configurat                                 
  814.                      default: break;
  815.                   }
  816.                  break;
  817.                  
  818.                  case 1:   //到接口
  819.               switch (Control_Data.DeviceRequest.bRequest)
  820.                    {
  821.                     case CLEAR_FEATURE:  clear_feature(1);break;
  822.                     case   SET_FEATURE:  set_feature(1); break;
  823.                 case SET_INTERFACE: set_interface();break;
  824.                     default: break;
  825.                 }
  826.                  break;
  827.                  
  828.                  case 2:   //到端点
  829.                   switch (Control_Data.DeviceRequest.bRequest)
  830.                    {
  831.                     case CLEAR_FEATURE: clear_feature(2);break;
  832.                     case   SET_FEATURE: set_feature(2);break;
  833.                 default: break;      
  834.                    }
  835.                  break;

  836.                  default: break;
  837.             }
  838.       break;

  839.           case 0x20:  //类请求
  840.       Prints("USB类请求................................",1);
  841.            switch(Control_Data.DeviceRequest.bmRequestType&0x1F)
  842.             {
  843.                  case 0:    //接收者为设备
  844.              switch (Control_Data.DeviceRequest.bRequest)
  845.               {                              
  846.                      default: break;
  847.                   }
  848.                  break;

  849.                  case 1:   //接收者为接口
  850.               switch (Control_Data.DeviceRequest.bRequest)
  851.                    {
  852.             case   SET_REPORT: set_report();   break; //设置报告
  853.             case     SET_IDLE: set_idle();     break; //设置空闲
  854.             case SET_PROTOCOL: set_protocol(); break; //设置协议
  855.                     default: break;
  856.                 }
  857.                  
  858.                  break;

  859.                  case 2:   //接收者为端点
  860.                   switch (Control_Data.DeviceRequest.bRequest)
  861.                    {
  862.                 default: break;      
  863.                    }
  864.                  break;
  865.                  
  866.                  case 3: //其它接收者
  867.                   switch (Control_Data.DeviceRequest.bRequest)
  868.                    {
  869.                 default: break;      
  870.                    }break;
  871.                                     
  872.                  default: break;
  873.             }      
  874.            break;

  875.        case 0x40:  //用户请求
  876.            Prints("USB用户请求................................",1);
  877.            switch(Control_Data.DeviceRequest.bmRequestType&0x1F)
  878.             {
  879.                  case 0:    //接收者为设备
  880.              switch (Control_Data.DeviceRequest.bRequest)
  881.               {                              
  882.                      default: break;
  883.                   }
  884.                  break;
  885.                  
  886.                  case 1:   //接收者为接口
  887.               switch (Control_Data.DeviceRequest.bRequest)
  888.                    {
  889.                     default: break;
  890.                 }
  891.              break;
  892.                  
  893.                  case 2:   //接收者为端点
  894.                   switch (Control_Data.DeviceRequest.bRequest)
  895.                    {
  896.                 default: break;      
  897.                    }
  898.                  break;
  899.                  
  900.                  case 3: //其它接收者
  901.                   switch (Control_Data.DeviceRequest.bRequest)
  902.                    {
  903.                 default: break;      
  904.                    }                  
  905.                  break;
  906.                                     
  907.                  default: break;
  908.             }
  909.         }
  910.   }
  911. }
  912. /******************************************************************************/

  913. /**********************端点1输出***********************************************/
  914. /*void endp1_out(void)
  915. {
  916. Prints("端点1输出................................",1);
  917. }*/
  918. /******************************************************************************/

  919. /*************************端点1输入*****************************************/
  920. /*void endp1_in(void)
  921. {
  922. Prints("端点1输入................................",1);
  923. }*/
  924. /******************************************************************************/

  925. /***************************端点2输出****************************************/
  926. void endp2_out(void)
  927. {
  928. uint8 i,j;

  929. j=read_endpoint_buff(4,64,buffer);
  930. P2=~buffer[0];
  931. Prints("端点2输出................................",1);
  932. Prints("    端点2的数据是  ",0);
  933. for(i=0;i<j;i++)
  934.   {
  935.    PrintHex(buffer[i]);
  936.    if(i==16)Prints("",1);
  937.   }
  938. Prints("",1);
  939. }
  940. /******************************************************************************/


  941. //用来返回数据的缓冲
  942. uint8 idata InBuffer[64];

  943. /***************************统计x中有多少个bit为1*******************************/
  944. uint8 Count1Bits(uint16 x)
  945. {
  946. uint8 i;

  947. i=0;
  948. while(x)
  949.   {
  950.    if(x&0x8000)i++;
  951.    x<<=1;
  952.   }
  953. return i;
  954. }
  955. /******************************************************************************/

  956. /****************************主端点输入处理************************************/
  957. void endp2_in(void)                                      
  958. {
  959. uint8 i;
  960. // Prints("端点2输入................................",1);
  961. KeyMapCanChange=0;  //禁止修改按键值
  962. if(KeyMapOk) //如果有按键按下
  963.   {
  964.    //4*4的键盘,最多能够识别3个键同时按下,
  965.    //如果开关上接二极管可以同时识别更多的键
  966.    if(Count1Bits(KeyMapOk)>3)
  967.     {
  968.          for(i=2;i<8;i++)InBuffer[i]=0x01;  //按键过多
  969.         }
  970.    else
  971.     {
  972.      if(KeyMapOk&(1<<3)) //左Ctrl键
  973.       {
  974.        InBuffer[0]|=1;
  975.       }
  976.      else
  977.       {
  978.        InBuffer[0]&=~1;
  979.       }
  980.         
  981.      if(KeyMapOk&(1<<7)) //左shift键
  982.       {
  983.        InBuffer[0]|=1<<1;
  984.       }
  985.      else
  986.       {
  987.        InBuffer[0]&=~(1<<1);
  988.       }
  989.         
  990.      if(KeyMapOk&(1<<2)) //左ALT键
  991.       {
  992.        InBuffer[0]|=1<<2;
  993.       }
  994.      else
  995.       {
  996.            InBuffer[0]&=~(1<<2);
  997.           }
  998.          i=2;
  999.          if(KeyMapOk&(1))
  1000.           {
  1001.            InBuffer[i++]=0x28;            //回车键
  1002.           }
  1003.          if(KeyMapOk&(1<<1))
  1004.           {
  1005.            InBuffer[i++]=0x62;            //0键
  1006.           }
  1007.          if(KeyMapOk&(1<<4))
  1008.           {
  1009.            InBuffer[i++]=0x5B;            //3键
  1010.           }
  1011.          if(KeyMapOk&(1<<5))
  1012.           {
  1013.            InBuffer[i++]=0x5A;            //2键
  1014.           }
  1015.          if(KeyMapOk&(1<<6))
  1016.           {
  1017.            InBuffer[i++]=0x59;            //1键
  1018.           }
  1019.          if(KeyMapOk&(1<<8))
  1020.           {
  1021.            InBuffer[i++]=0x5E;            //6键
  1022.           }
  1023.          if(KeyMapOk&(1<<9))
  1024.           {
  1025.            InBuffer[i++]=0x5D;            //5键
  1026.           }
  1027.          if(KeyMapOk&(1<<10))
  1028.           {
  1029.            InBuffer[i++]=0x5C;            //4键
  1030.           }
  1031.          if(KeyMapOk&(1<<11))
  1032.           {
  1033.            InBuffer[i++]=0x39;            //Caps Lock键
  1034.           }
  1035.          if(KeyMapOk&(1<<12))
  1036.           {
  1037.            InBuffer[i++]=0x61;            //9键
  1038.           }
  1039.          if(KeyMapOk&(1<<13))
  1040.           {
  1041.            InBuffer[i++]=0x60;            //8键
  1042.           }
  1043.          if(KeyMapOk&(1<<14))
  1044.           {
  1045.            InBuffer[i++]=0x5F;            //2键
  1046.           }
  1047.          if(KeyMapOk&(1<<15))
  1048.           {
  1049.            InBuffer[i++]=0x53;            //Num Lock键
  1050.           }
  1051.          for(;i<8;i++)
  1052.           {
  1053.            InBuffer[i]=0;  //多余的清0
  1054.           }
  1055.         }
  1056.   }
  1057. else //如果无按键按下,则返回0
  1058.   {
  1059.    for(i=0;i<8;i++)
  1060.     {
  1061.          InBuffer[i]=0;
  1062.         }
  1063.   }
  1064. KeyMapCanChange=1; //允许修改按键值
  1065. //返回8个字节数据
  1066. write_endpoint_buff(5,8,InBuffer);
  1067. }
  1068. /******************************************************************************/


  1069. /***************************主函数**********************************************/
  1070. void main(void)
  1071. {
  1072. InitUART();  //串口初始化
  1073. Printc(0x0c);  //清屏
  1074. Printc(0x0c);
  1075. Prints("系统启动................................",1);
  1076. delay(1000);         //延迟
  1077. disconnect_usb();            //断开USB连接
  1078. init_usb();                   //初始化USB芯片
  1079. connect_usb();                   //连接USB
  1080. InitTimer0();  //定时器0初始化,用来做键盘扫描,定时时间大约为5ms



  1081. …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码


0.png
下载:
51单片机模拟一个USB键盘的代码,.rar (322.46 KB, 下载次数: 364)

评分

参与人数 2黑币 +6 收起 理由
a4270 + 1
jinmei1314 + 5 很给力!

查看全部评分

回复

使用道具 举报

ID:196774 发表于 2017-5-5 08:38 | 显示全部楼层
谢谢分享,感觉很有用
回复

使用道具 举报

ID:91469 发表于 2017-9-29 10:32 来自手机 | 显示全部楼层
d12的应用!学习了
回复

使用道具 举报

ID:99130 发表于 2017-9-29 19:02 | 显示全部楼层
上面那个IC是什么型号
回复

使用道具 举报

ID:68356 发表于 2017-9-30 15:52 | 显示全部楼层
好东西,感谢分享
回复

使用道具 举报

ID:245832 发表于 2017-11-3 21:22 | 显示全部楼层
好东西,感谢分享
回复

使用道具 举报

ID:137231 发表于 2017-11-3 22:37 | 显示全部楼层
谢谢分享
回复

使用道具 举报

ID:251833 发表于 2017-11-21 11:57 | 显示全部楼层

谢谢分享
回复

使用道具 举报

ID:255846 发表于 2017-12-7 13:46 | 显示全部楼层
谢谢分享
回复

使用道具 举报

ID:259719 发表于 2017-12-10 12:32 | 显示全部楼层
谢谢分享
回复

使用道具 举报

ID:112865 发表于 2017-12-14 11:28 | 显示全部楼层
看一下
回复

使用道具 举报

ID:264054 发表于 2017-12-23 14:58 | 显示全部楼层
好东西,学习一下
回复

使用道具 举报

ID:230470 发表于 2018-1-17 15:43 | 显示全部楼层
已经下载学习了,感觉很实用
回复

使用道具 举报

ID:200117 发表于 2018-1-20 14:00 | 显示全部楼层
好东西,学习学习
回复

使用道具 举报

ID:116893 发表于 2018-3-1 16:33 | 显示全部楼层
下来学习学习了,多谢
回复

使用道具 举报

ID:320626 发表于 2018-5-2 18:08 | 显示全部楼层
正想搞一个~
回复

使用道具 举报

ID:330209 发表于 2018-5-15 10:18 | 显示全部楼层
正在找这个资料,也想做个键盘。
回复

使用道具 举报

ID:46331 发表于 2018-5-15 15:02 | 显示全部楼层
用不了  
回复

使用道具 举报

ID:344671 发表于 2018-6-4 15:01 | 显示全部楼层
学习学习。。。。。。
回复

使用道具 举报

ID:357808 发表于 2018-6-24 15:29 | 显示全部楼层
感谢楼主分享
回复

使用道具 举报

ID:377104 发表于 2018-7-22 09:34 | 显示全部楼层
感谢分享,好好学习一下
回复

使用道具 举报

ID:399212 发表于 2018-9-17 20:20 | 显示全部楼层
数组真的剪啊
回复

使用道具 举报

ID:285069 发表于 2018-9-18 09:42 | 显示全部楼层
手上剛好有D12 USB芯片;可供參考.感謝分想
回复

使用道具 举报

ID:406411 发表于 2018-10-8 10:41 | 显示全部楼层
用普通的IO模拟的话,速度跟的上吗?
回复

使用道具 举报

ID:406559 发表于 2018-10-8 15:41 | 显示全部楼层
正好需要做一个模拟键盘,先学习学习
回复

使用道具 举报

ID:407803 发表于 2018-10-10 23:15 | 显示全部楼层
学习了,DIY爱好者,正在做一个键盘模拟器,学习分享。
回复

使用道具 举报

ID:414016 发表于 2018-10-23 14:22 | 显示全部楼层
不错,学习学习
回复

使用道具 举报

ID:390615 发表于 2018-11-1 07:32 | 显示全部楼层
不错的,是不是根据书上的例子改编的?
回复

使用道具 举报

ID:390615 发表于 2018-11-1 07:33 | 显示全部楼层

不错,学习学习
回复

使用道具 举报

ID:418921 发表于 2018-11-1 09:25 来自手机 | 显示全部楼层
厉害,有空弄一下
回复

使用道具 举报

ID:422825 发表于 2018-11-8 10:43 | 显示全部楼层
太棒了!~感谢
回复

使用道具 举报

ID:428228 发表于 2018-11-17 16:04 | 显示全部楼层
谢谢分享,十分有用!
回复

使用道具 举报

ID:286005 发表于 2018-12-1 15:48 | 显示全部楼层
楼主推荐的程序有用,先参考一下,解决我的疑惑
回复

使用道具 举报

ID:404514 发表于 2018-12-3 20:57 | 显示全部楼层
感谢楼主分享
回复

使用道具 举报

ID:73182 发表于 2018-12-4 10:15 | 显示全部楼层
源码编译不过
回复

使用道具 举报

ID:404159 发表于 2018-12-10 13:38 | 显示全部楼层
谢谢分享   
回复

使用道具 举报

ID:459203 发表于 2019-2-12 21:55 | 显示全部楼层
谢谢分享,感觉很有用
回复

使用道具 举报

ID:476052 发表于 2019-2-12 23:19 | 显示全部楼层
很实用
回复

使用道具 举报

ID:224094 发表于 2019-3-27 10:09 | 显示全部楼层
感谢分享!!!!!!!!!!!!
回复

使用道具 举报

ID:500112 发表于 2019-3-28 19:15 | 显示全部楼层
请问下这个的功能是不是通过单片机来控制电脑USB键盘的输入?
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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