USB(Universal Serial Bus,通用串行总线)是一种广泛应用的接口标准,用于在计算机和各种外设之间进行数据传输。STM32F7系列微控制器集成了一个高度灵活的USB接口,支持USB 2.0全速(12 Mbps)和高速(480 Mbps)通信。该接口不仅支持标准的USB设备和主机模式,还支持OTG(On-The-Go)模式,使得STM32F7可以同时作为设备和主机使用,极大地扩展了其应用范围。
高速数据传输:支持480 Mbps的高速传输,适用于需要大量数据传输的应用场景。
多种模式支持:支持设备模式、主机模式和OTG模式,灵活应对不同的应用需求。
丰富的端点配置:支持多个端点,每个端点可以配置为不同的传输类型(控制、批量、中断、等时)。
强大的DMA支持:内置DMA控制器,可以实现高效的数据传输,减轻CPU的负担。
低功耗管理:支持多种低功耗模式,如挂起和恢复,有助于延长电池寿命。
外设支持:集成了USB物理层(PHY)和数据链路层(DLC),简化了硬件设计。
STM32F7系列的USB接口硬件结构主要由以下几个部分组成:
USB控制器(USB Device/Host Controller):负责USB协议的解析和生成,管理USB传输的状态和控制。
USB物理层(USB PHY):实现USB信号的物理传输,包括信号的编码和解码。
USB数据链路层(USB DLC):负责数据包的打包和解包,以及错误检测和校正。
DMA控制器:用于高效的数据传输,减轻CPU的负担。
USB引脚:包括D+、D-和VBUS引脚,用于连接USB设备或主机。
USB控制器是USB接口的核心部分,负责处理USB的协议层。它支持多种传输类型,包括控制传输、批量传输、中断传输和等时传输。控制器通过USB设备或主机协议栈与外设进行通信,管理USB传输的状态和控制。
USB物理层负责实现USB信号的物理传输。STM32F7系列集成了全速和高速的PHY,可以在不同的传输速率下工作。物理层包括信号的编码和解码、差分信号的处理以及电源管理。
USB数据链路层负责数据包的打包和解包,以及错误检测和校正。它确保数据在传输过程中保持完整性和可靠性。数据链路层还负责处理USB的握手信号,如ACK、NAK和STALL。
DMA控制器用于高效的数据传输,减轻CPU的负担。通过配置DMA,可以实现数据的自动传输,无需CPU的频繁干预。这对于大流量的数据传输特别有用,可以显著提高系统的性能。
STM32F7系列的USB引脚包括D+、D-和VBUS。D+和D-用于差分信号的传输,VBUS用于电源管理。这些引脚需要连接到外部USB设备或主机,以实现通信。
STM32F7系列的USB接口配置主要通过STM32CubeMX工具和HAL库(Hardware Abstraction Layer,硬件抽象层)来实现。以下是一些基本的配置步骤和示例代码。
打开STM32CubeMX:启动STM32CubeMX工具。
选择微控制器:在项目配置中选择STM32F7系列的微控制器。
配置USB接口:在Pinout & Configuration界面中,找到并配置USB接口。可以选择设备模式、主机模式或OTG模式。
生成代码:配置完成后,生成初始化代码。这些代码将包括必要的头文件、库文件和初始化函数。
以下是一个使用HAL库初始化USB接口的示例代码:
#include "stm32f7xx_hal.h"
// USB设备句柄
USBD_HandleTypeDef hUsbDeviceFS;
// USB初始化函数
void MX_USB_Device_Init(void)
{
// USB设备初始化
USBD_Init(&hUsbDeviceFS, &FS_Desc, 0);
// 配置USB设备类
USBD_RegisterClass(&hUsbDeviceFS, &USBD_CDC_ClassDriver);
// 注册USB设备类回调函数
USBD_CDC_RegisterInterface(&hUsbDeviceFS, &USBD_Interface_fop庹);
// 启动USB设备
USBD_Start(&hUsbDeviceFS);
}
// USB设备描述符
USBD_Descriptors_t FS_Desc = {
.pStrDesc = (uint8_t*)USBD_FS_DEVICE_DESC,
.pStrLang = (uint8_t*)USBD_FS_LANGID_STR_DESC,
.pStrMfc = (uint8_t*)USBD_FS_MANUFACTURER_STR_DESC,
.pStrProduct = (uint8_t*)USBD_FS_PRODUCT_STR_DESC,
.pStrSerial = (uint8_t*)USBD_FS_SERIAL_STR_DESC,
.pStrConfig = (uint8_t*)USBD_FS_CONFIGURATION_STR_DESC,
.pStrInterface = (uint8_t*)USBD_FS_INTERFACE_STR_DESC
};
// USB设备类接口回调函数
USBD_CDC_ItfTypeDef USBD_Interface_fop庹 = {
.pItf = &USBD_CDC_fop庹,
.pData = NULL
};
// USB设备类接口实现
USBD_CDC_ItfDef USBD_CDC_fop庹 = {
.Init = CDC_Init,
.DeInit = CDC_DeInit,
.Control = CDC_Control,
.Receive = CDC_Receive,
.Send = CDC_Transmit
};
// 初始化USB设备类接口
static int8_t CDC_Init(void)
{
// 例如:配置USB中断和DMA
HAL_NVIC_SetPriority(USB_OTG_FS_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(USB_OTG_FS_IRQn);
return USBD_OK;
}
// 反初始化USB设备类接口
static int8_t CDC_DeInit(void)
{
// 例如:关闭USB中断和DMA
HAL_NVIC_DisableIRQ(USB_OTG_FS_IRQn);
return USBD_OK;
}
// 控制USB设备类接口
static int8_t CDC_Control(uint8_t cmd, uint8_t* pbuf, uint16_t length)
{
// 处理USB控制传输
switch (cmd) {
case CDC_SEND_ENCAPSULATED_COMMAND:
// 处理命令
break;
case CDC_GET_ENCAPSULATED_RESPONSE:
// 处理响应
break;
case CDC_SET_COMM_FEATURE:
// 设置通信特性
break;
case CDC_GET_COMM_FEATURE:
// 获取通信特性
break;
case CDC_CLEAR_COMM_FEATURE:
// 清除通信特性
break;
case CDC_SET_LINE_CODING:
// 设置线路编码
break;
case CDC_GET_LINE_CODING:
// 获取线路编码
break;
case CDC_SET_CONTROL_LINE_STATE:
// 设置控制线状态
break;
case CDC_SEND_BREAK:
// 发送中断信号
break;
}
return USBD_OK;
}
// 接收USB数据
static int8_t CDC_Receive(uint8_t* pbuf, uint32_t *plen)
{
// 将接收到的数据发送到UART
HAL_UART_Transmit(&huart1, pbuf, *plen, 1000);
return USBD_OK;
}
// 发送USB数据
static int8_t CDC_Transmit(uint8_t* pbuf, uint16_t length)
{
// 将UART接收到的数据发送到USB
USBD_CDC_SetTxBuffer(&hUsbDeviceFS, pbuf, length);
USBD_CDC_TransmitPacket(&hUsbDeviceFS);
return USBD_OK;
}
以下是一个USB设备模式的示例代码,展示了如何使用USB CDC类(通信设备类)实现简单的串行通信。
#include "stm32f7xx_hal.h"
#include "usbd_cdc.h"
// USB设备句柄
USBD_HandleTypeDef hUsbDeviceFS;
// UART句柄
UART_HandleTypeDef huart1;
// USB接收缓冲区
uint8_t USB_Rx_Buffer[64];
// USB发送缓冲区
uint8_t USB_Tx_Buffer[64];
// USB接收中断处理函数
void USB_OTG_FS_IRQHandler(void)
{
HAL_USB_IRQHandler(&hUsbDeviceFS);
}
// USB初始化函数
void MX_USB_Device_Init(void)
{
// USB设备初始化
USBD_Init(&hUsbDeviceFS, &FS_Desc, 0);
// 注册USB设备类
USBD_RegisterClass(&hUsbDeviceFS, &USBD_CDC_ClassDriver);
// 注册USB设备类回调函数
USBD_CDC_RegisterInterface(&hUsbDeviceFS, &USBD_Interface_fop庹);
// 启动USB设备
USBD_Start(&hUsbDeviceFS);
// 配置UART
huart1.Instance = USART1;
huart1.Init.BaudRate = 115200;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowControl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
HAL_UART_Init(&huart1);
}
// 初始化USB设备类接口
static int8_t CDC_Init(void)
{
// 配置USB中断和DMA
HAL_NVIC_SetPriority(USB_OTG_FS_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(USB_OTG_FS_IRQn);
return USBD_OK;
}
// 反初始化USB设备类接口
static int8_t CDC_DeInit(void)
{
// 关闭USB中断和DMA
HAL_NVIC_DisableIRQ(USB_OTG_FS_IRQn);
return USBD_OK;
}
// 控制USB设备类接口
static int8_t CDC_Control(uint8_t cmd, uint8_t* pbuf, uint16_t length)
{
// 处理USB控制传输
switch (cmd) {
case CDC_SET_LINE_CODING:
// 设置线路编码
break;
case CDC_GET_LINE_CODING:
// 获取线路编码
break;
case CDC_SET_CONTROL_LINE_STATE:
// 设置控制线状态
break;
case CDC_SEND_BREAK:
// 发送中断信号
break;
}
return USBD_OK;
}
// 接收USB数据
static int8_t CDC_Receive(uint8_t* pbuf, uint32_t *plen)
{
// 将接收到的数据发送到UART
HAL_UART_Transmit(&huart1, pbuf, *plen, 1000);
return USBD_OK;
}
// 发送USB数据
static int8_t CDC_Transmit(uint8_t* pbuf, uint16_t length)
{
// 将UART接收到的数据发送到USB
USBD_CDC_SetTxBuffer(&hUsbDeviceFS, pbuf, length);
USBD_CDC_TransmitPacket(&hUsbDeviceFS);
return USBD_OK;
}
// 主函数
int main(void)
{
// 系统初始化
HAL_Init();
// 配置时钟
SystemClock_Config();
// 初始化USB设备
MX_USB_Device_Init();
// 无限循环
while (1) {
// 检查UART接收缓冲区
if (HAL_UART_Receive(&huart1, USB_Tx_Buffer, 64, 100) == HAL_OK) {
// 发送数据到USB
CDC_Transmit(USB_Tx_Buffer, 64);
}
}
}
// 系统时钟配置函数
void SystemClock_Config(void)
{
// 配置系统时钟
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
// 配置HSE时钟
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 25;
RCC_OscInitStruct.PLL.PLLN = 432;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 9;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
Error_Handler();
}
// 配置系统时钟
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_7) != HAL_OK) {
Error_Handler();
}
}
// 错误处理函数
void Error_Handler(void)
{
// 处理错误
while (1) {
// 无限循环
}
}
以下是一个USB主机模式的示例代码,展示了如何使用USB主机库实现简单的USB主机功能。
#include "stm32f7xx_hal.h"
#include "usbh_core.h"
#include "usbh_cdc.h"
// USB主机句柄
USBH_HandleTypeDef hUsbHostFS;
// USB主机类句柄
USBH_CDC_ItfTypeDef USBH_USER_CDC_fop庹;
// USB接收缓冲区
uint8_t USB_Rx_Buffer[64];
// USB发送缓冲区
uint8_t USB_Tx_Buffer[64];
// USB主机初始化函数
void MX_USB_Host_Init(void)
{
// USB主机初始化
USBH_Init(&hUsbHostFS, USBH_USR_Callback, FS_HIGHSPEED);
// 注册USB主机类
USBH_RegisterClass(&hUsbHostFS, USBH_CDC_CLASS);
// 启动USB主机
USBH_Start(&hUsbHostFS);
}
// USB主机类回调函数
void USBH_USR_Callback(USBH_HandleTypeDef *phost, uint8_t id)
{
switch (id) {
case HOST_USER_CLASS_ACTIVE:
// 主机类激活
break;
case HOST_USER_CLASS_DEACTIVATED:
// 主机类反激活
break;
case HOST_USER_DISCONNECTION:
// 设备断开连接
break;
case HOST_USER_CONNECTION:
// 设备连接
break;
case HOST_USER_DEVICE_READY:
// 设备准备就绪
break;
case HOST_USER_DEVICE_NOT_READY:
// 设备未准备好
break;
case HOST_USER_DEVICE_UNSUPPORTED:
// 设备不支持
break;
case HOST_USER_CLASS_INIT_COMPLETE:
// 类初始化完成
break;
case HOST_USER_CLASS_DEINIT_COMPLETE:
// 类反初始化完成
break;
case HOST_USER experiencia_COMPLETE:
// 传输完成
break;
case HOST_USER experiencia_ABORT:
// 传输中止
break;
case HOST_USER experiencia_IN_PROGRESS:
// 传输进行中
break;
case HOST_USER experiencia_STALL:
// 传输停止
break;
case HOST_USER experiencia_NAK:
// 传输未确认
break;
case HOST_USER experiencia_ERROR:
// 传输错误
break;
case HOST_USER experiencia_TIMEOUT:
// 传输超时
break;
case HOST_USER_DEVICE_DESC_READY:
// 设备描述符准备好
break;
case HOST_USER_DEVICE_DESC_FAIL:
// 设备描述符获取失败
break;
case HOST_USER_CONFIGURATION_DESC_READY:
// 配置描述符准备好
break;
case HOST_USER_CONFIGURATION_DESC_FAIL:
// 配置描述符获取失败
break;
case HOST_USER_STRING_DESC_READY:
// 字符串描述符准备好
break;
case HOST_USER_STRING_DESC_FAIL:
// 字符串描述符获取失败
break;
case HOST_USER_CLASS_REQUEST:
// 类请求
break;
case HOST_USER_CLASS_REQUEST_FAIL:
// 类请求失败
break;
case HOST_USER_CLASS_REQUEST_COMPLETE:
// 类请求完成
break;
case HOST_USER_CLASS_REQUEST_NOSUPPORT:
// 类请求不支持
break;
case HOST_USER_CLASS_REQUEST_ABORT:
// 类请求中止
break;
case HOST_USER_DEVICE_SPEED:
// 设备速度
break;
case HOST_USER_DEVICE_ADDRESS:
// 设备地址
break;
case HOST_USER_DEVICE_DETACH:
// 设备断开
break;
case HOST_USER_DEVICE_ATTACH:
// 设备连接
break;
case HOST_USER_DEVICE_RESET:
// 设备重置
break;
case HOST_USER_DEVICE_SUSPEND:
// 设备挂起
break;
case HOST_USER_DEVICE_RESUME:
// 设备恢复
break;
case HOST_USER_DEVICE_LOW_SPEED:
// 低速设备
break;
case HOST_USER_DEVICE_HIGH_SPEED:
// 高速设备
break;
case HOST_USER_DEVICE_FULL_SPEED:
// 全速设备
break;
case HOST_USER_DEVICE_POWER:
// 设备电源状态
break;
case HOST_USER_DEVICE_LOW_POWER:
// 低功耗模式
break;
case HOST_USER_DEVICE_SOF:
// 帧开始
break;
case HOST_USER_DEVICE_SOF_DISABLE:
// 禁用帧开始
break;
case HOST_USER_DEVICE_ESOF:
// 帧结束
break;
}
}
// 主函数
int main(void)
{
// 系统初始化
HAL_Init();
// 配置时钟
SystemClock_Config();
// 初始化USB主机
MX_USB_Host_Init();
// 无限循环
while (1) {
// 处理USB主机事件
USBH_Process(&hUsbHostFS);
}
}
// 系统时钟配置函数
void SystemClock_Config(void)
{
// 配置系统时钟
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
// 配置HSE时钟
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 25;
RCC_OscInitStruct.PLL.PLLN = 432;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 9;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
Error_Handler();
}
// 配置系统时钟
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_7) != HAL_OK) {
Error_Handler();
}
}
// 错误处理函数
void Error_Handler(void)
{
// 处理错误
while (1) {
// 无限循环
}
}
STM32F7系列的USB接口非常灵活,支持多种传输模式和速率。通过STM32CubeMX工具和HAL库,可以方便地配置和使用USB接口,实现设备模式、主机模式和OTG模式的功能。以上示例代码展示了如何初始化USB接口、配置UART通信以及处理USB传输的各个阶段。希望这些示例能帮助你更好地理解和使用STM32F7系列的USB接口。