STM32
直播中

文甘翀

8年用户 1037经验值
私信 关注
[问答]

STM32H7使用HAL库如何控制外置USB HS PHY进入低功耗?

项目使用STM32H7的HAL库控制外置USB HS PHY(如USB3300或CH132)的。不知如何让MCU通过ULPI接口写寄存器让USB HS PHY进入低功耗,且USB保持链接状态让PC可以重新唤醒。

回帖(1)

打马过草原

2025-8-18 16:42:25

在STM32H7上使用HAL库控制外置USB HS PHY(如USB3300或CH132)进入低功耗状态(保持链接以支持PC唤醒),需通过ULPI接口操作PHY寄存器。以下是完整的实现步骤和示例代码:




核心步骤



  1. 配置ULPI接口:确保STM32H7的USB_OTG_HS控制器已正确初始化和ULPI接口使能。

  2. 操作PHY寄存器:通过ULPI接口写PHY寄存器,启用低功耗模式(如Suspend模式)。

  3. 唤醒配置:使能唤醒中断,确保PHY能检测到PC唤醒信号。

  4. 中断处理:在USB唤醒中断中恢复PHY状态。




代码实现


1. 初始化USB和PHY(关键配置)


#include "stm32h7xx_hal.h"
#include "usbh.h"  // 根据你的驱动选择

void MX_USB_OTG_HS_PHY_Init(void) {
  USB_OTG_GlobalTypeDef *USBx = USB_OTG_HS;

  // 使能ULPI时钟和PHY
  USBx->GCCFG |= USB_OTG_GCCFG_PHYHSEN; // 使能外部HS PHY
  USBx->GUSBCFG |= USB_OTG_GUSBCFG_ULPIEVBUSD; // 禁用VBUS监控(低功耗要求)
  HAL_Delay(10);
}

2. 进入低功耗模式(Suspend)


void Enter_USB_HS_PHY_LowPower(void) {
  // 步骤1: 通过ULPI写PHY寄存器(以USB3300为例)
  uint8_t func_ctrl_reg = 0x04; // 功能控制寄存器地址
  uint8_t suspend_cmd = 0x10;   // 设置bit4 (SUSPENDM) = 1

  // 写入ULPI寄存器(见下文ULPI写函数实现)
  USB_ULPI_Write(func_ctrl_reg, suspend_cmd);

  // 步骤2: 配置STM32唤醒检测
  USB_OTG_GlobalTypeDef *USBx = USB_OTG_HS;
  USBx->GINTMSK |= USB_OTG_GINTMSK_WUIM; // 使能唤醒中断
  USBx->GLPMCFG |= USB_OTG_GLPMCFG_LPMEN; // 使能LPM支持(可选)
}

3. ULPI寄存器写入函数


void USB_ULPI_Write(uint8_t reg_addr, uint8_t data) {
  USB_OTG_GlobalTypeDef *USBx = USB_OTG_HS;

  // 等待ULPI接口就绪
  while ((USBx->GOTGINT & USB_OTG_GOTGINT_ULPIInt) == 0);

  // 配置ULPI Viewport(寄存器访问模式)
  USBx->GOTGCTL |= USB_OTG_GOTGCTL_ULPIVM; // 启用Viewport
  USBx->GOTGCTL |= USB_OTG_GOTGCTL_ULPICSM; // 命令启动模式

  // 组合地址和数据(ULPI格式:Read/Write# + Address + Data)
  uint32_t ulpi_cmd = (0 << 7) | (reg_addr << 2) | data; // bit7=0表示写操作
  USBx->GOTGCTL = (USBx->GOTGCTL & ~0xFFFF) | ulpi_cmd;

  // 触发传输并等待完成
  USBx->GOTGCTL |= USB_OTG_GOTGCTL_ULPIEEN; // 启用传输
  while ((USBx->GOTGINT & USB_OTG_GOTGINT_ULPIInt) == 0);
  USBx->GOTGINT = USB_OTG_GOTGINT_ULPIInt; // 清除中断标志

  // 关闭Viewport
  USBx->GOTGCTL &= ~(USB_OTG_GOTGCTL_ULPIVM | USB_OTG_GOTGCTL_ULPICSM);
}

4. 唤醒中断处理


在USB中断服务例程(如OTG_HS_IRQHandler)中检测唤醒事件:


void OTG_HS_IRQHandler(void) {
  USB_OTG_GlobalTypeDef *USBx = USB_OTG_HS;

  if (USBx->GINTSTS & USB_OTG_GINTSTS_WKUINT) {
    // 步骤1: 清除唤醒中断标志
    USBx->GINTSTS = USB_OTG_GINTSTS_WKUINT;

    // 步骤2: 退出PHY低功耗模式
    uint8_t func_ctrl_reg = 0x04;
    uint8_t resume_cmd = 0x00; // SUSPENDM=0
    USB_ULPI_Write(func_ctrl_reg, resume_cmd);

    // 步骤3: 恢复USB时钟(如果之前关闭)
    __HAL_RCC_USB_OTG_HS_ULPI_CLK_ENABLE();

    // 步骤4: 通知应用层唤醒事件
    USB_Wakeup_Callback();
  }
  HAL_PCD_IRQHandler(&hpcd_USB_OTG_HS); // 继续处理其他中断
}

// 用户自定义唤醒回调
__weak void USB_Wakeup_Callback(void) {
  // 添加应用层唤醒处理代码
}



关键配置说明




  1. PHY寄存器设置



    • USB3300:写寄存器0x04(功能控制),设置SUSPENDM=1进入挂起模式。

    • CH132:参考其数据手册,通常类似(如寄存器0x01SUSPEND位)。




  2. STM32H7唤醒机制



    • 使能USB_OTG_GINTMSK_WUIM中断(唤醒中断掩码)。

    • PHY检测到PC唤醒信号(恢复信号)后,触发USB_OTG_GINTSTS_WKUINT中断。




  3. 低功耗硬件设计



    • 确保PHY的VBUS监控已禁用(避免漏电)。

    • 如果使用Stop模式,需保留USB时钟源(如HSE)。






注意事项



  1. PHY兼容性:不同PHY的寄存器地址可能不同,需查阅数据手册(如USB3300 DS00001692B, CH132 DS000757)。

  2. 时钟管理

    • 进入低功耗前,勿关闭ULPI时钟(USBPHYCHSE)。

    • 唤醒后检查时钟是否恢复。


  3. 中断优先级:确保USB中断优先级足够高(避免唤醒延迟)。

  4. 连接状态保持:在Suspend模式下,PHY自动维持USB连接。


通过以上步骤,USB HS PHY将在保持链接的状态下进入低功耗,PC可通过发送USB唤醒信号恢复设备。

举报

更多回帖

发帖
×
20
完善资料,
赚取积分