历史上的今天
返回首页

历史上的今天

今天是:2024年09月14日(星期六)

正在发生

2018年09月14日 | 移植STM32固件库用于HID双向通信

2018-09-14 来源:eefocus

USB的应用中HID类是比较常见的方式。通过修改STM32 USB固件库V4.0的JOYSTICK应用,我们实现一个双向USB通信。
一、移植
使用STM32源程序为点亮LED灯程序。
首先将USB固件库中有用的函数复制到源函数中,建立LIB文件夹其中放入USB2.0协议函数



建立CFG文件夹放入USB应用函数


将两个文件夹都放到源工程目录下将文件添加进来,设置好,配置好KEIL软件设置。

二、修改文件
1、首先修改platform_config.h函数。
    该文件是对于多种芯片对于USB库的支持。我们使用STM32F103ZET6芯片,所以只保留与之相关的ID项,与USB_DISCONNECT线(PG11)的配置。修改之后的头文件如下所示



2、然后修改hw_config.c中Set_System函数

    实际上STM32F103zet6不需要对USB端口进行单独的配置,删掉Set_System函数中没用的部分,只对USB_DISCONNECT线(PG11)进行初始化。修改后的函数如下图所示。


3、接下来修改hw_config.c文件中USB_Cable_Config函数因为我使用的是比较老的神舟III开发板,当PG11为高电平时实现上拉,所以修改后的函数为


4、修改USB_Interrupt_Config函数,配置USB_LP_CAN1_RX0_IRQn和USBWakeUp_IRQn中断修改后的函数如下图所示。


5、接下来删掉hw_config.c文件中GPIO_AINConfig函数,没有什么用,只会报错

6、删掉与按键相关的设置,因为我们并没有用到,主要是先清除JoyState和Joystick_Send函数中内容,不用管。

7、最后我们处理USB挂起相关的问题。在USB固件库中提供挂起相关的处理函数,主要有2个函数需要修改。它们是Suspend函数和Enter_LowPowerMode函数。其中,在Suspend函数中注释掉PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFI);语句。修改Suspend函数,如下图所示

OK接下来应该就没有什么需要修改的地方了(如果有的话请酌情修改)
三、描述符修改
使用USB HID类进行通信调试。所以要对USB的描述符要做部分修改(usb_desc.c)。下面我们贴程序说明(只对重要修改做说明)

设备描述符
修改idVendor和idProduct的值,为任意其他值,我里我用给的是0x0413和0x5724,修改的时候注意大小端

配置描述符集合

const uint8_t Joystick_ConfigDescriptor[JOYSTICK_SIZ_CONFIG_DESC] =

  {

    0x09, /* bLength: Configuration Descriptor size */

    USB_CONFIGURATION_DESCRIPTOR_TYPE, /* bDescriptorType: Configuration */

    JOYSTICK_SIZ_CONFIG_DESC,

    /* wTotalLength: Bytes returned */

    0x00,

    0x01,         /*bNumInterfaces: 1 interface*/

    0x01,         /*bConfigurationValue: Configuration value*/

    0x00,         /*iConfiguration: Index of string descriptor describing

                                     the configuration*/

    0xE0,         /*bmAttributes: Self powered */

    0x32,         /*MaxPower 100 mA: this current is used for detecting Vbus*/

 

    /************** Descriptor of Joystick Mouse interface ****************/

    /* 09 */

    0x09,         /*bLength: Interface Descriptor size*/

    USB_INTERFACE_DESCRIPTOR_TYPE,/*bDescriptorType: Interface descriptor type*/

    0x00,         /*bInterfaceNumber: Number of Interface*/

    0x00,         /*bAlternateSetting: Alternate setting*/

    0x02,         /*bNumEndpoints除端点0外,需要1输入1输出*/

    0x03,         /*bInterfaceClass: HID*/

    0x00,         /*bInterfaceSubClass : 1=BOOT, 0=no boot选择no boot*/

    0x00,         /*nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse选择none*/

    0,            /*iInterface: Index of string descriptor*/

    /******************** Descriptor of Joystick Mouse HID ********************/

    /* 18 */

    0x09,         /*bLength: HID Descriptor size*/

    HID_DESCRIPTOR_TYPE, /*bDescriptorType: HID*/

    0x00,         /*bcdHID: HID Class Spec release number*/

    0x01,

    0x00,         /*bCountryCode: Hardware target country*/

    0x01,         /*bNumDescriptors: Number of HID class descriptors to follow*/

    0x22,         /*bDescriptorType*/

    JOYSTICK_SIZ_REPORT_DESC,/*wItemLength: Total length of Report descriptor*/

    0x00,

    /******************** Descriptor of Joystick Mouse endpoint ********************/

    /* 27 */

    0x07,          /*bLength: Endpoint Descriptor size*/

    USB_ENDPOINT_DESCRIPTOR_TYPE, /*bDescriptorType:*/

 

    0x81,          /*bEndpointAddress: Endpoint Address (IN)*/

    0x03,          /*bmAttributes: Interrupt endpoint*/

    0x40,          /*wMaxPacketSize: 64 Byte max修改最大包大小为64字节 */

    0x00,

    0x0A,          /*bInterval: Polling Interval (10 ms)修改轮询间隔为10ms*/

/******************** Descriptor of Joystick Mouse endpoint ********************/

    /* 34 */

    0x07,          /*bLength: Endpoint Descriptor size*/

    USB_ENDPOINT_DESCRIPTOR_TYPE, /*bDescriptorType:*/

 

    0x01,          /*bEndpointAddress: Endpoint Address (OUT)*/

    0x03,          /*bmAttributes: Interrupt endpoint*/

    0x40,          /*wMaxPacketSize: 64 Byte max修改最大包大小为64字节 */

    0x00,

    0x20,          /*bInterval: Polling Interval (10 ms) 修改轮询间隔为10ms */

/*41 */

  } ;


报告描述符


const uint8_t Joystick_ReportDescriptor[JOYSTICK_SIZ_REPORT_DESC] =

  {

    0x05, 0xFF,          /*Usage Page(User Define)*/

    0x09, 0xFF,          /*Usage(User Define)*/

    0xA1, 0x01,          /*Collection(application)*/

    0x05, 0x01,          /*Usage Page(1)*/

    0x19, 0x00,          /*Usage Minimum(0)*/

    0x29, 0xFF,          /*Usage Maximum(255)*/

    0x15, 0x00,          /*Logical Minimum(0)*/

    0x25, 0xFF,          /*Logical Maximum(255)*/

    0x95, 0x40,          /*Report Count(3)*/

    0x75, 0x08,          /*Report Size(1)*/

0x81, 0x02,          /*Input(Data,Var,Abs)*/

0x05, 0x02          /*Usage Page(2)*/

0x19, 0x00,          /*Usage Minimum(0)*/

    0x29, 0xFF,          /*Usage Maximum(255)*/

    0x15, 0x00,          /*Logical Minimum(0)*/

    0x25, 0xFF,          /*Logical Maximum(255)*/

    0x95, 0x40,          /*Report Count(64)*/

    0x75, 0x08,          /*Report Size(8)*/

0x91, 0x02,          /*Input(Data,Var,Abs)*/

0xc0               /*关集合*/

  }; /* Joystick_ReportDescriptor */

上面我们修改了数组内容,导致数组大小发生变化,所以根据变化做响应修改,在usb_desc.c中


#define JOYSTICK_SIZ_CONFIG_DESC                41

#define JOYSTICK_SIZ_REPORT_DESC                39

四、修改函数


    修改设备RESET函数Joystick_Reset,这个函数是在RESET中断中被调用,用于端口的初始化。因为我们增加了端点1的输出,修改了包大小,所以要做响应的修改。这个函数位于usb_prop.c中,修改后的函数为


void Joystick_Reset(void)

{

  /* Set Joystick_DEVICE as not configured */

  pInformation->Current_Configuration = 0;

  pInformation->Current_Interface = 0;/*the default Interface*/

 

  /* Current Feature initialization */

  pInformation->Current_Feature = Joystick_ConfigDescriptor[7];

  SetBTABLE(BTABLE_ADDRESS);

  /* 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, 64);//修改大小为64

  SetEPTxStatus(ENDP1, EP_TX_NAK);

 

  /* Initialize Endpoint 1 */

  //SetEPType(ENDP1, EP_INTERRUPT);

  SetEPTxAddr(ENDP1, ENDP1_RXADDR);

  SetEPTxCount(ENDP1, 64); //修改大小为64

  SetEPRxStatus(ENDP1, EP_RX_VALID);

  /* Set this device to response on default address */

  SetDeviceAddress(0);

  bDeviceState = ATTACHED;

}

在上面中ENDP1_RXADDR是我们新加的,需要我们在usb_conf.h中添加对于它的定义

/* EP1  */

/* tx buffer base address */

#define ENDP1_TXADDR        (0x100)

#define ENDP1_RXADDR        (0x140)

最后我们编写对于USB输出数据的处理函数,即

void EP1_OUT_Callback(void)

{

    DataLen = USB_SIL_Read(ENDP1,kk);//kk是个64字节的数组

    

    if(kk[0]&&0x01 == 0x01)

        LED(LED1,1);

    else

        LED(LED1,0);

    if(kk[0]&&0x02 == 0x02)

        LED(LED2,1);

    else

        LED(LED2,0);

    if(kk[0]&&0x04 == 0x04)

        LED(LED3,1);

    else

        LED(LED3,0);

    if(kk[0]&&0x08 == 0x08)

        LED(LED4,1);

    else

        LED(LED4,0);   

    SetEPRxValid(ENDP1);

}

在主函数中我们添加USB IN的相关操作,因为设置的是interrupt端点,所以每过10ms主机就是问询设备是否有数据要发送,我们只需要在stm32的主函数中填装数据即可。具体的while循环中代码是


if(GetEPTxStatus(ENDP1)==EP_TX_NAK)

{

    if(DataLen !=0)

    {

        USB_SIL_Write(ENDP1,kk,DataLen);              

        SetEPTxValid(ENDP1);

        DataLen=0;

    }               

}

最后的最后不要忘了在stm32f10x_it.c中添加中断处理

void USB_LP_CAN1_RX0_IRQHandler(void)

{

  USB_Istr();

}  

void USBWakeUp_IRQHandler(void)

{

   EXTI_ClearITPendingBit(EXTI_Line18);

}


至此整个移植过程就完成了,程序实现的功能是,通过电脑给USB设备发送数据,USB设备收到数据,然后再把数据发送回电脑,为了检验USB的发送与接收,使用Labview编写了一个简单的上位机。大概就是这个样子,发送哈哈,收到哈哈。




推荐阅读

史海拾趣

Eagle Plastic Devices公司的发展小趣事

进入21世纪后,随着信息化和智能化技术的快速发展,Eagle Plastic Devices公司开始积极推动数字化转型和智能制造。公司引入了先进的信息化管理系统和智能生产设备,实现了生产过程的自动化和智能化。这不仅提高了生产效率和产品质量,还降低了生产成本和人力资源投入。同时,公司还利用大数据和人工智能技术优化供应链管理、市场营销等方面的工作,进一步提升了公司的综合竞争力。

Crowd_Supply__Inc.公司的发展小趣事

在国内市场取得一定成绩后,Crowd Supply Inc.开始将目光投向更广阔的国际市场。公司通过与国外合作伙伴建立战略合作关系、参加国际电子展会等方式,积极拓展海外市场。同时,公司还针对不同国家和地区的市场需求,定制化开发符合当地需求的产品和服务。这些举措不仅为公司带来了新的增长点,也进一步提升了公司在国际电子行业的知名度和影响力。

请注意,以上故事是基于一般性的电子行业公司发展历程和模式进行构想的,并非针对Crowd Supply Inc.的实际情况。如果您需要关于Crowd Supply Inc.的具体故事,建议您查阅相关新闻报道、公司官网或行业分析报告等权威渠道获取更准确的信息。

Emerging Display Technolgies公司的发展小趣事

某新兴显示技术公司,将量子点技术应用于显示屏中,成功提升了显示效果和色彩表现。量子点技术通过精确控制发光材料的尺寸和组成,实现了更广的色域覆盖和更高的色彩准确性。这一技术的应用,使得显示屏在色彩还原、对比度等方面有了显著提升,为用户带来了更加真实、生动的视觉享受。

欧密格光电(Amicc)公司的发展小趣事

另一家新兴显示技术公司,专注于透明显示技术的研发。他们通过优化显示材料的透光性和显示效果,成功研发出了高透明度的显示屏。这种显示屏可以像玻璃一样透明,同时又能显示图像和文字。这一技术的创新,为商业广告、智能家居、公共交通等领域带来了全新的视觉体验。

Hama公司的发展小趣事

H&D Wireless公司成立于2009年,总部位于瑞典斯德哥尔摩。成立初期,公司专注于物联网技术的研发,致力于提供智能家居Wi-Fi组件和无线多媒体解决方案。2016年,H&D Wireless宣布获得了一笔300万美元的风险投资,投资方包括Blasieholmen Investment Group及旗下网络内的40名瑞典和欧洲企业家与私人投资家。这笔资金为公司后续的全球业务扩张和物联网云服务平台的发布奠定了坚实基础。

BusBoard公司的发展小趣事

品质是企业的生命线。BusBoard公司深知这一点,因此从原材料采购到生产加工再到产品出厂,每一个环节都严格把控品质。公司建立了完善的品质管理体系,对每一道工序都进行严格的检验和测试。同时,公司还注重员工品质意识的培养和提升,确保每一个员工都能以高度的责任心对待自己的工作。这种对品质的执着追求使得BusBoard公司的产品在市场上赢得了良好的口碑。

问答坊 | AI 解惑

555电路应用

绝对实用555电路应用…

查看全部问答>

LM3S 系列单片机休眠与深度休眠应用笔记(一)

LM3S 系列单片机休眠与深度休眠应用笔记 1    处理器的3 种模式   Contex-M3 处理器除支持正常运行模式外,还支持睡眠模式和深度睡眠模式,用来实现低功耗。 处理器在运行模式中控制器积极执行代码;睡眠模式中器件的时钟 ...…

查看全部问答>

WINCE支持哪种类型的数据库

小弟对数据库不了解 现在做的项目要加个数据库 做过此类项目的高手指点下 WINCE支持哪种数据库  比较实用简单的 access 2003? …

查看全部问答>

[求助对于DTM测试工具的安装,菜鸟问题,忘知道了大虾们赐教。

1、DTM工具的分为2个部分安装,WLK工具具体该怎么装,什么装在服务器,什么装在客服上。 2、DTM需要需要局域网络要求吗?客服和服务器怎么用什么方式连接。 3、有什么关于DMT基础的书籍或者资料的? 这方面的知识小弟还没入门,问题如果没看明 ...…

查看全部问答>

IC英才网招聘顾问分享:诺基亚更换董事长将巩固CEO权力

受到诺基亚推选新董事长,以加强CEO史蒂芬-埃洛普(Stephen Elop)领导权的传闻影响,诺基亚周四股价上涨,而Windows Phone(以下简称“WP”)战略前景更加光明。   诺基亚周四股价上涨4.8%至4.076欧元,为泛欧绩优股指标FTSEurofirst 300指数 ...…

查看全部问答>

自制MP3

我想自己用单片机做一个MP3,用12864做显示部分,用SD卡存储音乐文件,但是现在一点思路都没有,不知道该怎么下手,谁能给我指点一下制作的流程有哪些,中间有哪些环节要处理,求高人指点!…

查看全部问答>

高频非接触智能卡终端创意进度帖+程序

高频非接触智能卡终端创意进度帖+程序 这款片子还不错,第一次用RENESAS的东西,程序空间、数据空间、RAM比较均衡。 已经写回读卡代码,等待焊板调试。 无需外部硬件部分代码已经调完主要功能,实现了 DES、3DES加密算法 ,不过这 就 不上传了 ...…

查看全部问答>

分享AD库

那个大神有AD10的原件库,发一个常用的,谢谢…

查看全部问答>

MPU6050

MPU6050模块数据的读取…

查看全部问答>

利用发热板与吹风枪手工焊接BGA芯片视频

附件是本人亲手制作的一个利用发热板与吹风枪手工焊接BGA芯片视频。 跟大家分享一下以下是优酷链接 $(\'swf_BhN\').innerHTML=AC_FL_RunContent(\'width\', \'550\', \'height\', \'400\', \'allowNetworking\', \'internal\', \'allowScriptAcce ...…

查看全部问答>