STM32 USB無法連接電腦

一、說明

在調試 STM32 USB device MSC 功能時,使用官方提供的庫和示例項目,電腦可以正確識別設備,也可以正常操作。但是將 USB 部分的代碼移植到自己的工程後,發現電腦無法正確識別設備,有時會在右下角顯示無法識別設備。

二、解決方法

在main.c中添加 hal_delay() 函數的實現方式。

在默認的模板工程裏,一般使用如下的方式實現延遲函數。


__weak uint32_t HAL_GetTick(void)
{
  return uwTick;
}

__weak void HAL_Delay(__IO uint32_t Delay)
{
  uint32_t tickstart = 0U;
  tickstart = HAL_GetTick();
  while((HAL_GetTick() - tickstart) < Delay)
  {
  }
}

而在 USB 項目中,需要使用如下的方式實現延時函數。

void HAL_Delay(__IO uint32_t Delay)
{
  while(Delay) 
  {
    if (SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk) 
    {
      Delay--;
    }
  }
}

這兩種方式都可以實現基本的延時功能,都是使用的 SysTick 定時器來實現,也都是使用 while() 來進行條件判斷,條件不滿足,即計時到了指定的延時後退出 while() 。區別在於,第一種方式,進行條件判斷的變量 uwTick 在 SysTick 的中斷函數中進行加一操作,即如下代碼:

__weak void HAL_IncTick(void)
{
  uwTick++;
}

void SysTick_Handler(void)
{
  HAL_IncTick();
}

而第二種方式,進行 while() 條件判斷的變量 Delay 是不依賴於 SysTick 中斷函數進行改變的,而是直接在這個函數中進行判斷,等待寄存器數值改變,延時 1ms 後,對 Delay 進行減一操作。

默認的實現方式依賴於 SysTick 中斷函數void SysTick_Handler(void),而在使用 USB 功能時,USB的操作本身就是需要在中斷函數 void OTG_FS_IRQHandler(void) 中進行的。可能由於對不同中斷函數的處理,導致了時間上的錯誤,從而電腦無法正確進行枚舉操作。

USB 部分是在 usbd_conf.c 文件中的 void USBD_LL_Delay(uint32_t Delay) 函數中進行延時函數的調用的,如下所示:

void USBD_LL_Delay(uint32_t Delay)
{
  HAL_Delay(Delay);
}

而且在底層的 USB 庫中,也有直接調用到hal_delay的,如下:
這裏寫圖片描述

2018.1.3修改

後來發現好像不是這個問題,不這樣修改也可以連接。講道理 SysTick 的中斷優先等級比 USB 的高,因此應該是不會受影響的。可是當時對比了兩個工程的代碼,好像也就這點區別。不過在官方庫中,都是使用第二種方式的。

發佈了119 篇原創文章 · 獲贊 302 · 訪問量 103萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章