晓伍 发表于 2025-2-23 21:21

STM32F4系列USB接口

1. USB接口概述
USB(Universal Serial Bus,通用串行总线)是一种标准的串行接口,广泛应用于计算机和各种外部设备之间进行通信和供电。STM32F4系列单片机集成了多个USB接口,包括全速USB(FS)、高速USB(HS)和USB OTG(On-The-Go)接口。这些接口支持多种USB设备模式,如设备模式、主机模式和OTG模式,可以满足不同应用场景的需求。



1.1 USB接口类型
STM32F4系列单片机支持以下几种USB接口类型:

全速USB(FS):最高传输速率为12 Mbps,适用于需要简单、低功耗USB通信的场景。

高速USB(HS):最高传输速率为480 Mbps,适用于需要高速数据传输的场景。

USB OTG:支持USB设备模式和主机模式的切换,适用于需要在设备和主机之间灵活切换的场景。

1.2 USB接口功能
STM32F4系列单片机的USB接口具有以下功能:

设备模式:作为USB设备与主机通信,支持多种USB设备类标准(如HID、CDC、Mass Storage等)。

主机模式:作为USB主机与外部USB设备通信。

OTG模式:支持设备和主机模式的动态切换。

高速和全速支持:根据应用场景选择不同的传输速率。

DMA支持:通过DMA(Direct Memory Access)提高数据传输效率。

电源管理:支持USB供电和低功耗模式。

2. USB接口硬件设计
2.1 USB接口引脚
STM32F4系列单片机的USB接口引脚如下:

DP(D+):USB数据线正。

DM(D-):USB数据线负。

VBUS:USB电源线,用于检测USB连接状态。

ID:用于检测USB OTG模式。

2.2 外部电路设计
为了确保USB接口的正常工作,需要设计合适的外部电路。以下是一些基本的外部电路设计要点:

终端电阻:在USB DP和DM引脚之间连接一个1.5kΩ的终端电阻,用于匹配传输线的阻抗。

滤波电容:在VBUS和GND之间连接一个10µF的滤波电容,用于滤除电源噪声。

上拉电阻:在DP引脚和3.3V之间连接一个1.5kΩ的上拉电阻,用于指示设备连接状态。

OTG检测电路:对于USB OTG接口,需要在ID引脚上连接一个下拉电阻和一个上拉电阻,用于检测OTG模式。

2.3 USB电源管理
STM32F4系列单片机的USB接口支持多种电源管理功能,包括:

VBUS检测:通过检测VBUS引脚的电压来确定USB连接状态。

低功耗模式:在不使用USB接口时,可以进入低功耗模式以节省电能。

USB供电:单片机可以通过USB接口获取5V电源,经过内部稳压器转换为3.3V供电。

3. USB接口软件开发
3.1 USB库介绍
STM32F4系列单片机提供了丰富的USB库,包括标准USB设备库、USB主机库和USB OTG库。这些库简化了USB接口的开发工作,提供了多种USB设备类(如HID、CDC、Mass Storage等)的实现。

3.2 USB设备模式开发
3.2.1 CDC设备类(虚拟串口)
CDC(Communication Device Class)设备类可以将STM32F4系列单片机模拟成一个虚拟串口,实现与PC的串行通信。以下是一个简单的CDC设备类开发示例:

配置开发环境:

安装STM32CubeMX工具,生成USB CDC设备类的初始化代码。

使用STM32CubeIDE进行代码开发。

初始化USB接口:


// 初始化USB接口

static void MX_USB_DEVICE_Init(void)

{

USBD_Init(&hUsbDeviceFS, &USD_CDC_cb, 0);

USBD_RegisterClass(&hUsbDeviceFS, USBD_CDC_CLASS);

USBD_CDC_RegisterInterface(&hUsbDeviceFS, &USBD_Interface_fops);

USBD_Start(&hUsbDeviceFS);

}



实现USB CDC类接口:


// USB CDC类接口操作函数

static int8_t CDC_Receive(uint8_t *pData, uint32_t *Len)

{

// 通过CDC设备类接收数据

USBD_CDC_ReceivePacket(&hUsbDeviceFS);

return USBD_OK;

}



static int8_t CDC_Transmit(uint8_t *pData, uint32_t Len)

{

// 通过CDC设备类发送数据

USBD_CDC_SendPacket(&hUsbDeviceFS, pData, Len);

return USBD_OK;

}



USBD_CDC_IfTypeDef USBD_Interface_fops = {

CDC_Init,

CDC_DeInit,

CDC_Control,

CDC_Receive,

CDC_Transmit

};



主程序:


int main(void)

{

HAL_Init();

SystemClock_Config();

MX_GPIO_Init();

MX_USB_DEVICE_Init();



while (1)

{

    // 主循环中处理USB通信

    HAL_Delay(1000);

    char data[] = "Hello, USB CDC!";

    CDC_Transmit((uint8_t *)data, strlen(data));

}

}




3.3 USB主机模式开发
3.3.1 USB主机类(HID设备)
HID(Human Interface Device)类设备包括键盘、鼠标等输入设备。以下是一个简单的USB主机模式开发示例,实现对HID设备的支持:

配置开发环境:

安装STM32CubeMX工具,生成USB主机类的初始化代码。

使用STM32CubeIDE进行代码开发。

初始化USB主机接口:


// 初始化USB主机接口

static void MX_USB_HOST_Init(void)

{

USBH_Init(&hUsbHost, &USBD_UsrDesc, 0);

USBH_RegisterClass(&hUsbHost, USBH_HID_CLASS);

USBH_Start(&hUsbHost);

}



实现USB HID类接口:


// USB HID类接口操作函数

static void HID_Process(uint8_t *pData, uint32_t Len)

{

// 处理HID设备的数据

for (uint32_t i = 0; i < Len; i++)

{

    if (pData == 0x01)

    {

      // 处理键值0x01

      HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET);

    }

    else if (pData == 0x02)

    {

      // 处理键值0x02

      HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET);

    }

}

}



static HID_ReportTypeDef HID_Report = {

HID_Process

};




主程序:


int main(void)

{

HAL_Init();

SystemClock_Config();

MX_GPIO_Init();

MX_USB_HOST_Init();



while (1)

{

    // 主循环中处理USB通信

    USBH_Process(&hUsbHost);

    HAL_Delay(100);

}

}



3.4 USB OTG模式开发
3.4.1 USB OTG设备模式
USB OTG设备模式允许STM32F4系列单片机在没有主机的情况下作为主机运行,实现设备间的直接通信。以下是一个简单的USB OTG设备模式开发示例:

配置开发环境:

安装STM32CubeMX工具,生成USB OTG设备类的初始化代码。

使用STM32CubeIDE进行代码开发。

初始化USB OTG接口:


// 初始化USB OTG接口

static void MX_USB_OTG_FS_DEVICE_Init(void)

{

USBD_Init(&hUsbDeviceFS, &USD_CDC_cb, 0);

USBD_RegisterClass(&hUsbDeviceFS, USBD_CDC_CLASS);

USBD_CDC_RegisterInterface(&hUsbDeviceFS, &USBD_Interface_fops);

USBD_Start(&hUsbDeviceFS);

}



实现USB OTG设备类接口:


// USB OTG设备类接口操作函数

static int8_t CDC_Receive(uint8_t *pData, uint32_t *Len)

{

// 处理接收的数据

USBD_CDC_ReceivePacket(&hUsbDeviceFS);

return USBD_OK;

}



static int8_t CDC_Transmit(uint8_t *pData, uint32_t Len)

{

// 发送数据

USBD_CDC_SendPacket(&hUsbDeviceFS, pData, Len);

return USBD_OK;

}



USBD_CDC_IfTypeDef USBD_Interface_fops = {

CDC_Init,

CDC_DeInit,

CDC_Control,

CDC_Receive,

CDC_Transmit

};




主程序:


int main(void)

{

HAL_Init();

SystemClock_Config();

MX_GPIO_Init();

MX_USB_OTG_FS_DEVICE_Init();



while (1)

{

    // 主循环中处理USB通信

    HAL_Delay(1000);

    char data[] = "Hello, USB OTG!";

    CDC_Transmit((uint8_t *)data, strlen(data));

}

}




3.4.2 USB OTG主机模式
USB OTG主机模式允许STM32F4系列单片机作为主机,管理多个USB设备。以下是一个简单的USB OTG主机模式开发示例:

配置开发环境:

安装STM32CubeMX工具,生成USB OTG主机类的初始化代码。

使用STM32CubeIDE进行代码开发。

初始化USB OTG主机接口:


// 初始化USB OTG主机接口

static void MX_USB_OTG_FS_HOST_Init(void)

{

USBH_Init(&hUsbHost, &USBD_UsrDesc, 0);

USBH_RegisterClass(&hUsbHost, USBH_HID_CLASS);

USBH_Start(&hUsbHost);

}



实现USB OTG主机类接口:


// USB OTG主机类接口操作函数

static void HID_Process(uint8_t *pData, uint32_t Len)

{

// 处理HID设备的数据

for (uint32_t i = 0; i < Len; i++)

{

    if (pData == 0x01)

    {

      // 处理键值0x01

      HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET);

    }

    else if (pData == 0x02)

    {

      // 处理键值0x02

      HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET);

    }

}

}



static HID_ReportTypeDef HID_Report = {

HID_Process

};




主程序:


int main(void)

{

HAL_Init();

SystemClock_Config();

MX_GPIO_Init();

MX_USB_OTG_FS_HOST_Init();



while (1)

{

    // 主循环中处理USB通信

    USBH_Process(&hUsbHost);

    HAL_Delay(100);

}

}


3.5 USB中断处理
USB接口的工作依赖于中断处理,以确保数据的及时传输和处理。以下是一个简单的USB中断处理示例:


// USB中断处理函数

void USB OTG_FS_IRQHandler(void)

{

HAL_USB_OTG_IRQHandler(&hUsbDeviceFS);

}



// USB中断回调函数

void HAL_USB_OTG_FS_DataOutStageCallback(uint8_t epnum)

{

// 处理数据输出中断

if (epnum == 0x01)

{

    // 例如处理端点1的数据输出

    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_6, GPIO_PIN_SET);

}

}



void HAL_USB_OTG_FS_DataInStageCallback(uint8_t epnum)

{

// 处理数据输入中断

if (epnum == 0x81)

{

    // 例如处理端点0x81的数据输入

    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_6, GPIO_PIN_RESET);

}

}



void HAL_USB_OTG_FS_SOF_Callback(void)

{

// 处理USB SOF(Start of Frame)中断

static uint32_t count = 0;

count++;

if (count % 1000 == 0)

{

    // 每1000个SOF中断执行一次操作

    HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_7);

}

}




3.6 USB电源管理
USB接口的电源管理对于提高系统能效和确保设备的正常工作非常重要。以下是一些电源管理的示例代码:

检测VBUS状态:


// 检测VBUS状态

void Check_VBUS_Status(void)

{

if (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_9) == GPIO_PIN_SET)

{

    // VBUS检测引脚为高,表示USB已连接

    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_SET);

}

else

{

    // VBUS检测引脚为低,表示USB未连接

    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_RESET);

}

}




进入低功耗模式:


// 进入低功耗模式

void Enter_LowPower_Mode(void)

{

HAL_PWRErrorStatusTypeDef status;

PWR进入低功耗模式配置

__HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);

HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);

status = HAL_PWR_GetErrorStatus();

if (status != HAL_PWR_ERROR_NONE)

{

    // 低功耗模式进入失败

    Error_Handler();

}

}




从低功耗模式唤醒:


// 从低功耗模式唤醒

void WakeUp_from_LowPower_Mode(void)

{

// 检测唤醒源

if (__HAL_PWR_GET_FLAG(PWR_FLAG_WU) != RESET)

{

    // USB唤醒

    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_SET);

}

}




3.7 USB设备枚举
USB设备枚举是USB主机与设备之间的初始化过程,通过枚举,主机可以获取设备的描述符信息并配置设备。以下是一个简单的USB设备枚举示例:

设备描述符:


// USB设备描述符

__ALIGN_BEGIN const uint8_t USBD_DeviceDesc __ALIGN_END = {

0x12,   // bLength

0x01,   // bDescriptorType

0x00,   // bcdUSB (low byte)

0x02,   // bcdUSB (high byte)

0x00,   // bDeviceClass

0x00,   // bDeviceSubClass

0x00,   // bDeviceProtocol

0x40,   // bMaxPacketSize0

0x84,   // idVendor (low byte)

0x04,   // idVendor (high byte)

0x00,   // idProduct (low byte)

0x01,   // idProduct (high byte)

0x00,   // bcdDevice (low byte)

0x01,   // bcdDevice (high byte)

0x01,   // iManufacturer

0x02,   // iProduct

0x03,   // iSerialNumber

0x01    // bNumConfigurations

};




配置描述符:


// 配置描述符

USBD_StatusTypeDef USBD_CDC_Init(USBD_HandleTypeDef *pdev, uint8_t cfgidx)

{

pdev->pClassData = USBD_malloc(sizeof(USBD_CDC_HandleTypeDef));

if (pdev->pClassData == NULL)

{

    return USBD_MEM_ERROR;

}

pdev->pClassData = (USBD_CDC_HandleTypeDef *)pdev->pClassData;

pdev->pClassData->hUsbDevice = pdev;

pdev->pClassData->ChannelState = CDC_CHANNEL_IDLE;

return USBD_OK;

}




枚举回调函数:


// 枚举回调函数

void USBD_EnumCallback(uint8_t dev, uint8_t event, uint8_t *data, uint16_t len)

{

switch (event)

{

case USB_EVENT_DEVICE_CONNECTED:

    // 设备连接

    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET);

    break;

case USB_EVENT_DEVICE_DISCONNECTED:

    // 设备断开

    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET);

    break;

case USB_EVENT_CONFIGURATION_DONE:

    // 配置完成

    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_6, GPIO_PIN_SET);

    break;

default:

    break;

}

}




3.8 USB数据传输
USB数据传输包括控制传输、批量传输、中断传输和同步传输。这些传输类型适用于不同的应用场景,以确保数据的高效传输和处理。以下是对这些传输类型的详细介绍和示例代码:

3.8.1 控制传输
控制传输主要用于传输控制信息和获取设备的状态。这种传输类型在USB设备枚举过程中非常重要。

控制传输请求:


// 发送控制传输请求

static void Send_Control_Request(void)

{

USBD_SetupPacket setup;

setup.bmRequestType = 0x80; // IN方向,标准请求

setup.bRequest = USB_REQ_GET_DESCRIPTOR;

setup.wValue = USB_DESC_TYPE_DEVICE << 8;

setup.wIndex = 0x00;

setup.wLength = USB_LEN_DEV_DESC;

USBD-ControlTransfer(&hUsbDeviceFS, &setup, (uint8_t *)USBD_DeviceDesc);

}





处理控制传输响应:


// 处理控制传输响应

static int8_t Handle_Control_Transfer(uint8_t *pData, uint32_t Len)

{

// 处理接收到的设备描述符

if (Len == USB_LEN_DEV_DESC)

{

    // 处理设备描述符

    // 例如,解析设备描述符中的信息

}

return USBD_OK;

}





3.8.2 批量传输
批量传输用于传输大量数据,适用于文件传输等场景。这种传输类型保证了数据的完整性和可靠性。

发送批量数据:


// 发送批量数据

static void Send_Bulk_Data(uint8_t *pData, uint32_t Len)

{

USBD_BulkOUT(&hUsbDeviceFS, 0x02, pData, Len);

}




接收批量数据:


// 接收批量数据

static int8_t Receive_Bulk_Data(uint8_t *pData, uint32_t *Len)

{

// 处理接收到的批量数据

if (*Len > 0)

{

    // 例如,将数据保存到文件中

}

return USBD_OK;

}





3.8.3 中断传输
中断传输用于传输周期性的、少量的数据,适用于键盘、鼠标等输入设备。这种传输类型保证了数据的及时性和响应性。

发送中断数据:


// 发送中断数据

static void Send_Interrupt_Data(uint8_t *pData, uint32_t Len)

{

USBD_InterruptOUT(&hUsbDeviceFS, 0x03, pData, Len);

}



接收中断数据:


// 接收中断数据

static int8_t Receive_Interrupt_Data(uint8_t *pData, uint32_t *Len)

{

// 处理接收到的中断数据

if (*Len > 0)

{

    // 例如,处理键盘按键事件

}

return USBD_OK;

}




3.8.4 同步传输
同步传输用于传输实时数据,如音频和视频。这种传输类型保证了数据的传输速率和时序。

发送同步数据:


// 发送同步数据

static void Send_Sync_Data(uint8_t *pData, uint32_t Len)

{

USBD_ISOOUT(&hUsbDeviceFS, 0x04, pData, Len);

}



接收同步数据:


// 接收同步数据

static int8_t Receive_Sync_Data(uint8_t *pData, uint32_t *Len)

{

// 处理接收到的同步数据

if (*Len > 0)

{

    // 例如,处理音频数据

}

return USBD_OK;

}



3.9 USB库配置
STM32F4系列单片机的USB库配置可以通过STM32CubeMX工具进行。以下是一些基本的配置步骤:

打开STM32CubeMX:

启动STM32CubeMX工具。

选择相应的STM32F4系列单片机型号。

配置USB接口:

在“Pinout & Configuration”选项卡中,找到“Connectivity”模块,选择“USB OTG FS”。

配置USB OTG FS的模式(设备模式、主机模式或OTG模式)。

配置USB OTG FS的引脚(DP、DM、VBUS、ID)。

生成初始化代码:

在“Project Manager”选项卡中,选择生成项目代码的路径。

选择“Generate Code”按钮,生成初始化代码。

使用生成的代码:

打开生成的项目文件,使用STM32CubeIDE进行开发。

根据生成的代码进行USB接口的初始化和配置。

3.10 USB调试和测试
USB接口的调试和测试对于确保系统的正常工作非常重要。以下是一些常用的调试和测试方法:

使用USB调试工具:

使用USB调试工具(如USBlyzer、Wireshark等)捕获USB通信数据包,分析数据传输过程。

检查USB设备的枚举过程和配置信息。

日志输出:

在代码中添加日志输出功能,记录关键的USB事件和数据传输状态。

使用串口或调试接口输出日志信息,方便调试。

单元测试:

编写单元测试代码,测试USB接口的基本功能(如初始化、数据传输、中断处理等)。

使用模拟USB设备或实际USB设备进行测试,确保功能的正确性。

3.11 USB常见问题及解决方法
在使用STM32F4系列单片机的USB接口时,可能会遇到一些常见问题。以下是一些解决方法:

USB设备不被识别:

检查USB引脚连接是否正确。

确保电源管理设置正确,VBUS检测引脚正常工作。

检查USB描述符配置是否正确。

数据传输速率低:

确认USB接口模式(全速或高速)是否设置正确。

检查DMA配置是否正确,确保数据传输效率。

优化USB中断处理函数,减少中断延迟。

USB接口功耗高:

确认低功耗模式配置是否正确。

检查电源管理设置,确保在不使用USB接口时进入低功耗模式。

优化USB通信代码,减少不必要的数据传输和处理。

3.12 USB应用示例
以下是一些常见的USB应用示例,展示如何在STM32F4系列单片机上实现不同的USB功能:

3.12.1 USB虚拟键盘
实现一个USB虚拟键盘,将STM32F4系列单片机模拟成一个键盘设备,发送按键事件到主机。

配置USB HID设备类:

使用STM32CubeMX生成USB HID设备类的初始化代码。

配置HID报告描述符,定义按键事件的数据格式。

主程序:


int main(void)

{

HAL_Init();

SystemClock_Config();

MX_GPIO_Init();

MX_USB_DEVICE_Init();



while (1)

{

    // 例如,发送一个按键事件

    uint8_t key_data = {0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00}; // 按下A键

    USBD_HID_SendReport(&hUsbDevice, key_data, 8);

    HAL_Delay(1000);



    // 释放按键

    uint8_t release_data = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

    USBD_HID_SendReport(&hUsbDevice, release_data, 8);

    HAL_Delay(1000);

}

}




3.12.2 USB虚拟串口
实现一个USB虚拟串口,使STM32F4系列单片机与PC进行串行通信。

配置USB CDC设备类:

使用STM32CubeMX生成USB CDC设备类的初始化代码。

配置CDC接口的操作函数(如CDC_Receive和CDC_Transmit)。

主程序:


int main(void)

{

HAL_Init();

SystemClock_Config();

MX_GPIO_Init();

MX_USB_DEVICE_Init();



while (1)

{

    // 接收PC发送的数据

    uint8_t rx_buffer;

    uint32_t rx_length;

    CDC_Receive(rx_buffer, &rx_length);



    if (rx_length > 0)

    {

      // 处理接收到的数据

      for (uint32_t i = 0; i < rx_length; i++)

      {

      // 例如,将接收到的数据回传给PC

      CDC_Transmit(&rx_buffer, 1);

      }

    }



    // 发送数据给PC

    char tx_data[] = "Hello, USB CDC!";

    CDC_Transmit((uint8_t *)tx_data, strlen(tx_data));

    HAL_Delay(1000);

}

}




3.13 总结
STM32F4系列单片机的USB接口功能强大,支持多种传输速率和工作模式。通过STM32CubeMX工具和STM32CubeIDE开发环境,可以轻松实现USB设备、主机和OTG模式的开发。本文档介绍了USB接口的基本概念、硬件设计要点、软件开发步骤以及一些常见的应用示例。希望这些内容能够帮助开发者更好地理解和使用STM32F4系列单片机的USB接口。

附录
附录A:USB描述符
USB描述符是USB设备与主机通信的重要数据结构,描述了设备的基本信息和功能。以下是一些常用的USB描述符:

设备描述符(Device Descriptor):描述设备的基本信息,如USB版本、设备类型、最大包大小等。

配置描述符(Configuration Descriptor):描述设备的配置信息,如接口数量、电源需求等。

接口描述符(Interface Descriptor):描述设备的接口信息,如接口类、子类等。

端点描述符(Endpoint Descriptor):描述设备的端点信息,如传输类型、最大包大小等。
————————————————

                            版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

原文链接:https://blog.csdn.net/2401_87715305/article/details/145660506

页: [1]
查看完整版本: STM32F4系列USB接口