⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 usbkeyboard.c

📁 51+pdiusbd12做的usb键盘
💻 C
📖 第 1 页 / 共 3 页
字号:

#include <AT89x52.H>
#include "USB.H"
#include "PDIUSBD12.H"
#include "My_type.h"
#include "UART.H"
#include "key.h"
#include "keyboard.h"
#include <stdio.h>

#include <stdio.h>

#define USB_COMMAND_ADD           1
#define USB_DATA_ADD              0

//USB芯片连接引脚
#define USB_DATA                  P1
#define USB_A0                    P0_0
#define USB_WR                    WR
#define USB_RD                    RD
#define USB_INT                   INT0


#define ENDPOINT_NUMBER           2
#define MAX_CONTROL_DATA_SIZE     16       //重复定义啦  可以不要


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

//缓冲
uint8 idata buffer[64];

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

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

//高低字节交换

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

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

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

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

//设备序列号										
code uint8 device_serial_number[]=
{22,STRING_DESCRIPTOR,'2',0,'0',0,'0',0,'8',0,'-',0,'0',0,'5',0,'-',0,'2',0,'7',0};

//厂商字符串
code uint8 ManufacturerString[80]=
{80,STRING_DESCRIPTOR,0x61,0x53,0x11,0x81,0x08,0x57,0x08,0x57,0x84,0x76,0xB6,0x5B,
 0x53,0x5F,'-',0x00,'-',0x00,'-',0x00,'-',0x00,'@',0,0x20,0x00,'S',0,'H',0,'U',0,
 'S',0,'H',0,'I',0,'-',0,'-',0,'-',0,'-',0,'S',0,'H',0,'U',0,'S',0,'H',0,'I',0,
 '0',0,'5',0,'-',0,'2',0,'7',0,'-',0,'2',0,'0',0,'0',0,'8',0};

//产品字符串
code uint8 ProducterString[80]=
{80,STRING_DESCRIPTOR,0x61,0x53,0xC9,0x62,0x47,0x59,0x84,0x76,0xD1,0x8D,0xD1,0x8D, 
0x2E,0x95,0xD8,0x76,'@',0,0x20,0x00,'S',0,'H',0,'U',0,'S',0,'H',0,'I',0,'S',0,'H',0,
'U',0,'S',0,'H',0,'I',0,0x56,0x6E,0x57,0x53,0x06,0x74,0xE5,0x5D,0x66,0x5B, 0x62,0x96,
0x00,0x5F,  /*开*/
0x66,0x8F,  /*车*/
0x9E,0x64,  /*撞*/
0x7B,0x6B,  /*死*/
0x54,0x8D,  /*赔*/
0xB1,0x94,  /*钱*/
0x01,0xFF,  /*!*/
};


code DEVICE_DESCRIPTOR_STRUCT device_descriptor=     //设备描述符
{
 sizeof(DEVICE_DESCRIPTOR_STRUCT),                   //设备描述符的字节数大小
 DEVICE_DESCRIPTOR,	                                 //设备描述符类型编号
 0x1001,                                             //USB版本号
 0x00,                                               //USB分配的设备类代码
 0x00,                                               //USB分配的子类代码
 0x00,                                               //USB分配的设备协议代码
 0x10,                                               //端点0的最大包大小
 0x3412,                                             //厂商编号VID
 0x7856,                                             //产品编号PID
 0x0100,                                             //设备出厂编号
 0x01,                                               //设备厂商字符串的索引
 0x02,                                               //描述产品字符串的索引
 0x03,                                               //描述设备序列号字符串的索引
 0x01                                                //可能的配置数量
};

//定义配置,接口,端点等描述符结构体,因为它们是随配置描述符一起返回的
typedef struct _CON_INT_ENDP_DESCRIPTOR_STRUCT
{
 CONFIGURATION_DESCRIPTOR_STRUCT configuration_descriptor;   // 09
 INTERFACE_DESCRIPTOR_STRUCT  interface_descriptor;          //09
 HID_DESCRIPTOR_STRUCT hid_descriptor;     
 ENDPOINT_DESCRIPTOR_STRUCT  endpoint_descriptor[ENDPOINT_NUMBER];//两个07
}CON_INT_ENDP_DESCRIPTOR_STRUCT;

code CON_INT_ENDP_DESCRIPTOR_STRUCT con_int_endp_descriptor=
{
//configuration_descriptor                                          //配置描述符
{
 sizeof(CONFIGURATION_DESCRIPTOR_STRUCT),                           //配置描述符的字节数大小
 CONFIGURATION_DESCRIPTOR,                                          //配置描述符类型编号
 SWAP16(sizeof(CON_INT_ENDP_DESCRIPTOR_STRUCT)),
 0x01,                                                            //只包含一个接口
 0x01,                                                            //该配置的编号
 0x00,                                                            //iConfiguration字段
 0xA0,                                                            //采用总线供电,支持远程唤醒
 0xC8                                                            //从总线获取最大电流400mA
},
//interface_descritor                                             //接口描述符
{
 sizeof(INTERFACE_DESCRIPTOR_STRUCT),                             //接口描述符的字节数大小
 INTERFACE_DESCRIPTOR,                                            //接口描述符类型编号
 0x00,                                                            //接口编号为0
 0x00,                                                            //该接口描述符的编号
 ENDPOINT_NUMBER,                                                 //非0端点数量为2,只使用端点主端点输入和输出
 0x03,                                                            //人机接口设备(HID)类
 0x01,                                                            //使用的子类:支持BIOS根启动Boot的子类
 0x01,                                                            //使用的协议:键盘
 0x00                                                             //接口描述符字符串索引
},
//hid_descriptor
{
 sizeof(HID_DESCRIPTOR_STRUCT),                                   //HID描述符的字节数大小
 HID_DESCRIPTOR,                                                  //HID描述符类型编号
 0x1001,                                                          //HID类协议版本号,为1.1
 0x21,                                                            //固件的国家地区代号,0x21为美国
 NUM_SUB_DESCRIPTORS,                                             //下级描述符的数量
 {
  {
   REPORT_DESCRIPTOR,                                             //下级描述符为报告描述符
   SWAP16(sizeof(KeyBoardReportDescriptor))                       //下级描述符的长度
  }
 },
},
//endpoint_descriptor[]
{
 {                                                                //主端点输入描述
  sizeof(ENDPOINT_DESCRIPTOR_STRUCT),                             //端点描述符的字节数大小
  ENDPOINT_DESCRIPTOR,                                            //端点描述符类型编号
  MAIN_POINT_IN,                                                  //端点号,主输入端点
  ENDPOINT_TYPE_INTERRUPT,                                        //使用的传输类型:中断传输
  0x4000,                                                         //该端点支持的最大包尺寸,64字节
  0x0A                                                            //中断扫描时间:设置为10ms
 },
  
 {                                                                //主端点输出描述
  sizeof(ENDPOINT_DESCRIPTOR_STRUCT),                             //端点描述符的字节数大小
  ENDPOINT_DESCRIPTOR,                                            //端点描述符类型编号
  MAIN_POINT_OUT,                                                 //端点号,主输出端点
  ENDPOINT_TYPE_INTERRUPT,                                        //使用的传输类型:中断传输
  0x4000,                                                         //该端点支持的最大包尺寸,64字节
  0x0A                                                            //中断扫描时间:设置为10ms
 }
}
};

union                                          //程序标志位
{
uint16 Register;
struct 
{
 uint8 bus_reset        :1;
 uint8 suspend          :1;
 uint8 remote_wakeup    :1;
 uint8 int_isr          :1;
 uint8 not_end          :1;
 uint8 usb_idle         :1;
 uint8 usb_busy         :1;
 uint8 setup_packet_in  :1;            //如果为1,表示要发送数据到主机
 uint8 setup_packet_out :1;             //如果为1,表示主机要发送数据到设备
 uint8 set_addr         :1;
 uint8 usb_endp0_in     :1;            //这个IN是对端点而言的即控制输出,主机向端点发送数据
 uint8 usb_endp2_in     :1;            //
 uint8 usb_endp2_out    :1;
}flags;
}usb_flags;

union                                           //中断寄存器
{
 uint8 Register[2];
 struct 
  {
   uint8 control_out_port  :1;
   uint8 control_in_port   :1;
   uint8 port_out_1        :1;
   uint8 port_in_1         :1;
   uint8 main_out_port     :1;
   uint8 main_in_port      :1;
   uint8 bus_reset         :1;
   uint8 suspend_change    :1;
   uint8 DMA_EOT           :1;
   uint8 not_use           :7;
  }Interrupt;
}Interrupt_Register;


union                                    //端点最后处理状态
{
 uint8 Register;
 struct
 {
  uint8 successful          :1;
  uint8 error_code          :4;
  uint8 setup_packet        :1;
  uint8 data_1              :1;
  uint8 prestatus_not_read  :1;
 }Status;
}Last_Status;


/*****************   延时x毫秒函数 ***********/
void delay(uint16 x)                
{
 uint16 i;
 uint16 j;
 for(i=0;i<x;i++)
 for(j=0;j<230;j++);
}
/********************************************/

/*******************************写USB命令******************************************/
void write_usb_command(uint8 usb_command)
{
 USB_A0=USB_COMMAND_ADD;
 USB_DATA=usb_command;
 USB_WR=0;
 USB_WR=1;
 USB_DATA=0xFF;
}
/******************************************************************************/

/*********************写一字节USB数据*******************************************/
void write_a_usb_data(uint8 usb_data)       
{
 USB_A0=USB_DATA_ADD;
 USB_DATA=usb_data;
 USB_WR=0;
 USB_WR=1;
 USB_DATA=0XFF;
}
/******************************************************************************/

/****************************读一字节USB数据************************************/
uint8 read_a_usb_data(void)
{
 uint8 temp;
 USB_A0=USB_DATA_ADD;
 USB_RD=0;
 temp=USB_DATA;
 USB_RD=1;
 return temp;
}
/******************************************************************************/

/************************读USB中断寄存器**************************************/
void read_interrupt_register(void)
{
 write_usb_command(Read_Interrupt_Register);
 Interrupt_Register.Register[0]=read_a_usb_data();
 Interrupt_Register.Register[1]=read_a_usb_data();
}
/******************************************************************************/

/************************设置USB地址*******************************************/
void set_usb_addr(uint8 addr)
{

 write_usb_command(Set_Address);//Set_Address数值为0xd0
 write_a_usb_data(0x80|addr);//设置地址为0,并且使能地址
 Prints("   设置地址.....................",1);
 Prints("       地址为:  ",0);
 PrintLongInt(addr);
 Prints("",1);
}
/******************************************************************************/

/*************************端点使能******************************************/
void set_endpoint_enable(void)
{
 write_usb_command(Set_Endpoint_Enable);//此命了必须在设置地址使能命令后才能使用
 write_a_usb_data(0x01);//将端点使能
}
/******************************************************************************/

/****************************选择终端点*************************************/
uint8 select_endpoint(uint8 endp)
{
 write_usb_command(Select_EndPoint+endp);
 return read_a_usb_data();
}
/******************************************************************************/

/****************************读端点最后状态寄存器**********************************/
uint8  read_last_status(uint8 endp)
{
 write_usb_command(Read_Last_Status+endp);
 return read_a_usb_data();
}
/******************************************************************************/

/****************************设置端点状态**************************************/
void set_endpoint_status(uint8 endp,uint8 status)  
{
 write_usb_command(0x40+endp);
 write_a_usb_data(!status);
}
/******************************************************************************/

/*****************************读端点状态**************************************/
uint8 read_endpoint_status(uint8 endp)
{
 write_usb_command(0x80+endp);
 return read_a_usb_data();
}
/******************************************************************************/

/************************清缓冲,在读取缓冲数据后调用**************************/
void clear_buffer(void)
{
 write_usb_command(Clear_Buffer);
}
/******************************************************************************/

/***********************缓冲区数据有效,在写缓冲后调用**************************/
void validate_buffer(void)
{
 write_usb_command(Validate_Buffer);
}
/******************************************************************************/

/***************************应答建立包************************************/
void ack_setup(uint8 endp)
{
 select_endpoint(endp);
 write_usb_command(Ack_Setup);
}
/******************************************************************************/

/***********************出错处理******************************************/
void error(uint8 number)
{
 Prints("有错误发生!!!",1);
 number=0;
}
/******************************************************************************/

/*************************读终端点缓冲****************************************/
uint8 read_endpoint_buff(uint8 endp,uint8 len,uint8 * buff)
{
 uint8 i,j;
 read_last_status(endp);                            //具体作用就是清PD12的中断寄存器
 if(!(select_endpoint(endp))&0x01){error(0); return 0;}//初始化端点缓冲区数据指针到缓冲区的开始
 read_endpoint_status(endp);        
 write_usb_command(Read_Buffer);
 read_a_usb_data();                            //第一个字节为任意数
 j=read_a_usb_data();                          //第二个字节是数据长度位 
 if(j>len)
  j=len;
 for(i=0;i<j;i++)
  {
   USB_RD=0;
   *(buff+i)=USB_DATA;
   USB_RD=1;
 //Prints("读取的数据为  ",0);
 //PrintLongInt(*(buff+i));
  }
 clear_buffer();
 return j;                                     //不仅把数据读到了MCU的缓冲区中,还返回了数据长度值
}
/******************************************************************************/

/*************************写终端点缓冲*****************************************/
uint8 write_endpoint_buff(uint8 endp,uint8 len,uint8 * buff)
{
 uint8 i;
 read_last_status(endp);                               //清PD12的中断寄存器
 select_endpoint(endp);                         //初始化端点缓冲区数据指针到缓冲区的开始
 write_usb_command(Write_Buffer);
 write_a_usb_data(0);    //在读从主机发送到PD12的数据的时候第一个字节是任意的
 write_a_usb_data(len);  //第二个字节是数据长度位,发送的时候也要按照这个规则发送数据
 for(i=0;i<len;i++)
  {
   USB_DATA=*(buff+i);       
   USB_WR=0;                 
   USB_WR=1;
	//Prints("数据",1);
 //PrintLongInt(*(buff+i));
  }
 USB_DATA=0XFF;
 validate_buffer();
 return len;
}
/******************************************************************************/

/***************************断开USB连接****************************************/
void disconnect_usb(void)
{
 Prints("断开USB连接........................",1);
 write_usb_command(0xf3);//设置命令,设置上拉电阻和分频系数
 write_a_usb_data(0x0e);
 write_a_usb_data(0x47);
 delay(100);
}
/******************************************************************************/

/*******************************连接USB**************************************/
void connect_usb(void)
{
 Prints("连接USB...............",1);
 write_usb_command(0xf3);                         //初始化USBD12
 write_a_usb_data(0x1e);                          //连接USB
 write_a_usb_data(0x47);                          //设置频率
}
/******************************************************************************/

/***************************初始化USB***************************************************/
void init_usb(void)               
{

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -