stm32 usb设备开发
1. 双摇杆 报告描述
// C:\Users\30619\Desktop\MCU DOWNLOAD\test\joysticks_2p.h
// 双摇杆 无按键 报告描述符
char ReportDescriptor[27] = {
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x04, // USAGE (Joystick)
0xa1, 0x01, // COLLECTION (Application)
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x30, // USAGE (X)
0x09, 0x31, // USAGE (Y)
0x09, 0x32, // USAGE (Z)
0x09, 0x33, // USAGE (Rx)
0x15, 0x81, // LOGICAL_MINIMUM (-127)
0x25, 0x7f, // LOGICAL_MAXIMUM (127)
0x75, 0x08, // REPORT_SIZE (8)
0x95, 0x04, // REPORT_COUNT (4)
0x81, 0x02, // INPUT (Data,Var,Abs)
0xc0 // END_COLLECTION
};
说明
// 两者配合使用
REPORT_SIZE (1) // 表示每个项目长度,bit按位计算
REPORT_COUNT (4) // 表示 有多少项目数
INPUT (cnst,Var,Abs) // data 表示可变,cnst固定不变;abs变成ver鼠标指针是相对值;摇杆用abs
2. tool自动生成的 joystick.hid
// C:\Users\30619\Desktop\MCU DOWNLOAD\usb_hid_report\project_PY\joystk.h
char ReportDescriptor[77] = {
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x09, 0x04, // USAGE (Joystick)
0xa1, 0x01, // COLLECTION (Application)
0x05, 0x02, // USAGE_PAGE (Simulation Controls)
//油门 1 byte
0x09, 0xbb, // USAGE (Throttle)
0x15, 0x81, // LOGICAL_MINIMUM (-127)
0x25, 0x7f, // LOGICAL_MAXIMUM (127)
0x75, 0x08, // REPORT_SIZE (8)
0x95, 0x01, // REPORT_COUNT (1)
0x81, 0x02, // INPUT (Data,Var,Abs)
//
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x01, // USAGE (Pointer)
0xa1, 0x00, // COLLECTION (Physical)
0x09, 0x30, // USAGE (X)
0x09, 0x31, // USAGE (Y)
0x95, 0x02, // REPORT_COUNT (2)
0x81, 0x02, // INPUT (Data,Var,Abs)
0xc0, // END_COLLECTION
0x09, 0x39, // USAGE (Hat switch)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x03, // LOGICAL_MAXIMUM (3)
0x35, 0x00, // PHYSICAL_MINIMUM (0)
0x46, 0x0e, 0x01, // PHYSICAL_MAXIMUM (270)
0x65, 0x14, // UNIT (Eng Rot:Angular Pos)
0x75, 0x04, // REPORT_SIZE (4)
0x95, 0x01, // REPORT_COUNT (1)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x05, 0x09, // USAGE_PAGE (Button)
0x19, 0x01, // USAGE_MINIMUM (Button 1)
0x29, 0x04, // USAGE_MAXIMUM (Button 4)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x75, 0x01, // REPORT_SIZE (1)
0x95, 0x04, // REPORT_COUNT (4)
0x55, 0x00, // UNIT_EXPONENT (0)
0x65, 0x00, // UNIT (None)
0x81, 0x02, // INPUT (Data,Var,Abs)
0xc0 // END_COLLECTION
};
生成手柄如下:
直接由工具生成的数据结构,关注byte3
2.1 添加脚舵rudder
// C:\Users\30619\Desktop\MCU DOWNLOAD\usb_hid_report\realse_hid_code\joystk1-bt2-thr1_head_rud.h
char ReportDescriptor[89] = {
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x09, 0x04, // USAGE (Joystick)
0xa1, 0x01, // COLLECTION (Application)
0x05, 0x02, // USAGE_PAGE (Simulation Controls)
0x09, 0xbb, // USAGE (Throttle)
0x15, 0x81, // LOGICAL_MINIMUM (-127)
0x25, 0x7f, // LOGICAL_MAXIMUM (127)
0x75, 0x08, // REPORT_SIZE (8)
0x95, 0x01, // REPORT_COUNT (1)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x09, 0xba, // USAGE (Rudder) 方向舵
0x15, 0x81, // LOGICAL_MINIMUM (-127)
0x25, 0x7f, // LOGICAL_MAXIMUM (127)
0x75, 0x08, // REPORT_SIZE (8)
0x95, 0x01, // REPORT_COUNT (1)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x01, // USAGE (Pointer)
0xa1, 0x00, // COLLECTION (Physical)
0x09, 0x30, // USAGE (X)
0x09, 0x31, // USAGE (Y)
0x95, 0x02, // REPORT_COUNT (2)
0x81, 0x02, // INPUT (Data,Var,Abs)
0xc0, // END_COLLECTION
0x09, 0x39, // USAGE (Hat switch)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x03, // LOGICAL_MAXIMUM (3)
0x35, 0x00, // PHYSICAL_MINIMUM (0)
0x46, 0x0e, 0x01, // PHYSICAL_MAXIMUM (270)
0x65, 0x14, // UNIT (Eng Rot:Angular Pos)
0x75, 0x04, // REPORT_SIZE (4)
0x95, 0x01, // REPORT_COUNT (1)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x05, 0x09, // USAGE_PAGE (Button)
0x19, 0x01, // USAGE_MINIMUM (Button 1)
0x29, 0x04, // USAGE_MAXIMUM (Button 4)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x75, 0x01, // REPORT_SIZE (1)
0x95, 0x04, // REPORT_COUNT (4)
0x55, 0x00, // UNIT_EXPONENT (0)
0x65, 0x00, // UNIT (None)
0x81, 0x02, // INPUT (Data,Var,Abs)
0xc0 // END_COLLECTION
};
1)数据结构体定义
// DATA STRUCT AND regulation
struct HID_JOYSTICK_DATA{
// range :-127 127
uint8_t throttle; // 油门
uint8_t rudder; // 脚舵
uint8_t x; //方向
uint8_t y;
// Hat switch and button
// range:hat:0-3 ,bit 4;button :0 1 bit 4
uint8_t HatBut;
};
2)数据处理 函数
#define LED_13_ON() HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_RESET);
#define LED_13_OFF() HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_SET
extern USBD_HandleTypeDef hUsbDeviceFS;
//ADC DATA
uint32_t adc_value[4] ;
// transimited usb data
int usb_value[4];
//function define 摇杆ADC数据0 - 4059转USB数据-127 - 127
void adc2usb(uint32_t *adc, int *usb, uint8_t num)
{
// num 转换的adc数量
for(int i=0;i<num;i++)
{
if(i==2)
{
// 方向修正
usb[i] = (int)(-127 + (float)adc[i]/4095*254);
}
else
{
usb[i] = (int)(127 - (float)adc[i]/4095*254);
}
// revise missing joystiks of central should be 0; no move speed
if(abs(usb[i])<5)
{
usb[i] = 0;
}
}
}
3) 初始化结构体
struct HID_JOYSTICK_DATA flightctl;
flightctl.throttle = 0;
flightctl.rudder = 0;
flightctl.x = 0;
flightctl.y = 0;
flightctl.HatBut = 0x00;
// ADC信号偏差修正函数
HAL_ADCEx_Calibration_Start(&hadc1);
4)while(1)循环体
//ADC 接收数据到adc_value[4]
for(int i=0;i<4;i++)
{
HAL_ADC_Start(&hadc1);
HAL_ADC_PollForConversion(&hadc1,100);
adc_value[i] = HAL_ADC_GetValue(&hadc1); // return 32bit
}
HAL_ADC_Stop(&hadc1);
adc2usb(adc_value, usb_value, 4);
// 赋值 通道 0 1 为油门y和脚舵x
flightctl.throttle = usb_value[0];
flightctl.rudder = usb_value[1];
flightctl.x = usb_value[3];
flightctl.y = usb_value[2];
flightctl.HatBut = 0x00;
// send data to usb
while(USBD_HID_SendReport(&hUsbDeviceFS, (uint8_t*)&flightctl, sizeof(struct HID_JOYSTICK_DATA)));
HAL_Delay(10);
2.2 删除头瞄
flightctl.x = usb_value[3];
flightctl.y = usb_value[2];
flightctl.HatBut = 0x00;
// send data to usb
while(USBD_HID_SendReport(&hUsbDeviceFS, (uint8_t*)&flightctl, sizeof(struct HID_JOYSTICK_DATA)));
HAL_Delay(10);