找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 4147|回复: 1
打印 上一主题 下一主题
收起左侧

PDIUSBD12-USB键盘keyboard,51单片机程序源码

[复制链接]
跳转到指定楼层
楼主
PDIUSBD12芯片做的usb键盘的一个例子,51单片机主控.
EDN USB开发板上共有8个按键,功能分别为:
K1:左Ctrl键  K2:左Shift键  K3:左Alt键  K4:0键
K5:1键  K6:2键  K7:Caps Lock键 K8:Num Lock键

按键功能测试:

同时按下K1和K2可做输入法切换,这跟键盘上的两个键功能一样的。
K7可打开大写字母锁定,同时LED2亮起。K8是小数字键盘锁定键,
当数字键盘打开时,LED1亮起,这时可用K4,K5,K6输入数字。
请留意EDN板上的LED会跟你自己的键盘上的LED灯同步。不管按哪块
键盘切换都是如此。不过按住切换键不放,可能会导致两块键盘之间
的LED失步。


所有资料51hei提供下载:
PDIUSBD12-keyboard.rar (112.77 KB, 下载次数: 48)


PDIUSBD12芯片USB键盘的单片机源程序如下:
  1. /******************************************************************
  2.    本程序只供学习使用,未经作者许可,不得用于其它任何用途
  3. USBKeyBoard.C  file
  4. 作者:Computer-lov
  5. 版本:V1.1
  6. 版权所有,盗版必究。
  7. Copyright(C) Computer-lov 2007-2017
  8. All rights reserved            
  9. *******************************************************************/

  10. #include "AT89x52.H"
  11. #include "USB.H"
  12. #include "PDIUSBD12.H"
  13. #include "My_type.h"
  14. #include "UART.H"
  15. #include "key.h"
  16. #include "keyboard.h"
  17. #include "led.h"

  18. #define DispLineInf()      \
  19. {                          \
  20. Prints(" in file \"");    \
  21. Prints(__FILE__);         \
  22. Prints(", @ line ");      \
  23. PrintLongInt(__LINE__-1); \
  24. Prints("\r\n");           \
  25. }

  26. //#define debug

  27. #define USB_COMMAND_ADD           1
  28. #define USB_DATA_ADD              0

  29. //USB芯片连接引脚
  30. #define USB_DATA                  P0
  31. #define USB_A0                    P3_5
  32. #define USB_WR                    P3_6
  33. #define USB_RD                    P3_7
  34. #define USB_INT                   P3_2


  35. #define ENDPOINT_NUMBER           2
  36. #define MAX_CONTROL_DATA_SIZE     16


  37. //控制传输时保存数据
  38. CONTROL_DATA_BUFF Control_Data;

  39. //缓冲
  40. uint8 idata buffer[64];

  41. //交换数据时用的指针
  42. uint8 *pData;

  43. uint8 idle;     //空闲状态
  44. uint8 protocol; //当前协议

  45. //高低字节交换

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

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

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

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

  53. //设备序列号                                                                                
  54. code uint8 device_serial_number[]=
  55. {22,STRING_DESCRIPTOR,'2',0,'0',0,'0',0,'7',0,'-',0,'1',0,'1',0,'-',0,'2',0,'9',0};

  56. //厂商字符串
  57. //汉字Unicode编码
  58. code uint8 ManufacturerString[80]=
  59. {80,STRING_DESCRIPTOR,0x35,0x75,0x11,0x81,0x08,0x57,0x08,0x57,0x84,0x76,'U',0x00,
  60. 'S',0x00,'B',0x00,0x13,0x4E,0x3A,0x53,0x20,0x00,'H',0,'t',0,'t',0,
  61. 'p',0,':',0,'/',0,'/',0,'g',0,'r',0,'o',0,'u',0,'p',0,'.',0,'e',0,'d',0,'n',0,
  62. 'c',0,'h',0,'i',0,'n',0,'a',0,'.',0,'c',0,'o',0,'m',0,'/',0,'9',0,'3',0};

  63. //产品字符串 
  64. //汉字Unicode编码
  65. code uint8 ProducterString[96]=
  66. {96,STRING_DESCRIPTOR,0x35,0x75,0x11,0x81,0x08,0x57,0x08,0x57,0x84,0x76,'U',0x00,
  67. 'S',0x00,'B',0x00,0x13,0x4E,0x3A,0x53,0x3B,0x6D,0xA8,0x52,0x4B,0x4E,'U',0x00,
  68. 'S',0x00,'B',0x00,0x2E,0x95,0xD8,0x76,0x20,0x00,'H',0,'t',0,'t',0,
  69. 'p',0,':',0,'/',0,'/',0,'g',0,'r',0,'o',0,'u',0,'p',0,'.',0,'e',0,'d',0,'n',0,
  70. 'c',0,'h',0,'i',0,'n',0,'a',0,'.',0,'c',0,'o',0,'m',0,'/',0,'9',0,'3',0};

  71. code DEVICE_DESCRIPTOR_STRUCT device_descriptor=     //设备描述符
  72. {
  73. sizeof(DEVICE_DESCRIPTOR_STRUCT),                   //设备描述符的字节数大小
  74. DEVICE_DESCRIPTOR,                                         //设备描述符类型编号
  75. SWAP16(0x0110),                                     //USB版本号,USB1.1
  76. 0x00,                                               //USB分配的设备类代码
  77. 0x00,                                               //USB分配的子类代码
  78. 0x00,                                               //USB分配的设备协议代码
  79. 0x10,                                               //端点0的最大包大小
  80. SWAP16(0x8888),                                     //厂商编号VID,这里只是作为测试用,请使用自己的VID
  81. SWAP16(0x0001),                                     //产品编号PID,这里只是作为测试用,请使用自己的PID
  82. SWAP16(0x0001),                                     //设备出厂编号
  83. 0x01,                                               //设备厂商字符串的索引
  84. 0x02,                                               //描述产品字符串的索引
  85. 0x03,                                               //描述设备序列号字符串的索引
  86. 0x01                                                //可能的配置数量
  87. };

  88. //定义配置,接口,端点等描述符结构体,因为它们是随配置描述符一起返回的
  89. typedef struct _CON_INT_ENDP_DESCRIPTOR_STRUCT
  90. {
  91. CONFIGURATION_DESCRIPTOR_STRUCT configuration_descriptor;
  92. INTERFACE_DESCRIPTOR_STRUCT  interface_descriptor;
  93. HID_DESCRIPTOR_STRUCT hid_descriptor;
  94. ENDPOINT_DESCRIPTOR_STRUCT  endpoint_descriptor[ENDPOINT_NUMBER];
  95. }CON_INT_ENDP_DESCRIPTOR_STRUCT;

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

  156. union                                          //程序标志位
  157. {
  158. uint16 Register;
  159. struct
  160. {
  161. uint8 bus_reset        :1;
  162. uint8 suspend          :1;
  163. uint8 remote_wakeup    :1;
  164. uint8 int_isr          :1;
  165. uint8 not_end          :1;
  166. uint8 usb_idle         :1;
  167. uint8 usb_busy         :1;
  168. uint8 setup_packet_in  :1;
  169. uint8 setup_packet_out :1;
  170. uint8 set_addr         :1;
  171. uint8 usb_endp0_in     :1;
  172. uint8 usb_endp2_in     :1;
  173. uint8 usb_endp2_out    :1;
  174. }flags;
  175. }usb_flags;

  176. union                                         //中断寄存器
  177. {
  178. uint8 Register[2];
  179. struct
  180.   {
  181.    uint8 control_out_port  :1;
  182.    uint8 control_in_port   :1;
  183.    uint8 port_out_1        :1;
  184.    uint8 port_in_1         :1;
  185.    uint8 main_out_port     :1;
  186.    uint8 main_in_port      :1;
  187.    uint8 bus_reset         :1;
  188.    uint8 suspend_change    :1;
  189.    uint8 DMA_EOT           :1;
  190.    uint8 not_use           :7;
  191.   }Interrupt;
  192. }Interrupt_Register;


  193. union                                    //端点最后处理状态
  194. {
  195. uint8 Register;
  196. struct
  197. {
  198.   uint8 successful          :1;
  199.   uint8 error_code          :4;
  200.   uint8 setup_packet        :1;
  201.   uint8 data_1              :1;
  202.   uint8 prestatus_not_read  :1;
  203. }Status;
  204. }Last_Status;


  205. /*****************   延时x毫秒函数 ***********/
  206. void delay(uint16 x)               
  207. {
  208. uint16 i;
  209. uint16 j;
  210. for(i=0;i<x;i++)
  211. for(j=0;j<230;j++);
  212. }
  213. /********************************************/

  214. /*******************************写USB命令******************************************/
  215. void write_usb_command(uint8 usb_command)
  216. {
  217. USB_A0=USB_COMMAND_ADD;
  218. USB_DATA=usb_command;
  219. USB_WR=0;
  220. USB_WR=1;
  221. USB_DATA=0xFF;
  222. }
  223. /******************************************************************************/

  224. /*********************写一字节USB数据*******************************************/
  225. void write_a_usb_data(uint8 usb_data)      
  226. {
  227. USB_A0=USB_DATA_ADD;
  228. USB_DATA=usb_data;
  229. USB_WR=0;
  230. USB_WR=1;
  231. USB_DATA=0XFF;
  232. }
  233. /******************************************************************************/

  234. /****************************读一字节USB数据************************************/
  235. uint8 read_a_usb_data(void)
  236. {
  237. uint8 temp;
  238. USB_A0=USB_DATA_ADD;
  239. USB_RD=0;
  240. temp=USB_DATA;
  241. USB_RD=1;
  242. return temp;
  243. }
  244. /******************************************************************************/

  245. /************************读USB中断寄存器**************************************/
  246. void read_interrupt_register(void)
  247. {
  248. write_usb_command(Read_Interrupt_Register);
  249. Interrupt_Register.Register[0]=read_a_usb_data();
  250. Interrupt_Register.Register[1]=read_a_usb_data();
  251. }
  252. /******************************************************************************/

  253. /************************设置USB地址*******************************************/
  254. void set_usb_addr(uint8 addr)
  255. {
  256. write_usb_command(Set_Address);
  257. write_a_usb_data(0x80|addr);
  258. Prints("   设置地址.\r\n");
  259. Prints("       地址为:  ");
  260. PrintLongInt(addr);
  261. Prints("\r\n");
  262. }
  263. /******************************************************************************/

  264. /*************************端点使能******************************************/
  265. void set_endpoint_enable(void)
  266. {
  267. write_usb_command(Set_Endpoint_Enable);
  268. write_a_usb_data(0x01);
  269. }
  270. /******************************************************************************/

  271. /****************************选择终端点*************************************/
  272. uint8 select_endpoint(uint8 endp)
  273. {
  274. write_usb_command(Select_EndPoint+endp);
  275. return read_a_usb_data();
  276. }
  277. /******************************************************************************/

  278. /****************************读端点最后状态**********************************/
  279. uint8  read_last_status(uint8 endp)
  280. {
  281. write_usb_command(Read_Last_Status+endp);
  282. return read_a_usb_data();
  283. }
  284. /******************************************************************************/

  285. /****************************设置端点状态**************************************/
  286. void set_endpoint_status(uint8 endp,uint8 status)  
  287. {
  288. write_usb_command(0x40+endp);
  289. write_a_usb_data(!status);
  290. }
  291. /******************************************************************************/

  292. /*****************************读端点状态**************************************/
  293. uint8 read_endpoint_status(uint8 endp)
  294. {
  295. write_usb_command(0x80+endp);
  296. return read_a_usb_data();
  297. }
  298. /******************************************************************************/

  299. /************************清缓冲,在读取缓冲数据后调用**************************/
  300. void clear_buffer(void)
  301. {
  302. write_usb_command(Clear_Buffer);
  303. #ifdef debug
  304. Prints("Clear buffer.\r\n");
  305. #endif
  306. }
  307. /******************************************************************************/

  308. /***********************缓冲区数据有效,在写缓冲后调用**************************/
  309. void validate_buffer(void)
  310. {
  311. write_usb_command(Validate_Buffer);
  312. #ifdef debug
  313. Prints("Validate buffer.\r\n");
  314. #endif
  315. }
  316. /******************************************************************************/

  317. /***************************应答建立包************************************/
  318. void ack_setup(uint8 endp)
  319. {
  320. select_endpoint(endp);
  321. write_usb_command(Ack_Setup);
  322. #ifdef debug
  323. Prints("Ack setup ");
  324. PrintLongInt(endp);
  325. Prints(".\r\n");
  326. #endif
  327. }
  328. /******************************************************************************/

  329. /***********************出错处理******************************************/
  330. void error(uint8 number)
  331. {
  332. Prints("有错误发生!!!\r\n");
  333. number=0;
  334. }
  335. /******************************************************************************/

  336. /*************************读终端点缓冲****************************************/
  337. uint8 read_endpoint_buff(uint8 endp,uint8 len,uint8 * buff)
  338. {
  339. uint8 i,j;
  340. read_last_status(endp);
  341. if(!(select_endpoint(endp)&0x01)){error(0); return 0;}
  342. if((read_endpoint_status(endp)&0x60)!=0x60)  //两个缓冲没有都满,才能清中断
  343. {
  344.   read_last_status(endp);  //清中断
  345. }
  346. write_usb_command(Read_Buffer);
  347. read_a_usb_data();
  348. j=read_a_usb_data();
  349. if(j>len)
  350.   j=len;  
  351. #ifdef debug
  352. Prints("Read endpoint");
  353. PrintLongInt(endp);
  354. Prints("\'s buffer ");
  355. PrintLongInt(j);
  356. Prints(" bytes.\r\n");
  357. #endif  
  358. for(i=0;i<j;i++)
  359.   {
  360.    USB_RD=0;
  361.    *(buff+i)=USB_DATA;
  362.    USB_RD=1;
  363. #ifdef debug
  364.    PrintHex(*(buff+i));
  365. #endif
  366.   }
  367. #ifdef debug
  368. Prints("\r\n");
  369. #endif
  370. clear_buffer();
  371. return j;
  372. }
  373. /******************************************************************************/

  374. /*************************写终端点缓冲*****************************************/
  375. uint8 write_endpoint_buff(uint8 endp,uint8 len,uint8 * buff)
  376. {
  377. uint8 i;
  378. read_last_status(endp);
  379. select_endpoint(endp);
  380. write_usb_command(Write_Buffer);
  381. write_a_usb_data(0);
  382. write_a_usb_data(len);
  383. #ifdef debug
  384. Prints("Write endpoint");
  385. PrintLongInt(endp);
  386. Prints("\'s buffer ");
  387. PrintLongInt(len);
  388. Prints(" bytes.\r\n");
  389. #endif
  390. for(i=0;i<len;i++)
  391.   {
  392.    USB_DATA=*(buff+i);
  393.    USB_WR=0;
  394.    USB_WR=1;
  395. #ifdef debug
  396.    PrintHex(*(buff+i));
  397. #endif
  398.   }
  399. #ifdef debug
  400. Prints("\r\n");
  401. #endif  
  402. USB_DATA=0xFF;
  403. validate_buffer();
  404. return len;
  405. }
  406. /******************************************************************************/

  407. /***************************断开USB连接****************************************/
  408. void disconnect_usb(void)
  409. {
  410. Prints("断开USB连接.\r\n");
  411. write_usb_command(0xf3);
  412. write_a_usb_data(0x0e);
  413. write_a_usb_data(0x47);
  414. delay(100);
  415. }
  416. /******************************************************************************/

  417. /*******************************连接USB**************************************/
  418. void connect_usb(void)
  419. {
  420. Prints("连接USB.\r\n");
  421. write_usb_command(0xf3);                         //初始化USBD12
  422. write_a_usb_data(0x1e);                          //连接USB
  423. write_a_usb_data(0x47);                          //设置频率
  424. }
  425. /******************************************************************************/

  426. /***************************初始化USB***************************************************/
  427. void init_usb(void)               
  428. {
  429. Prints("USBD12芯片初始化\r\n");
  430. set_usb_addr(0);
  431. set_endpoint_enable();
  432. }
  433.                         
  434. ……………………

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



分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏1 分享淘帖 顶 踩
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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