• 正文
    • 1 USB遠(yuǎn)程睡眠喚醒要注意的幾個(gè)點(diǎn)
    • 2 MCU喚醒之后引起USB異常的幾個(gè)點(diǎn)
  • 推薦器件
  • 相關(guān)推薦
申請(qǐng)入駐 產(chǎn)業(yè)圖譜

踩坑記錄——USB鍵盤(pán)睡眠喚醒

2024/07/18
3649
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點(diǎn)資訊討論

前段時(shí)間我用一個(gè)國(guó)產(chǎn)MCU實(shí)現(xiàn)了雷蛇鍵盤(pán)的效果,按鍵支持十鍵無(wú)沖,RGB燈支持單控任意一個(gè)燈任意一種顏色,但是這個(gè)過(guò)程還是比較曲折的,原本以為鍵盤(pán)功能是最難搞的,低功耗處理是最簡(jiǎn)單的,沒(méi)想到前面這么順利,最后才翻車(chē)了,所以特意出一期記錄一下我踩過(guò)的坑。

1 USB遠(yuǎn)程睡眠喚醒要注意的幾個(gè)點(diǎn)

1、配置描述符(Configuration Descriptor)要打開(kāi)遠(yuǎn)程喚醒(Remote Wakeup)功能。

Configuration Descriptor

Offset Field Size Value Description remark
0 bLength 1 Number 以字節(jié)為單位的描述符大小 bLength以字節(jié)為單位的描述符大小(0x09)
1 bDescriptorType 1 Constant 配置描述符類(lèi)型 一般為CONFIGURATION (0x02)
2 wTotalLength 2 Number 配置返回的數(shù)據(jù)總長(zhǎng)度 包括該配置返回的所有描述符(配置、接口、端點(diǎn)、和專(zhuān)用的類(lèi)型或者專(zhuān)用的廠商描述符)的總長(zhǎng)度
3 bNumInterfaces 1 Number 配置支持的接口數(shù)量 最小值為0x01
4 bConfigurationValue 1 Number Get Configuration 和Set Configuration請(qǐng)求的配置值 必須為0x01或者更高值。取值為0的Set Configuration請(qǐng)求會(huì)使設(shè)備進(jìn)入未配置狀態(tài)(Not Configured state)
5 iConfiguration 1 Index 字符串描述符索引 若沒(méi)有字符串描述符,這個(gè)字段的值為0
6 bmAttributes 1 Bitmap 配置特性 Bit7: USB1.0協(xié)議中表示總線供電(Bus Powered),設(shè)置bit7=1表示由總線供電(Bus Powered),其他協(xié)議該位保留(Reserved),必須設(shè)置為1
Bit6: 自供電(Self-powered),bits6=1時(shí),設(shè)備自供電(Self-powered)
Bit5: 遠(yuǎn)程喚醒(Remote Wakeup),bit5=1時(shí),設(shè)備支持遠(yuǎn)程喚醒
Bit4…0: 未使用,保留,必須為0
7 bMaxPower 1 mA 設(shè)備從總線獲取的最大功耗 當(dāng)設(shè)備完全運(yùn)行時(shí),特定配置的USB設(shè)備從總線取得的最大功耗

bmAttributes屬性的Bit5要置1,這樣才能打開(kāi)遠(yuǎn)程喚醒(Remote Wakeup)功能,另外PC端也要在相應(yīng)的USB設(shè)備上打開(kāi)“允許此設(shè)備喚醒計(jì)算機(jī)(O)”。

在這里插入圖片描述

Configuration Descriptor 部分配置參考示例:

0x09,                   //bLength(9);               配置描述符
0x02,                   //bDescriptorType(Configuration);
0x29,0x00,              //wTotalLength(41);
0x01,                   //bNumInterfaces(1);
0x01,                   //bConfigurationValue(1);
0x00,                   //iConfiguration(0);
0xA0,                   //bmAttributes(BUSPower); //支持遠(yuǎn)程喚醒
0x32,                   //MaxPower(100mA);

2、USB的時(shí)鐘頻率不能低于48MHz且必須是48的倍數(shù)。

時(shí)鐘頻率要設(shè)對(duì),否則會(huì)導(dǎo)致通訊異常。這個(gè)點(diǎn)原本我是知道的,但沒(méi)想到的是MCU在進(jìn)入休眠之后自動(dòng)切換到了內(nèi)部時(shí)鐘,而且在喚醒之后沒(méi)有切換回來(lái),因此導(dǎo)致喚醒之后USB通訊異常。

所以,在上電初始化的時(shí)候以及休眠喚醒之后都需要配置好系統(tǒng)時(shí)鐘。

3、USB Device喚醒PC需要發(fā)送喚醒序列。

PC在進(jìn)入睡眠之后會(huì)主動(dòng)發(fā)送SetDeviceFeature,設(shè)備端收到以后進(jìn)入掛起狀態(tài)(SUSPend)并且USB進(jìn)入低功耗模式,如果設(shè)備需要喚醒PC的話則需要發(fā)送喚醒序列,先使用RESUME_INTERNAL喚醒設(shè)備本身,然后進(jìn)入遠(yuǎn)程喚醒狀態(tài)RESUME_START,遠(yuǎn)程喚醒的操作就是把USB控制寄存器的第4位置1,然后等待10ms把USB控制寄存器的第4位置為0,最后進(jìn)入RESUME_OFF狀態(tài),設(shè)備的一次遠(yuǎn)程喚醒請(qǐng)求完成。

注:USB總線由SUSPend狀態(tài)切換回CONFIGURED狀態(tài)實(shí)際上是由Host決定的,Device只能發(fā)送喚醒序列,然后等Host返回ClearFeature之后才能真正的喚醒USB,回到正常的CONFIGURED狀態(tài)

RESUME函數(shù)參考示例:

/*******************************************************************************
 * @fn       Resume
 *
 * @brief    This is the state machine handling resume operations and
 *                 timing sequence. The control is based on the Resume structure
 *                 variables and on the ESOF interrupt calling this subroutine
 *                 without changing machine state.
 *
 * @param    a state machine value (RESUME_STATE)
 *                  RESUME_ESOF doesn't change ResumeS.eState allowing
 *                  decrementing of the ESOF counter in different states.
 *
 * @return  None.
 */
void Resume(RESUME_STATE eResumeSetVal)
{
  uint16_t wCNTR;

  if (eResumeSetVal != RESUME_ESOF)
	{
   ResumeS.eState = eResumeSetVal;
	}
	
  switch (ResumeS.eState)
  {
    case RESUME_EXTERNAL:
      if (remotewakeupon ==0)
      {
        Resume_Init();
        ResumeS.eState = RESUME_OFF;
      }
      else 
      {
        ResumeS.eState = RESUME_ON;
      }
      break;
			
    case RESUME_INTERNAL:
      Resume_Init();
      ResumeS.eState = RESUME_START;
      remotewakeupon = 1;
      break;
		
    case RESUME_LATER:
      ResumeS.bESOFcnt = 2;
      ResumeS.eState = RESUME_WAIT;
      break;
		
    case RESUME_WAIT:
      ResumeS.bESOFcnt--;
      if (ResumeS.bESOFcnt == 0)
        ResumeS.eState = RESUME_START;
      break;
			
    case RESUME_START:
      wCNTR = _GetCNTR();
      wCNTR |= CNTR_RESUME;
      _SetCNTR(wCNTR);
      ResumeS.eState = RESUME_ON;
      ResumeS.bESOFcnt = 10;
      break;
		
    case RESUME_ON:    
      ResumeS.bESOFcnt--;
      if (ResumeS.bESOFcnt == 0)
      {
        wCNTR = _GetCNTR();
        wCNTR &= (~CNTR_RESUME);
        _SetCNTR(wCNTR);
        ResumeS.eState = RESUME_OFF;
        remotewakeupon = 0;
      }
      break;
			
    case RESUME_OFF:
			
    case RESUME_ESOF:
			
    default:
      ResumeS.eState = RESUME_OFF;
      break;
  }
}

2 MCU喚醒之后引起USB異常的幾個(gè)點(diǎn)

我在調(diào)試好鍵盤(pán)功能之后就開(kāi)始著手做MCU的休眠,但是在調(diào)試的過(guò)程中發(fā)現(xiàn)了一些新的問(wèn)題。

注:我用的MCU是ch32v203,這個(gè)MCU是一款國(guó)產(chǎn)IC,應(yīng)該是參考了stm32設(shè)計(jì)的,無(wú)論是硬件還是軟件都極其相似,因此,如果改用stm32或者其他stm32的替代方案可能也會(huì)有類(lèi)似的問(wèn)題。

1、不能在USB中斷服務(wù)函數(shù)里面讓MCU進(jìn)入休眠。

收到PC端傳過(guò)來(lái)的休眠信號(hào)之后,會(huì)進(jìn)USB中斷,然后進(jìn)入掛起狀態(tài)(SUSPend),我測(cè)試的時(shí)候圖方便直接在中斷里面讓MCU進(jìn)入了停機(jī)模式,結(jié)果MCU喚不醒了,可能是因?yàn)閱拘阎笠獜乃吣切写a繼續(xù)往后跑,但是因?yàn)樗呤窃谥袛喾?wù)函數(shù)里面的,喚醒之后進(jìn)不了這個(gè)中斷了,也就沒(méi)法繼續(xù)往下跑了。

2、睡眠之前要失能窗口看門(mén)狗。

這個(gè)問(wèn)題有點(diǎn)莫名其妙,窗口看門(mén)狗是掛在APB1時(shí)鐘上面的,MCU進(jìn)入休眠的時(shí)候會(huì)關(guān)閉APB1時(shí)鐘,所以看門(mén)狗是不會(huì)影響休眠和喚醒的,實(shí)際上也是MCU休眠和喚醒的功能也是正常的,休眠之前USB和看門(mén)狗也是正常的,但是如果休眠時(shí)不先關(guān)閉看門(mén)狗時(shí)鐘,喚醒之后就會(huì)出現(xiàn)USB通訊異常的情況,我一時(shí)間也沒(méi)搞懂是什么原因,唯一有關(guān)聯(lián)的是USB和看門(mén)狗都是掛在APB1下面的,有大神可以解答一下我的疑惑嗎?

3、MCU休眠只能選擇WFE,選擇WFI的話USB無(wú)法喚醒MCU。

普通外部中斷喚醒(EXTI0-15)不管用WFI還是WFE都是可以正常使用的,USB中斷(EXTI18)在MCU休眠之前也是可以正常使用,但是一旦MCU通過(guò)WFI進(jìn)入休眠之后,就無(wú)法通過(guò)USB中斷喚醒了,這個(gè)時(shí)候哪怕通過(guò)其他外部中斷喚醒了MCU,USB也還是無(wú)法恢復(fù)正常通訊。

如果是用WFE則沒(méi)有這個(gè)問(wèn)題,這就很奇怪了,中斷配置我也檢查過(guò)很多次了,并沒(méi)有發(fā)現(xiàn)什么問(wèn)題,最后沒(méi)辦法就只能用WFE了。

結(jié)束語(yǔ)

關(guān)于USB遠(yuǎn)程睡眠喚醒的坑就講到這,這里其實(shí)只是列舉了一部分,因?yàn)檫@只是總結(jié)我遇到的新坑,有些以前踩過(guò)的坑這里就沒(méi)寫(xiě)了,我也是第一次做USB的低功耗,沒(méi)想到會(huì)遇到這么多奇怪的問(wèn)題。雖然最后問(wèn)題都解決了,但是有些疑惑還是沒(méi)想明白,有大神知道的話還望不吝賜教!

推薦器件

更多器件
器件型號(hào) 數(shù)量 器件廠商 器件描述 數(shù)據(jù)手冊(cè) ECAD模型 風(fēng)險(xiǎn)等級(jí) 參考價(jià)格 更多信息
SN74LVC1G17DBVR 1 Rochester Electronics LLC Buffer,
$0.13 查看
SN74LVC1G07DCKTG4 1 Texas Instruments Single 1.65-V to 5.5-V buffer with open-drain outputs 5-SC70 -40 to 125

ECAD模型

下載ECAD模型
$1.61 查看
SN74LVC3G17DCUR 1 Rochester Electronics LLC LVC/LCX/Z SERIES, TRIPLE 1-INPUT NON-INVERT GATE, PDSO8, GREEN, PLASTIC, VSSOP-8
$0.53 查看

相關(guān)推薦