[应用方案] 自制USB键盘转载于圈圈

[复制链接]
 楼主| 捉虫天师 发表于 2016-2-11 19:31 | 显示全部楼层 |阅读模式
哈哈,终于搞了一回USB HID设备,做了一个USB键盘来玩玩~~~~其中的报告描述符让我晕了几天~~~~~几份HID相关的协议还是蛮长的~~~~~~明天再弄个USB鼠标设备玩玩~~~~~~~有空的话再搞个红外遥控器玩玩~~~
这回是拿以前做的Mass storage来改的,所以比较快,修改了一下描述符以及端点处理等,就行了。用了一个4*4的小键盘,有0-9十个数字键,Num Lock键,Caps Lock键,Shift键,Ctrl键,Alt键,回车键等。

最多可以有三个键同时按下,如果相交的话,最多只能两个键按下。


以下是通过串口返回的调试信息:

系统启动................................
断开USB连接........................
USBD12芯片初始化
   设置地址.....................
       地址为:  0
连接USB...............
USB总线复位................................
USB总线挂起................................
USB总线复位................................
USB总线挂起................................
USB总线复位................................
USB标准请求................................
    获取描述符................................
        获取设备描述符................................
USB总线复位................................
USB标准请求................................
   设置地址.....................
       地址为:  2
USB标准请求................................
    获取描述符................................
        获取设备描述符................................
USB标准请求................................
    获取描述符................................
USB标准请求................................
    获取描述符................................
        获取配置描述符................................
USB标准请求................................
    获取描述符................................
        获取字符串描述符................................
            获取语言ID................................
USB标准请求................................
    获取描述符................................
        获取字符串描述符................................
            获取设备序列号................................
USB标准请求................................
    获取描述符................................
USB标准请求................................
    获取描述符................................
        获取配置描述符................................
USB标准请求................................
    获取描述符................................
USB标准请求................................
    获取描述符................................
USB标准请求................................
    获取描述符................................
        获取字符串描述符................................
            获取语言ID................................
USB标准请求................................
    获取描述符................................
        获取字符串描述符................................
            获取产品字符串................................
USB标准请求................................
    获取描述符................................
USB标准请求................................
    获取描述符................................
USB标准请求................................
    获取描述符................................
USB标准请求................................
    获取描述符................................
USB标准请求................................
    获取描述符................................
USB标准请求................................
    获取描述符................................
        获取字符串描述符................................
            获取语言ID................................
USB标准请求................................
    获取描述符................................
        获取字符串描述符................................
            获取产品字符串................................
USB标准请求................................
    获取描述符................................
USB标准请求................................
    获取描述符................................
USB标准请求................................
    获取描述符................................
USB标准请求................................
    获取描述符................................
USB标准请求................................
    获取描述符................................
USB标准请求................................
    获取描述符................................
        获取设备描述符................................
USB标准请求................................
    获取描述符................................
USB标准请求................................
    获取描述符................................
        获取配置描述符................................
USB标准请求................................
    获取描述符................................
        获取配置描述符................................
USB标准请求................................
    获取描述符................................
USB标准请求................................
    获取描述符................................
USB标准请求................................
    设置配置................................
USB类请求................................
    设置空闲................................
USB标准请求................................
    获取描述符(从接口)..............................
        获取报告描述符................................
USB标准请求................................
    获取描述符(从接口)..............................
USB标准请求................................
    获取描述符(从接口)..............................
USB标准请求................................
    获取描述符(从接口)..............................
USB标准请求................................
    获取描述符(从接口)..............................
USB标准请求................................
    获取描述符(从接口)..............................
USB标准请求................................
    获取描述符(从接口)..............................
USB标准请求................................
    获取描述符(从接口)..............................
端点2输出................................
    端点2的数据是  0x01
端点2输出................................
    端点2的数据是  0x03
端点2输出................................
    端点2的数据是  0x01
端点2输出................................
    端点2的数据是  0x00
端点2输出................................
    端点2的数据是  0x02
端点2输出................................
    端点2的数据是  0x03


在设备管理器里看到的图:



原理图
(用的是以前做IDE转USB的板,所以上面还有个IDE接口和573锁存器,可以不用理会它们):

(注意:原理图上所标的晶体值是以前的,这个程序中使用的是22.1184M的晶体.它关系到串口波特率,如果你不使用串口,那么可以不用理会它.)


注意:图中串口电平转换部分的C8和C10接反了,C11负端应接VDD。D12的SUSPEND(12脚)应该接地。USB接头的D+和D-跟芯的D+和D-之间应该串联22欧姆的匹配电阻。片由于图得比较匆忙,所以没留意。右击选择图片另存为可以看到完整图片了.
实物图片(键盘是外接的):
  


 楼主| 捉虫天师 发表于 2016-2-11 19:32 | 显示全部楼层
  1. /******************************************************************
  2.    本程序只供学习使用,未经作者许可,不得用于其它任何用途
  3.       http://www.fxdzw.com

  4. KEY.C  file

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


  13. #include "Key.h"
  14. #include "my_type.h"

  15. uint16 idata KeyMapCurrent,KeyMapOld,KeyMapOk,KeyNoChangedTime;
  16. uint8 KeyMapCanChange;

  17. #define KeyIO P1

  18. /*************************定时器0初始化***************************************/
  19. void InitTimer0(void)
  20. {
  21. TMOD&=0xF0;
  22. TMOD|=0x01;
  23. TH0=0xDC;
  24. ET0=1;
  25. TR0=1;
  26. }
  27. /******************************************************************************/

  28. /*************************定时器0中断处理***************************************/
  29. void Timer0Isr(void) interrupt 1
  30. {
  31. uint8 temp;
  32. TH0=0xDC;         //定时器0重装
  33. KeyIO=0x0F;
  34. if((KeyIO&0x0F)==0x0F)  //如果现在没有按键按下
  35.   {
  36.    KeyMapCurrent=0;   //没有键按下
  37.   }
  38. else
  39.   {
  40.    //开始键盘扫描

  41.    //扫描第一行
  42.    KeyIO=~0x10;

  43.    //保存四个开关状态       
  44.    temp=KeyIO&0x0F;

  45.    //扫描第二行          
  46.    KeyIO=~0x20;

  47.    //保存四个开关状态                  
  48.    temp|=KeyIO<<4;

  49.    //保存按键状态到当前按键情况      
  50.    KeyMapCurrent=(~temp)&0xFF;

  51.    //扫描第三行
  52.    KeyIO=~0x40;       

  53.    //保存四个开关状态          
  54.    temp=KeyIO&0x0F;

  55.    //扫描第四行         
  56.    KeyIO=~0x80;

  57.    //保存四个开关状态          
  58.    temp|=KeyIO<<4;
  59.      
  60.    //保存全部16个开关的状态
  61.    //KeyMap总共有16个bit,当某个开关按下时,
  62.    //对应的bit为1
  63.    KeyMapCurrent|=(((uint16)~temp)<<8);
  64.   }

  65. if(KeyMapCurrent!=KeyMapOld)  //说明按键情况发生了改变
  66.   {
  67.    KeyNoChangedTime=0;       //键盘按下时间为0
  68.    KeyMapOld=KeyMapCurrent;  //保存当前按键情况
  69.    return;
  70.   }
  71. else
  72.   {
  73.    KeyNoChangedTime++;          //按下时间累计
  74.    if(KeyNoChangedTime>=1)         //如果按下时间足够
  75.     {
  76.          KeyNoChangedTime=1;
  77.          if(KeyMapCanChange)
  78.           {
  79.            KeyMapOk=KeyMapOld;  //保存按键
  80.           }
  81.         }
  82.   }
  83. }
  84. /******************************************************************************/


 楼主| 捉虫天师 发表于 2016-2-11 19:33 | 显示全部楼层
  1. /******************************************************************
  2.    本程序只供学习使用,未经作者许可,不得用于其它任何用途
  3.       http://www.fxdzw.com

  4. UART.C  file

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

  13. #include <at89x52.H>

  14. #include "UART.h"
  15. #include "my_type.h"

  16. uint8 Sending;


  17. //**************************************************************************************
  18. void InitUART(void)  //串口初始化函数,使用22.1184M晶体
  19. {
  20. EA=0;
  21. TMOD&=0x0F;
  22. TMOD|=0x20;    //定时器1工作在模式2
  23. SCON=0x50;    //串口工作在模式1
  24. TCON=0x05;
  25. TH1=0xF4;     //9600bps
  26. TL1=0xF4;
  27. PCON=0x80;    //串口波特率加倍
  28. ES=1;         //串行中断允许
  29. TR1=1;        //启动定时器1
  30. REN=1;        //允许接收
  31. EA=1;         //允许中断
  32. }
  33. //****************************************************************************************


  34. //*******************************   串口中断处理        ***********************************
  35. void SerialPort(void) interrupt 4
  36. {
  37. if(RI)    //收到数据
  38.   {
  39.    RI=0;                     //清中断请求
  40.   }
  41. else  //发送完一字节数据
  42.   {
  43.    TI=0;
  44.    Sending=0;               //清正在发送标志
  45.   }
  46. }
  47. //*****************************************************************************************

  48. //*****************************************************************************************
  49. void SendToComport(unsigned char d)       //往串口发送一字节数据
  50. {
  51. Sending=1;
  52. SBUF=d;
  53. while(Sending);
  54. }
  55. //*****************************************************************************************

  56. //*****************************************************************************************
  57. //发送一个字符串
  58. void prints(uint8 * pd,uint8 line_feed)
  59. {
  60. while((*pd)!='\0')
  61.   {
  62.    SendToComport(*pd);
  63.    pd++;
  64.   }
  65. if(line_feed)
  66. {
  67.   SendToComport(13);
  68.   SendToComport(10);
  69. }
  70. }
  71. //****************************************************************************************



  72. //*****************************************************************************************
  73. void PrintLongInt(uint32 x)  //将整数转按十进制字符串发送
  74. {
  75. int8 i;
  76. uint8 display_buffer[10];
  77. display_buffer[10]=0;
  78. for(i=9;i>=0;i--)
  79.   {
  80.    display_buffer[i]='0'+x%10;
  81.    x/=10;
  82.   }
  83. for(i=0;i<9;i++)
  84.   {
  85.    if(display_buffer[i]!='0')break;
  86.   }
  87. for(;i<10;i++)SendToComport(display_buffer[i]);
  88. }
  89. //*****************************************************************************************


  90. code uint8 HexTable[]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
  91. //*****************************************************************************************
  92. /*
  93. void PrintLongIntHex(uint32 x)  //将整数按十六进制发送
  94. {
  95. uint8 i;
  96. uint8 display_buffer[11];
  97. display_buffer[10]=0;
  98. display_buffer[0]='0';
  99. display_buffer[1]='x';
  100. for(i=9;i>=2;i--)
  101.   {
  102.    display_buffer[i]=HexTable[(x&0xf)];
  103.    x>>=4;
  104.   }
  105. prints(display_buffer,0);
  106. }
  107. */
  108. //*****************************************************************************************


  109. //*****************************************************************************************
  110. void Printc(uint8 x)  //发送一个byte的数据
  111. {
  112. Sending=1;
  113. SBUF=x;
  114. while(Sending);
  115. }
  116. //*****************************************************************************************


  117. //*****************************************************************************************
  118. void PrintHex(uint8 x)  //以HEX格式发送一个byte的数据
  119. {
  120. Printc('0');
  121. Printc('x');
  122. Printc(HexTable[x>>4]);
  123. Printc(HexTable[x&0xf]);
  124. Printc(' ');
  125. }
  126. //*****************************************************************************************


Thethree 发表于 2016-2-14 10:01 | 显示全部楼层
我前段时间也制作了USB键盘,不过用的是带USB的芯片
wahahaheihei 发表于 2016-2-14 12:06 | 显示全部楼层
图中串口电平转换部分的C8和C10接反了,C11负端应接VDD。
dentsgot 发表于 2016-2-14 17:50 | 显示全部楼层
这个USB做的hid 键盘在仪器上还是很实用的
您需要登录后才可以回帖 登录 | 注册

本版积分规则

212

主题

3272

帖子

7

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

212

主题

3272

帖子

7

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