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]