STM32_USB
概述本文是使用HAL库的USB驱动
由于官方cubeMX天生的hal库做组合装备时过于繁琐
以是这里使用某大神的插件,可以集成在cubeMX里自动天生组合装备
有小bug会覆盖天生文件里自己写的内容,以是天生一次后注意生存
插件安装
下载地址 https://github.com/alambe94/I-CUBE-USBD-Composite/releases/tag/V01.00.03
下载pack文件
打开cubeMX
https://i-blog.csdnimg.cn/img_convert/d7f339d55afd3b4e5e0ef9f2563eea6c.jpeg
点击这个 之后选择下载的文件 安装
https://i-blog.csdnimg.cn/img_convert/0d93ae6cf34ee6cd823402ddad7ca71b.jpeg
出现这个即为安装成功
https://i-blog.csdnimg.cn/img_convert/0ee44280a865df4f53a1b6c66cd1cdab.jpeg
天生代码
打开USB 设为装备模式,打开中断
https://i-blog.csdnimg.cn/img_convert/cbd438a696d59db415c25a0ac8b023f6.jpeg
注意设置时钟树
USB需要较为精确的时钟 建议用外部晶振
https://i-blog.csdnimg.cn/img_convert/2a2b19f5af950dd248dfb1b9a59ea51b.jpeg
选择库文件
https://i-blog.csdnimg.cn/img_convert/63ead0c255a44e7da154c28a367edcfb.jpeg
现在打勾的这俩必选
别的根据需要选择
https://i-blog.csdnimg.cn/img_convert/43a65ef9829dfa15c5ca61f4c642f395.jpeg
根据需要选择,注意要在上步开启的库文件中选
https://i-blog.csdnimg.cn/img_convert/afc4573d3aa9192467d806049f609e06.jpeg
在初始化后参加这个函数
MX_USB_DEVICE_Init();
https://i-blog.csdnimg.cn/img_convert/772f114c6f2206346f7a1c44aeb6f4f6.jpeg
可以去usbd_desc.c里设置VID/PID 某些名称等参数,差别装备有些许差别
https://i-blog.csdnimg.cn/img_convert/3cf8be69cd3923d047dc9d5b55ca1229.jpeg
虚拟串口(CDC)
概述
串口名是由PC的驱动来决定的,没法在STM32端设置
设置
打开这个
可以在这里设置虚拟的串口数目
注意一个串口要占用2个IN端点和一个OUT端点
https://i-blog.csdnimg.cn/img_convert/4e2928569554068195cbd8895993dde2.jpeg
也可以设置AL94.I-CUBE-USBD-COMPOSITE_conf.h文件中的_USBD_CDC_ACM_COUNT设置虚拟的CDC串口数目
发送
开始发送
类型名称功能uint8_tch通道uint8_t *Buf缓冲区地址uint16_tLen发送数目uint8_t输出已经发送的数目 uint8_t CDC_Transmit(uint8_t ch, uint8_t *Buf, uint16_t Len)
发送完成
类型名称功能uint8_tcdc_ch通道uint8_t *Buf缓冲区地址uint32_tLen发送数目uint8_tepnum端点号uint8_t错误码 int8_t CDC_TransmitCplt(uint8_t cdc_ch, uint8_t *Buf, uint32_t *Len, uint8_t epnum)
接收
类型名称功能uint8_tcdc_ch通道uint8_t *Buf缓冲区地址uint32_tLen发送数目int8_t错误码 接收到数据会自动调用这函数
int8_t CDC_Receive(uint8_t cdc_ch, uint8_t *Buf, uint32_t *Len)
在这个函数里调用这俩句,来接收下个数据包
USBD_CDC_SetRxBuffer(cdc_ch, &hUsbDevice, &Buf);
USBD_CDC_ReceivePacket(cdc_ch, &hUsbDevice);
控制函数
类型名称功能uint8_tcdc_ch通道uint8_tcmd命令类型uint8_t *pbuf命令缓冲区uint16_tlength长度int8_t错误码 int8_t CDC_Control(uint8_t cdc_ch, uint8_t cmd, uint8_t *pbuf, uint16_t length)
在cmd为CDC_SET_LINE_CODING时收到来自主机的命令
具体内容天生的函数中有注释
人体工学装备(HID)
概述
全部使用自定义HID装备
根据差别装备设置描述符即可
HID间的复合直接复制就行
eg:鼠标+键盘 直接把鼠标的描述符和键盘的描述符写到一起即可
建立工程
https://i-blog.csdnimg.cn/img_convert/03b7cab0a7276aaed6e51aba66d9ee5b.jpeg
https://i-blog.csdnimg.cn/img_convert/37f770fc04dafbc061c574ac32d4eaed.jpeg
设置
在 usbd_customhid.h中
名称功能CUSTOM_HID_STR_DESCHID描述CUSTOM_HID_EPIN_SIZE输入缓冲大小(一般设为64)CUSTOM_HID_EPOUT_SIZE输出缓冲大小(一般设为64)USBD_CUSTOMHID_OUTREPORT_BUF_SIZEHID缓冲区(一般设为64)CUSTOM_HID_FS_BINTERVAL包间隔时间 在usbd_custom_hid_if.c中
CUSTOM_HID_ReportDesc 设置HID描述符 USBD_CUSTOM_HID_REPORT_DESC_SIZE 同时也要设置配置符大小
https://i-blog.csdnimg.cn/img_convert/8c38b34f2dab389766fc8b294b491c70.jpeg
APIs
发送数据
类型名称功能USBD_HandleTypeDef *pdevUSB句柄uint8_t *report缓冲区uint16_tlen数据长度uint8_t错误码 uint8_t USBD_CUSTOM_HID_SendReport(USBD_HandleTypeDef *pdev,uint8_t *report, uint16_t len);
接收数据回调
usbd_custom_hid_if.c
类型名称功能uint8_tevent_idxuint8_tstateuint8_t错误码 int8_t CUSTOM_HID_OutEvent(uint8_t event_idx, uint8_t state)
在内部调用以获取数据
USBD_CUSTOM_HID_HandleTypeDef *hhid = (USBD_CUSTOM_HID_HandleTypeDef *)HZ_DAP_USB_Handle.pClassData_HID_Custom;
// hhid->Report_buf;
USBD_CUSTOM_HID_ReceivePacket(&HZ_DAP_USB_Handle);
鼠标
鼠标的配置描述符
0x05, 0x01,
0x09, 0x02,
0xa1, 0x01,
0x85, 0x02, // 报告ID (2)
0x09, 0x01,
0xa1, 0x00,
0x05, 0x09,
0x19, 0x01,
0x29, 0x03,
0x15, 0x00,
0x25, 0x01,
0x95, 0x03,
0x75, 0x01,
0x81, 0x02,
0x95, 0x01,
0x75, 0x05,
0x81, 0x03,
0x95, 0x03,
0x75, 0x08,
0x05, 0x01,
0x09, 0x30,
0x09, 0x31,
0x09, 0x38,
0x15, 0x81,
0x25, 0x7f,
0x81, 0x06,
0xc0,
0xc0
需要发送的命令 寄义
位置功能Bit0陈诉IDBit1左键(0未按1按下)Bit1右键(0未按1按下)Bit1中键(0未按1按下)Bit2x轴(正右负左 -127~127)Bit3y轴(正下负上 -127~127)Bit4滚动(正上负下 -127~127) 这个函数是自己封装的
extern USBD_HandleTypeDef hUsbDevice;
/**
* @brief 控制鼠标
* @param key_l 左键(仅bit0 0未按1按下)
* @param key_r 右键(仅bit0 0未按1按下)
* @param key_m 中键(仅bit0 0未按1按下)
* @param x x轴(正右负左 -127~127)
* @param y y轴(正下负上 -127~127)
* @param ec 滚动(正上负下 -127~127)
* @author HZ12138
* @date 2025-03-28 20:17:39
*/
void HZ_Mouse_set(uint8_t key_l, uint8_t key_r, uint8_t key_m, int8_t x, int8_t y, int8_t ec)
{
uint8_t buf;
key_l &= 0x01;
key_r &= 0x01;
key_m &= 0x01;
buf = 0x02; // 报告ID 鼠标是0x02
buf = (key_m << 2) | (key_r << 1) | (key_l << 0);
buf = (uint8_t)x;
buf = (uint8_t)y;
buf = (uint8_t)ec;
USBD_CUSTOM_HID_SendReport(&hUsbDevice, buf, 5);
}
键盘
描述符
0x85后面跟的是陈诉ID 0保留
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x06, // USAGE (Keyboard)
0xa1, 0x01, // COLLECTION (Application)
0x85, 0x01, // 报告ID (1)
0x05, 0x07, // USAGE_PAGE (Keyboard)
0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl)
0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x75, 0x01, // REPORT_SIZE (1)
0x95, 0x08, // REPORT_COUNT (8)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x08, // REPORT_SIZE (8)
0x81, 0x03, // INPUT (Cnst,Var,Abs)
0x95, 0x05, // REPORT_COUNT (5)
0x75, 0x01, // REPORT_SIZE (1)
0x05, 0x08, // USAGE_PAGE (LEDs)
0x19, 0x01, // USAGE_MINIMUM (Num Lock)
0x29, 0x05, // USAGE_MAXIMUM (Kana)
0x91, 0x02, // OUTPUT (Data,Var,Abs)
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x03, // REPORT_SIZE (3)
0x91, 0x03, // OUTPUT (Cnst,Var,Abs)
0x95, 0x06, // REPORT_COUNT (6)
0x75, 0x08, // REPORT_SIZE (8)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x65, // LOGICAL_MAXIMUM (101)
0x05, 0x07, // USAGE_PAGE (Keyboard)
0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated))
0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application)
0x81, 0x00, // INPUT (Data,Ary,Abs)
0xc0 // END_COLLECTION
数据内容
Bit2~8 发送的是按下的键号 如果不按下写0即可
位置功能Bit0陈诉IDBit1左CTRL(0未按1按下)Bit1左SHIFT(0未按1按下)Bit1左ALT(0未按1按下)Bit1左GUI(0未按1按下)Bit1右CTRL(0未按1按下)Bit1右SHIFT(0未按1按下)Bit1右ALT(0未按1按下)Bit1右GUI(0未按1按下)Bit2保留(0x00)Bit3按键1Bit4按键2Bit5按键3Bit6按键4Bit7按键5Bit8按键6 封装的发送按键函数和单个按键按下函数
extern USBD_HandleTypeDef hUsbDevice;
/**
* @brief 发送按键
* @param keys 按键
* @param key_num 数量最大6个
* @param ctrl_l 如名(0未按1按下)
* @param shift_l 如名(0未按1按下)
* @param alt_l 如名(0未按1按下)
* @param gui_l 如名(0未按1按下)
* @param ctrl_r 如名(0未按1按下)
* @param shift_r 如名(0未按1按下)
* @param alt_r 如名(0未按1按下)
* @param gui_r 如名(0未按1按下)
* @author HZ12138
* @date 2025-03-28 22:52:09
*/
void HZ_KeyBoard_set(uint8_t *keys, uint8_t key_num,
uint8_t ctrl_l, uint8_t shift_l, uint8_t alt_l, uint8_t gui_l,
uint8_t ctrl_r, uint8_t shift_r, uint8_t alt_r, uint8_t gui_r)
{
uint8_t buf;
ctrl_l &= 0x01;
shift_l &= 0x01;
alt_l &= 0x01;
gui_l &= 0x01;
ctrl_r &= 0x01;
shift_r &= 0x01;
alt_r &= 0x01;
gui_r &= 0x01;
buf = 0x01;
buf = (gui_r << 7) | (alt_r << 6) | (shift_r << 5) | (ctrl_r << 4) |
(gui_l << 3) | (alt_l << 2) | (shift_l << 1) | (ctrl_l << 0);
buf = 0x00;
for (int i = 0; i < key_num; i++)
buf = keys;
USBD_CUSTOM_HID_SendReport(&hUsbDevice, buf, 9);
}
/**
* @brief 发送单个按键
* @param key 按键值
* @author HZ12138
* @date 2025-03-28 22:52:12
*/
void HZ_KeyBoard_one_key(uint8_t key)
{
uint8_t temp;
temp = key;
HZ_KeyBoard_set(temp, 6, 0, 0, 0, 0, 0, 0, 0, 0);
}
键码对应表,使用HID码
按键名称HID码虚拟键码ESC41 27 F158 112 F259 113 F360 114 F461 115 F562 116 F663 117 F764 118 F865 119 F966 120 F1067 121 F1168 122 F1269 123 Esc41 27 Back (回退)42 8 Tab43 9 CapLck (大小写)57 20 Enter (回车)40 13 Space (空格)44 32 Scroll71 145 Pause(暂停)72 19 Insert (插入)73 45 PrintScr (截屏)70 44 Delete (删除)76 46 Home (首页)74 36 End (末端)77 35 PageUp (上一页)75 33 PageDn (下一页)78 34 Left (左)80 37 Up (上)82 38 Right (右)79 39 Down (下)81 40 Num0 (小键盘)98 96 Num1 (小键盘)89 97 Num2 (小键盘)90 98 Num3 (小键盘)91 99 Num4 (小键盘)92 100 Num5 (小键盘)93 101 Num6 (小键盘)94 102 Num7 (小键盘)95 103 Num8 (小键盘)96 104 Num9 (小键盘)97 105 NumAdd (加号)87 107 NumSub (减号)86 109 NumMult (乘号)85 106 NumDiv (除号)84 111 NumDecim (点)99 110 NumLock (数字锁定键)83 144 Ctrl1 17 LCtrl (左CTR)1 162 RCtrl16 163 Shift2 16 LShift2 160 RShift32 161 Alt4 18 LAlt4 164 RAlt64 165 WIN8 91 LWIN8 91 RWIN128 92 A4 65 B5 66 C6 67 D7 68 E8 69 F9 70 G10 71 H11 72 I12 73 J13 74 K14 75 L15 76 M16 77 N17 78 O18 79 P19 80 Q20 81 R21 82 S22 83 T23 84 U24 85 V25 86 W26 87 X27 88 Y28 89 Z29 90 039 48 130 49 231 50 332 51 433 52 534 53 635 54 736 55 837 56 938 57 大容量存储(MSC)
建立工程
https://i-blog.csdnimg.cn/img_convert/b5573a4d09952917a4e000f34c990906.jpeg
https://i-blog.csdnimg.cn/img_convert/b703905039d11430977b9675e0dc55b4.jpeg
设置
usbd_msc.h 中的 MSC_MEDIA_PACKET 要设为扇区(sector)大小
w25Qxx为4096 SD卡为512
STORAGE_LUN_NBR为虚拟磁盘卷数目 一般把一个装备设为一个卷 设置这个可以虚拟出多个磁盘
usbd_storage_if.c 的STORAGE_BLK_NBR 为最小操作单元数目(一般写扇区数目)
usbd_storage_if.c 的 STORAGE_BLK_SIZ 为最小操作单元大小 (一般写扇区大小) 单元(Byte)
这俩相乘即可得到总大小 单元(Byte)
注意这俩的blk所指的块与FLASH的差别,也是我写成最小操作单元的缘故原由
可以修改这个末了三项来更改表现名称
usbd_storage_if.c的STORAGE_Inquirydata
https://i-blog.csdnimg.cn/img_convert/18e27fa8467255747e231935a132657d.jpeg
APIs
存储读取(必写)
描述名称功能uint8_tlun卷标uint8_t *buf缓冲区uint32_tblk_addr最小操作单元起始地址(*STORAGE_BLK_SIZ后得到Byte起始地址 )uint16_tblk_len最小操作单元的数目(*STORAGE_BLK_SIZ后得到Byte数目 )int8_t输出错误码 在usbd_storage_if.c 中
需要根据自己内容填写
int8_t STORAGE_Read(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len)
存储写入(必写)
描述名称功能uint8_tlun卷标uint8_t *buf缓冲区uint32_tblk_addr最小操作单元起始地址(*STORAGE_BLK_SIZ后得到Byte起始地址 )uint16_tblk_len最小操作单元的数目(*STORAGE_BLK_SIZ后得到Byte数目 )int8_t输出错误码 在usbd_storage_if.c 中
需要根据自己内容填写
int8_t STORAGE_Write(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len)
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页:
[1]