久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 32552|回復: 47
打印 上一主題 下一主題
收起左側

用51單片機模擬USB鍵盤源程序及原理圖

  [復制鏈接]
跳轉到指定樓層
樓主
使用51單片機模擬USB鍵盤原理圖(附件里面可以下載清晰版的電路圖及完整源碼):



單片機源程序:
  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黑下載附件…………
復制代碼



下載:
51單片機模擬一個USB鍵盤的代碼,.rar (322.46 KB, 下載次數: 364)

評分

參與人數 2黑幣 +6 收起 理由
a4270 + 1
jinmei1314 + 5 很給力!

查看全部評分

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏17 分享淘帖 頂3 踩
回復

使用道具 舉報

沙發
ID:196774 發表于 2017-5-5 08:38 | 只看該作者
謝謝分享,感覺很有用
回復

使用道具 舉報

板凳
ID:91469 發表于 2017-9-29 10:32 來自手機 | 只看該作者
d12的應用!學習了
回復

使用道具 舉報

地板
ID:99130 發表于 2017-9-29 19:02 | 只看該作者
上面那個IC是什么型號
回復

使用道具 舉報

5#
ID:68356 發表于 2017-9-30 15:52 | 只看該作者
好東西,感謝分享
回復

使用道具 舉報

6#
ID:245832 發表于 2017-11-3 21:22 | 只看該作者
好東西,感謝分享
回復

使用道具 舉報

7#
ID:137231 發表于 2017-11-3 22:37 | 只看該作者
謝謝分享
回復

使用道具 舉報

8#
ID:251833 發表于 2017-11-21 11:57 | 只看該作者

謝謝分享
回復

使用道具 舉報

9#
ID:255846 發表于 2017-12-7 13:46 | 只看該作者
謝謝分享
回復

使用道具 舉報

10#
ID:259719 發表于 2017-12-10 12:32 | 只看該作者
謝謝分享
回復

使用道具 舉報

11#
ID:112865 發表于 2017-12-14 11:28 | 只看該作者
看一下
回復

使用道具 舉報

12#
ID:264054 發表于 2017-12-23 14:58 | 只看該作者
好東西,學習一下
回復

使用道具 舉報

13#
ID:230470 發表于 2018-1-17 15:43 | 只看該作者
已經下載學習了,感覺很實用
回復

使用道具 舉報

14#
ID:200117 發表于 2018-1-20 14:00 | 只看該作者
好東西,學習學習
回復

使用道具 舉報

15#
ID:116893 發表于 2018-3-1 16:33 | 只看該作者
下來學習學習了,多謝
回復

使用道具 舉報

16#
ID:320626 發表于 2018-5-2 18:08 | 只看該作者
正想搞一個~
回復

使用道具 舉報

17#
ID:330209 發表于 2018-5-15 10:18 | 只看該作者
正在找這個資料,也想做個鍵盤。
回復

使用道具 舉報

18#
ID:46331 發表于 2018-5-15 15:02 | 只看該作者
用不了  
回復

使用道具 舉報

19#
ID:344671 發表于 2018-6-4 15:01 | 只看該作者
學習學習。。。。。。
回復

使用道具 舉報

20#
ID:357808 發表于 2018-6-24 15:29 | 只看該作者
感謝樓主分享
回復

使用道具 舉報

21#
ID:377104 發表于 2018-7-22 09:34 | 只看該作者
感謝分享,好好學習一下
回復

使用道具 舉報

22#
ID:399212 發表于 2018-9-17 20:20 | 只看該作者
數組真的剪啊
回復

使用道具 舉報

23#
ID:285069 發表于 2018-9-18 09:42 | 只看該作者
手上剛好有D12 USB芯片;可供參考.感謝分想
回復

使用道具 舉報

24#
ID:406411 發表于 2018-10-8 10:41 | 只看該作者
用普通的IO模擬的話,速度跟的上嗎?
回復

使用道具 舉報

25#
ID:406559 發表于 2018-10-8 15:41 | 只看該作者
正好需要做一個模擬鍵盤,先學習學習
回復

使用道具 舉報

26#
ID:407803 發表于 2018-10-10 23:15 | 只看該作者
學習了,DIY愛好者,正在做一個鍵盤模擬器,學習分享。
回復

使用道具 舉報

27#
ID:414016 發表于 2018-10-23 14:22 | 只看該作者
不錯,學習學習
回復

使用道具 舉報

28#
ID:390615 發表于 2018-11-1 07:32 | 只看該作者
不錯的,是不是根據書上的例子改編的?
回復

使用道具 舉報

29#
ID:390615 發表于 2018-11-1 07:33 | 只看該作者

不錯,學習學習
回復

使用道具 舉報

30#
ID:418921 發表于 2018-11-1 09:25 來自手機 | 只看該作者
厲害,有空弄一下
回復

使用道具 舉報

31#
ID:422825 發表于 2018-11-8 10:43 | 只看該作者
太棒了!~感謝
回復

使用道具 舉報

32#
ID:428228 發表于 2018-11-17 16:04 | 只看該作者
謝謝分享,十分有用!
回復

使用道具 舉報

33#
ID:286005 發表于 2018-12-1 15:48 | 只看該作者
樓主推薦的程序有用,先參考一下,解決我的疑惑
回復

使用道具 舉報

34#
ID:404514 發表于 2018-12-3 20:57 | 只看該作者
感謝樓主分享
回復

使用道具 舉報

35#
ID:73182 發表于 2018-12-4 10:15 | 只看該作者
源碼編譯不過
回復

使用道具 舉報

36#
ID:404159 發表于 2018-12-10 13:38 | 只看該作者
謝謝分享   
回復

使用道具 舉報

37#
ID:459203 發表于 2019-2-12 21:55 | 只看該作者
謝謝分享,感覺很有用
回復

使用道具 舉報

38#
ID:476052 發表于 2019-2-12 23:19 | 只看該作者
很實用
回復

使用道具 舉報

39#
ID:224094 發表于 2019-3-27 10:09 | 只看該作者
感謝分享!!!!!!!!!!!!
回復

使用道具 舉報

40#
ID:500112 發表于 2019-3-28 19:15 | 只看該作者
請問下這個的功能是不是通過單片機來控制電腦USB鍵盤的輸入?
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 免费av直接看 | 国产成人在线观看免费 | 黄色一级免费 | 91久久久久久久久 | 国产精品福利视频 | 在线观看亚洲专区 | 国产一区二区小视频 | 亚洲欧美国产精品久久 | av中文字幕在线播放 | 成人免费在线播放 | 欧美性生活网 | 久久国产精品偷 | 国产资源在线视频 | 午夜三级视频 | 999观看免费高清www | 欧美成人精品一区二区三区 | 欧美成人一级 | 欧美日韩高清一区 | 黄视频国产 | av网站在线看 | 成人在线中文 | 色天堂影院 | 日本粉嫩一区二区三区视频 | 91精品欧美久久久久久久 | 九九综合 | 人人爽日日躁夜夜躁尤物 | 国产一区二区欧美 | 亚洲精品久久久久久下一站 | 伊人网伊人网 | 观看av| 国产伦精品一区二区三区照片91 | 天天干天天谢 | 性做久久久久久免费观看欧美 | 一区在线免费视频 | 欧美精品三区 | 超碰日本 | 久久久久国产精品一区二区 | 成人午夜网站 | 韩国久久| 国产一级在线 | 永久免费视频 |