第一范文网 - 专业文章范例文档资料分享平台

stm32 USB模块的HID设备开发

来源:用户分享 时间:2025/6/9 15:11:06 本文由loading 分享 下载这篇文档手机版
说明:文章内容仅供预览,部分内容可能不全,需要完整文档或者需要复制内容,请下载word后使用。下载word有问题请添加微信号:xxxxxxx或QQ:xxxxxx 处理(尽可能给您提供完整文档),感谢您的支持与谅解。

ENDP2_RXADDR,50),作用是接收上位机数据到Receive_Buffer[50]中,上位机发送数据时datasize必须为50,无用的位可以写为0发送。

1.3 USB库应用接口层 1.3.1 usb_istr(.c)

Usb_istr.c提供了一个函数USB_istr()处理所有的USB宏单元中断。

函数void (*pEpInt_IN[7])(void)引用了所有EP*_IN(1-7)的回调函数,函数void

(*pEpInt_OUT[7])(void)引用了所有EP*_out(1-7)的回调函数,如果需要调用相应的回调函数,则应该在usb_config.h中将对应的函数无效声明注释掉如//#define EP2_OUT_Callback NOP_Process,再添加函数的具体内容。

注:在工程中,HID双向通信定义使用端点1发送数据,端点2接收数据,其中端点2接收数据需要用回调函数接收,所以在usb_config.h中将//#define EP2_OUT_Callback NOP_Process注释掉,并且在usb_istr.c中添加了EP2_OUT_Callback的定义: void EP2_OUT_Callback(void) {

PMAToUserBufferCopy(Receive_Buffer, ENDP2_RXADDR,50); SetEPRxStatus(ENDP2, EP_RX_VALID); Usb_ReceivePro(); }

函数的第一句作用是将端点2接收的数据存入大小为50bytes的Receive_Buffer中。 第二句作用是使能端点2的数据接收,第三句是引用自己定义的函数,这个函数用来处理接收到的数据。

1.3.2 usb_conf(.h)

Usb_conf.h定义了BTABLE和PMA中的所有端点地址

注:EP_NUM指需要用到的端点数量。 以下这一段宏定义定义了端点发送或接收缓冲区的大小,

都定义为了64bytes

#define BTABLE_ADDRESS (0x00) //这个是基地址 /* EP0 */

/* rx/tx buffer base address */

#define ENDP0_RXADDR (0x18) #define ENDP0_TXADDR (0x58)

/* EP1 */

/* tx buffer base address */

#define ENDP1_TXADDR (0x100) #define ENDP2_RXADDR (0x140)

下面这一段是回调函数的无效宏定义,相当于一个mask,需要相应的回调函数,则注释掉那一句。

#define EP1_IN_Callback NOP_Process

#define EP2_IN_Callback NOP_Process #define EP3_IN_Callback NOP_Process #define EP4_IN_Callback NOP_Process #define EP5_IN_Callback NOP_Process #define EP6_IN_Callback NOP_Process #define EP7_IN_Callback NOP_Process

#define EP1_OUT_Callback NOP_Process //#define EP2_OUT_Callback NOP_Process #define EP3_OUT_Callback NOP_Process #define EP4_OUT_Callback NOP_Process #define EP5_OUT_Callback NOP_Process #define EP6_OUT_Callback NOP_Process #define EP7_OUT_Callback NOP_Process

1.3.3 usb_prop(.c,.h)

Usb_prop模块实现了USB内核使用的Device_Table,Device_Property和USER_STANDARD_REQUEST结构。

A) Device_Table使用结构体DEVICE定义:

DEVICE Device_Table = {

EP_NUM, 1 }

可以知道Device_Table 的EP_NUM就是需要的端点数,它的宏定义在usb_conf.h中。Device_Table中成员1则代表设备只有一个配置

B) Device_Property使用结构体DEVICE_PROP定义:

DEVICE_PROP Device_Property = {

Joystick_init, Joystick_Reset, Joystick_Status_In, Joystick_Status_Out, Joystick_Data_Setup, Joystick_NoData_Setup,

Joystick_Get_Interface_Setting, Joystick_GetDeviceDescriptor, Joystick_GetConfigDescriptor, Joystick_GetStringDescriptor, 0,

0x40 /*MAX PACKET SIZE*/ }

下面解释几个主要关心的回调函数:

1、Joystick_init作用为初始化设备。

2、Joystick_Reset主要作用是对需要的端点进行设置,在工程中使用了endp0,endp1_in,endp2_out,所以必须对这三个端点进行设置。如下:

/* Initialize Endpoint 0 */

SetEPType(ENDP0, EP_CONTROL); SetEPTxStatus(ENDP0, EP_TX_STALL); SetEPRxAddr(ENDP0, ENDP0_RXADDR); SetEPTxAddr(ENDP0, ENDP0_TXADDR); Clear_Status_Out(ENDP0);

SetEPRxCount(ENDP0, Device_Property.MaxPacketSize); SetEPRxValid(ENDP0);

/* Initialize Endpoint 1 */

SetEPType(ENDP1, EP_INTERRUPT); SetEPTxAddr(ENDP1, ENDP1_TXADDR); SetEPTxCount(ENDP1, 14);

SetEPTxStatus(ENDP1, EP_TX_NAK); /* Initialize Endpoint 12*/

SetEPType(ENDP2, EP_INTERRUPT); SetEPRxAddr(ENDP2, ENDP2_RXADDR); SetEPRxCount(ENDP2, 50);

SetEPRxStatus(ENDP2, EP_RX_VALID);

endp0为用作控制,不用自己设置。

endp1用作中断输入(方向为设备到主机)端点,在endp1初始化语句中, setEPType(ENDP1, EP_INTERRUPT)设置端点1为中断方式, SetEPTxAddr(ENDP1, ENDP1_TXADDR)设置其输入地址, SetEPTxCount(ENDP1, 14)设置配置Tx 缓冲计数器,

SetEPTxStatus(ENDP1, EP_TX_NAK) 设置端点1发送不应答。

endp2 用作中断输出(方向主机到设备)端点,在endp2初始化语句中

SetEPType(ENDP2, EP_INTERRUPT)设置端点2为中断方式 SetEPRxAddr(ENDP2, ENDP2_RXADDR);设置输出地址 SetEPRxCount(ENDP2, 50);配置RX缓冲计数器 SetEPRxStatus(ENDP2, EP_RX_VALID);设置输入有效

注:配置TX缓冲计数器时注意它的值等于设备发送数据的最大宽度。同理对RX一样。 3、 Joystick_Data_Setup处理主机获取设备的特定描述符的请求,内核文件usb_core无法处

理该请求,因此需要用户分析请求,准备好数据,再传送个内核,特定描述符请求包括获取HID描述符,报告描述符等。

注:函数体RESULT Joystick_Data_Setup(uint8_t RequestNo)

{

uint8_t *(*CopyRoutine)(uint16_t);

CopyRoutine = NULL;

if ((RequestNo == GET_DESCRIPTOR)

&& (Type_Recipient == (STANDARD_REQUEST | INTERFACE_RECIPIENT)) && (pInformation->USBwIndex0 == 0)) {

if (pInformation->USBwValue1 == REPORT_DESCRIPTOR) {

CopyRoutine = Joystick_GetReportDescriptor; }

else if (pInformation->USBwValue1 == HID_DESCRIPTOR_TYPE) {

CopyRoutine = Joystick_GetHIDDescriptor; }

} /* End of GET_DESCRIPTOR */

/*** GET_PROTOCOL ***/

else if ((Type_Recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT)) && RequestNo == GET_PROTOCOL) {

CopyRoutine = Joystick_GetProtocolValue; } if(ReportOffset>=6) ReportOffset=0; */

if (CopyRoutine == NULL) {

return USB_UNSUPPORT; }

pInformation->Ctrl_Info.CopyData = CopyRoutine; pInformation->Ctrl_Info.Usb_wOffset = 0; (*CopyRoutine)(0); return USB_SUCCESS;

}

函数中的判断语句说明

if ((RequestNo == GET_DESCRIPTOR) && (Type_Recipient == (STANDARD_REQUEST | INTERFACE_RECIPIENT)) && (pInformation->USBwIndex0 == 0)) 它的意思是判断主机发送的请求信息,如果是GET_DESCRIPTOR请求类型,并且是标准的USB请求,并且索引USBwIndex0为0,则执行后面的语句,在后面判断语句内部,再通过索引USBwIndex1确定是应该返回ReportDescriptor还是HIDDescriptor。

else if ((Type_Recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT)) && RequestNo == GET_PROTOCOL)

搜索更多关于: stm32 USB模块的HID设备开发 的文档
stm32 USB模块的HID设备开发.doc 将本文的Word文档下载到电脑,方便复制、编辑、收藏和打印
本文链接:https://www.diyifanwen.net/c9fubm1s16t5nd0f7mk4r_2.html(转载请注明文章来源)
热门推荐
Copyright © 2012-2023 第一范文网 版权所有 免责声明 | 联系我们
声明 :本网站尊重并保护知识产权,根据《信息网络传播权保护条例》,如果我们转载的作品侵犯了您的权利,请在一个月内通知我们,我们会及时删除。
客服QQ:xxxxxx 邮箱:xxxxxx@qq.com
渝ICP备2023013149号
Top