我是靠谱客的博主 虚拟蛋挞,最近开发中收集的这篇文章主要介绍STM32F429连接USB飞行摇杆 (一) 连接摇杆,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

本文介绍如何使用stm32连接usb接口的飞行摇杆。

工程源码:单片机STM32F429连接USB飞行摇杆示例工程-单片机文档类资源-CSDN文库

开发环境

硬件: STM32F429IGT6开发板,USB接口的飞行摇杆。

软件:STM32CubeIDE 1.11

仿真器:stlink

参考书:《圈圈教你玩USB》

USB设备描述符

一个USB设备只有一个设备描述符。USB主机通过不同种类的描述符,获得一个设备的特性。描述符的种类包括:设备描述符,配置描述符,接口描述符,端点描述符。USB描述符之间的关系是一种树状结构。设备描述符包含多个配置描述符,配置描述符包含多个接口描述符,接口描述符包含多个端点描述符。如下图所示:

STM32CubeIDE的USB HOST模块实现了USB设备通讯,实现了设备发现到设备枚举,获得描述符等一系列操作。在此基础之上,可以方便的开发USB主机模式的应用。本文使用USB HOST模块实现连接USB飞行摇杆。

建立项目

使用CubeIDE 新建一个F429项目,项目的名称为F429JoyStick。

芯片配置:

RCC

USB_OTG_FS

USB_HOST

时钟

USB使用的时钟,必须是48MHz,否则在运行代码时,通讯会失败,无法获得设备描述符。

配置完成,保存并生成代码。

USB设备处理流程

int main(void)
{
  HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();

  MX_USB_HOST_Init(); //初始化USB硬件

  while (1)
  {
    MX_USB_HOST_Process();  //更新USB设备状态。
  }
}

main方法循环调用MX_USB_HOST_Process(),所有USB操作都在MX_USB_HOST_Process()方法里完成。MX_USB_HOST_Process()最终会调用usbh_core.c文件里的 USBH_StatusTypeDef USBH_Process (USBH_HandleTypeDef *phost) 方法,这个方法的源代码较长。以下是这个方法的流程图:

USBH_Process()使用状态机在不同的状态之间转换,一切顺利的情况下,将会获得所有的描述符。

调试及修改

用仿真器烧录程序、调试,会发现运行到HOST_CHECK_CLASS状态时,直接跳转到了HOST_ABORT_STATE状态。问题出在这一段代码:

第714行 if (phost->pActiveClass->Init(phost) ==USBH_OK)

只有在返回值为USBH_OK时,才能转到下一个状态,否则转到HOST_ABORT_STATE状态。

phost->pActiveClass->Init(phost)调用的是usbh_hid.c文件里的static USBH_StatusTypeDef USBH_HID_InterfaceInit(USBH_HandleTypeDef*phost)方法

代码如下:

USBH_HID_InterfaceInit方法继续调用USBH_FindInterface方法:

这段代码遍历&pcfg->Itf_Desc的所有接口描述符,如果有符合条件的描述符,返回描述符的序号,否则返回0xFFU。

下图是使用仿真器获得的飞行摇杆的接口描述符:

其中的pcfg->Itf_Desc[0]接口描述符里的三个值是

bInterfaceClass = 3

bInterfaceSubClass = 0

bInterfaceProtocol = 0

这三个值很重要,后面的代码修改都是围绕这三个值。

if (((pif->bInterfaceClass ==Class) || (Class == 0xFFU)) &&

((pif->bInterfaceSubClass ==SubClass) || (SubClass == 0xFFU)) &&

((pif->bInterfaceProtocol == Protocol) || (Protocol == 0xFFU)))

这个判断条件里的其他值

Class = 3

SubClass = 1

Protocol = 0xFFU

显然不满足判断语句的条件。USB HOST默认生成的代码不支持Class=3,SubClass=0,Protocol=0的USB设备。

修改USBH_HID_InterfaceInit(USBH_HandleTypeDef*phost)方法的代码,修改结果如下:

重新编译后继续调试,会发现USBH_HID_InterfaceInit(USBH_HandleTypeDef*phost)方法里的这段代码又出现了问题:

同样的道理,对于不支持的USB设备,会直接返回USBH_FAIL。为此,需要在项目里增加一个飞行摇杆设备。

增加usbh_hid_joystick.h, usbh_hid_joystick.c文件

新增文件的目录结构如下:

usbh_hid_joystick.h

#ifndef __USBH_HID_JOYSTICK_H
#define __USBH_HID_JOYSTICK_H

#ifdef __cplusplus
extern "C" {
#endif

#include "usbh_hid.h"

#define PROTOLENGTH 8

typedef struct _HID_JOYSTICK_Info
{
  uint8_t              data[PROTOLENGTH];
}
HID_JOYSTICK_Info_TypeDef;


USBH_StatusTypeDef USBH_HID_JoyStickInit(USBH_HandleTypeDef *phost);
HID_JOYSTICK_Info_TypeDef *USBH_HID_GetJoyStickInfo(USBH_HandleTypeDef *phost);


#ifdef __cplusplus
}
#endif

#endif 

usbh_hid_joystick.c

#include "usbh_hid_joystick.h"
#include "usbh_hid_parser.h"
#include <string.h>

HID_JOYSTICK_Info_TypeDef    joystick_info;
uint8_t                  joystick_report_data[PROTOLENGTH];
uint8_t                  joystick_rx_report_buf[PROTOLENGTH];

static USBH_StatusTypeDef USBH_HID_JoyStickDecode(USBH_HandleTypeDef *phost);

USBH_StatusTypeDef USBH_HID_JoyStickInit(USBH_HandleTypeDef *phost)
{
  uint32_t i;
  HID_HandleTypeDef *HID_Handle = (HID_HandleTypeDef *) phost->pActiveClass->pData;

    for (i = 0U; i <PROTOLENGTH; i++)
    {
      joystick_info.data[i] = 0U;
        joystick_report_data[i] = 0U;
        joystick_rx_report_buf[i] = 0U;
    }

  if (HID_Handle->length > sizeof(joystick_report_data))
  {
    HID_Handle->length = (uint16_t)sizeof(joystick_report_data);
  }
  HID_Handle->pData = (uint8_t *)(void *)joystick_rx_report_buf;
  USBH_HID_FifoInit(&HID_Handle->fifo, phost->device.Data, (uint16_t)(HID_QUEUE_SIZE * sizeof(joystick_report_data)));

  return USBH_OK;
}

HID_JOYSTICK_Info_TypeDef *USBH_HID_GetJoyStickInfo(USBH_HandleTypeDef *phost)
{
  if (USBH_HID_JoyStickDecode(phost) == USBH_OK)
  {
    return &joystick_info;
  }
  else
  {
    return NULL;
  }
}

static USBH_StatusTypeDef USBH_HID_JoyStickDecode(USBH_HandleTypeDef *phost)
{
  HID_HandleTypeDef *HID_Handle = (HID_HandleTypeDef *) phost->pActiveClass->pData;

  if (HID_Handle->length == 0U)
  {
    return USBH_FAIL;
  }

  if (USBH_HID_FifoRead(&HID_Handle->fifo, &joystick_report_data, HID_Handle->length) ==  HID_Handle->length)
  {
      for(int i=0;i<HID_Handle->length;i++)
      {
          joystick_info.data[i] = *(joystick_report_data + i);
      }
    return USBH_OK;
  }
  return   USBH_FAIL;
}

修改其他文件,修改内容如下:

增加适当的include文件后,保存所有修改,重新生成文件,调试。

将断点设置在usb_host.c的如下位置:

程序能运行到Appli_state = APPLICATION_READY这一行说明USB设备可以正常连接了。

其他

在usbh_hid_joystick.h里的PROTOLENGTH是USB数据传输时使用的长度

#define PROTOLENGTH 8

PROTOLENGTH定义的长度值需要从端点描述符里获得:

获得位置也是在USBH_HID_InterfaceInit(USBH_HandleTypeDef*phost)方法里

其中HID_Handle->length变量的值就是PROTOLENGTH需要定义的值。

usbh_hid_joystick.c :

USBH_HID_GetJoyStickInfo方法用来获得飞行摇杆的数据。

摇杆协议解析:

STM32F429连接USB飞行摇杆 (二) 摇杆协议

最后

以上就是虚拟蛋挞为你收集整理的STM32F429连接USB飞行摇杆 (一) 连接摇杆的全部内容,希望文章能够帮你解决STM32F429连接USB飞行摇杆 (一) 连接摇杆所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(49)

评论列表共有 0 条评论

立即
投稿
返回
顶部