历史上的今天

今天是:2024年10月30日(星期三)

正在发生

2020年10月30日 | STM32 usb_pwr.c文件分析

发布者:MysticalDreamer 来源: eefocus关键字:STM32  usb_pwr  文件分析 手机看文章 扫描二维码
随时随地手机看文章

usb_pwr.c 这个文件看文件名就知道跟功耗有关了,有很多的状态:上电、掉电、挂起、恢复。


当首先是usb的上电和断电函数的定义了。


usb上电函数如下:

/*******************************************************************************

* Function Name  : PowerOn

* Description    : 上电

* Input          : None.

* Output         : None.

* Return         : USB_SUCCESS.

*******************************************************************************/

RESULT PowerOn(void)

{

  u16 wRegVal;


  USB_Cable_Config(ENABLE); //接上上拉电阻

  wRegVal = CNTR_FRES; //设置强制复位

  _SetCNTR(wRegVal);

  wInterrupt_Mask = 0; //先禁止所有的中断

  _SetCNTR(wInterrupt_Mask);

  _SetISTR(0); //清除所有的中断标志

  wInterrupt_Mask = CNTR_RESETM | CNTR_SUSPM | CNTR_WKUPM;

  _SetCNTR(wInterrupt_Mask);//再打开复位中断、挂起中断、唤醒中断屏蔽位


  return USB_SUCCESS;

}


上电的过程是:

1、当然接上D+或D-的上啦电阻,让主机可以识别到USB;

2、配置USB控制寄存器CNTR,是USB强制复位

3、打开复位中断、挂起中断、唤醒中断,其他中断屏蔽位则关闭


接下去是断电的函数定义:

/*******************************************************************************

* Function Name  : PowerOff

* Description    : 掉电

* Input          : None.

* Output         : None.

* Return         : USB_SUCCESS.

*******************************************************************************/

RESULT PowerOff()

{

  /* disable all ints and force USB reset */

  _SetCNTR(CNTR_FRES); //设置强制复位

  _SetISTR(0); //清除所有的中断标志

  USB_Cable_Config(DISABLE); //断开上拉电阻

  _SetCNTR(CNTR_FRES + CNTR_PDWN); //设置强制复位,并且进入断电模式


  return USB_SUCCESS;

}


掉电的过程很简单,先强制复位USB,并清除所有的中断标志,断开上拉电阻,并设置控制进入断电模式。


挂起也是USB的一种状态,所谓的挂起起始就是进入低功耗状态,一般的事情我不响应,除非有重要的事情我才唤醒处理。

/*******************************************************************************

* Function Name  : Suspend

* Description    : 挂起

* Input          : None.

* Output         : None.

* Return         : USB_SUCCESS.

*******************************************************************************/

void Suspend(void)

{

  u16 wCNTR;


  wCNTR = _GetCNTR();    //读取控制寄存器的值

  wCNTR |= CNTR_FSUSP;    //添加强制挂起标志

  _SetCNTR(wCNTR);    //进入挂起模式

  wCNTR = _GetCNTR();    //读取控制寄存器的值

  wCNTR |= CNTR_LPMODE;    //添加低功耗标志

  _SetCNTR(wCNTR);    //进入低功耗模式


  Enter_LowPowerMode();    //进入低功耗模式


}


进入挂起状态的过程跟我们平时进入中断服务函数的过程很像,当然要保护现场了。所以usb进入挂起状态,不改变控制寄存器原来的值,只是在原来的上面添加了挂起状态和低功耗状态标志而已。


说到挂起,当然有恢复了。首先的讲Resume_Init()这个函数:

/*******************************************************************************

* Function Name  : Resume_Init

* Description    : 处理唤醒恢复的函数

* Input          : None.

* Output         : None.

* Return         : USB_SUCCESS.

*******************************************************************************/

void Resume_Init(void)

{

  u16 wCNTR;


  wCNTR = _GetCNTR();

  wCNTR &= (~CNTR_LPMODE);  

  _SetCNTR(wCNTR); //进入非低功耗模式

  Leave_LowPowerMode(); //离开低功耗模式

  _SetCNTR(IMR_MSK); //打开使能全部中断


}


这个就是唤醒的函数了,比较简单,但是比较难理解的是恢复的各个状态。

typedef enum _RESUME_STATE

{

  RESUME_EXTERNAL,

  RESUME_INTERNAL,

  RESUME_LATER,

  RESUME_WAIT,

  RESUME_START,

  RESUME_ON,

  RESUME_OFF,

  RESUME_ESOF

} RESUME_STATE;


恢复有这么多的状态变化,当然有理由理解下各个状态了。

RESUME_EXTERNAL:个人理解,就想硬件复位一样,是通过某个物理硬件唤醒USB的

RESUME_INTERNAL:这个状态的唤醒应该就是软件唤醒之类的,比如收到某个中断

RESUME_LATER:表示待会儿唤醒,当然这里涉及到一个定时过程,定时时间到了在开始恢复

RESUME_WAIT:这个状态表示正在等待定时过程的结束

RESUME_START:表示USB开始要进行恢复了

RESUME_ON:表示即将恢复,该状态保持1毫秒~15ms内有效,主机就会对USB模块进行唤醒操作

RESUME_OFF:表示已经恢复完成了

RESUME_ESOF:个人理解表示,收到ESOF中断标志时,USB不允许进入挂起状态


 

各个状态之间的转化如下代码:

/*******************************************************************************

* Function Name  : Resume

* Description    :这是状态机处理恢复操作和时序。控制是基于Resume结构变量和

*   ESOF中断调用该子程序没有改变机状态。控制恢复的状态

* Input          : a state machine value (RESUME_STATE)

*                  RESUME_ESOF doesn't change ResumeS.eState allowing

*                  decrementing of the ESOF counter in different states.

* Output         : None.

* Return         : None.

*******************************************************************************/

void Resume(RESUME_STATE eResumeSetVal)  

{

  u16 wCNTR;


  if (eResumeSetVal != RESUME_ESOF) //如果不是ESOF中断导致的

    ResumeS.eState = eResumeSetVal; //ResumeS.eState设置为自己设定的值


  switch (ResumeS.eState)

  {

    case RESUME_EXTERNAL: //RESUME_EXTERNAL 外部恢复

      Resume_Init();

      ResumeS.eState = RESUME_OFF;

      break;

    case RESUME_INTERNAL: //RESUME_INTERNAL 内部恢复

      Resume_Init();

      ResumeS.eState = RESUME_START;

      break;

    case RESUME_LATER: //RESUME_LATER 定时恢复

      ResumeS.bESOFcnt = 2;

      ResumeS.eState = RESUME_WAIT;

      break;

    case RESUME_WAIT: //RESUME_WAIT  等待计时结束

      ResumeS.bESOFcnt--;

      if (ResumeS.bESOFcnt == 0)

        ResumeS.eState = RESUME_START;

      break;

    case RESUME_START: //RESUME_START 开始恢复

      wCNTR = _GetCNTR();

      wCNTR |= CNTR_RESUME;

      _SetCNTR(wCNTR); //设置唤醒请求位,将向PC主机发送唤醒请求

      ResumeS.eState = RESUME_ON;

      ResumeS.bESOFcnt = 10; //定时10ms,如果在这点时间内保持有效,主机将对USB模块进行唤醒操作

      break;

    case RESUME_ON: //RESUME_ON

      ResumeS.bESOFcnt--; //计时中

      if (ResumeS.bESOFcnt == 0) //计时时间到了

      {

        wCNTR = _GetCNTR();

        wCNTR &= (~CNTR_RESUME); //清除唤醒请求标志位

        _SetCNTR(wCNTR);

        ResumeS.eState = RESUME_OFF;

      }

      break;

    case RESUME_OFF:      //RESUME_OFF

    case RESUME_ESOF:      //RESUME_ESOF

    default:

      ResumeS.eState = RESUME_OFF;

      break;

  }

}


明显可以看到个状态的转化过程:

1、RESUME_EXTERNAL->RESUME_OFF

2、RESUME_INTERNAL->RESUME_START->RESUME_ON->RESUME_OFF

3、RESUME_WAIT->RESUME_START-> RESUME_ON-> RESUME_OFF

4、RESUME_ESOF->RESUME_OFF


关键字:STM32  usb_pwr  文件分析 引用地址:STM32 usb_pwr.c文件分析

上一篇:STM32 usb_core.c分析
下一篇:STM32的CustomHID的各描述符介绍

推荐阅读

近年来,我国许多地方出现雾霾污染,而造成雾霾天气的原因中机动车尾气排放平均占到20%~25%,目前,每年全国机动车排放污染物达到5700万吨,包括,氮氧化合物、一氧化物、颗粒物,其中汽车排放的氮氧化合物和颗粒物超过85%,碳氢化合物和一氧化碳超过70%。此外,大约占汽车保有量不到20%的重型柴油车排放了60%左右的氮氧化合物。因而在全球能源和环境系统...
和上一篇AD7793类似,项目中也涉及到利用AD7745读取电容值,来测环境湿度。编写了基于MSP430的AD7745的硬件IIC驱动和模拟IIC驱动,分享给大家。AD7745硬件IIC驱动完整版下载链接:https://download.csdn.net/download/qq_42580947/11041942AD7745模拟IIC驱动完整版下载链接:https://download.csdn.net/download/qq_42580947/11041947PS:目前资源积分无法...
  对于指针式万用表的电阻档输出电压,基本上等于表内电池的电压。比如MF47型的Rx1~RX1K为1.5V、Rx10K为9V。MF10型R x1~R x10K为1.5V、R x 100K 15V。  但这些输出电压相同的档位,由于电路设计不同、内阻不一样,导致对外输出电流的能力不一样。档位越高电流越小。例如用Rx1档测量钨丝小灯泡会发光,而用Rx1K以上就不发光。但对于LED灯珠,由...
在一份财报文件中,苹果公司明确表示,它认为在游戏领域,自己与索尼、微软和任天堂之间的地位平起平坐,强调了它对其平台上的游戏有多重要。在周五的一份监管文件中,该公司表示其产品作为游戏平台与索尼、微软和任天堂等传统游戏公司竞争。之前的文档通常苹果只会说它与Google的Android和微软的Windows保持着竞争。  游戏现在是苹果的一个重...

史海拾趣

问答坊 | AI 解惑

PLD/FPGA新手入门

PLD是可编程逻辑器件(Programable Logic Device)的简称,FPGA是现场可编程门阵列(Field Programable Gate Array)的简称,两者的功能基本相同,只是实现原理略有不同,所以我们有时可以忽略这两者的区别,统称为可编程逻辑器件或PLD/FPGA。 &nbs ...…

查看全部问答∨

如何在一体机中调出输入法

我买了个导航的PND,但是是一体机,也就是远峰的SHELL,但我在这个SHELL下怎么都无法把输入法打开,而通过注册表把它的SHELL屏蔽了并进入桌面后,在我的程序里就可以把输入法打开.究竟是什么原因呢? 另外,在进入WINDOW桌面它的任务栏有输入法图 ...…

查看全部问答∨

2440串口工作问题

    请问一下,谁能说一下,为什么2440串口工作时要把 CPU总线模式 从快速总线模式转变为异步总线模式?什么时候要在什么模式?两种模式有什么区别》?…

查看全部问答∨

tc35接收短信 单片机接收不到新短信提示

设置是:       AT+CNMI=2,1 单片机接收的时候有时有新短信提示,有时没有新短信提示(没有提示的情况占大部分) 这是为什么? 请高人指点下  谢谢!~…

查看全部问答∨

作为一名测控专业的研究生,毕业后如何适应工作

   自己在研究生期间,做过一些电路设计,但对即将从事的系统设计工作的内容几乎没有丝毫经验!ARM系统电路硬件设计很难吗?如何提高我ARM系统设计能力?特别是传感器设计方面!    谢谢各位大侠啦!…

查看全部问答∨

tms320f2812

我现在看一个程序,在CMD文件中是这样定义的 RAML0       : origin = 0x008000, length = 0x001000   FLASHD      : origin = 0x3EC000, length = 0x004000 ramfuncs     &n ...…

查看全部问答∨

WINCE下MMU地址映射问题

目前在做bootloader 在汇编中要对mmu设置虚拟地址和物理地址的映射关系  我在OEMAddressTable是这样的 DCD     0x80000000, 0x33E00000, 2      ; 64 MB DRAM BANK 6      &nb ...…

查看全部问答∨

想在arm技术上有些成就

      现在学校里都是以比赛的形式来驱动学习的,而我想做的是做自己想做的事情 但这是很矛盾的,因学校里的资源是向比赛倾斜的。而自己又没有过多的金费 来做这些事情。。      我自己也很矛盾。 ...…

查看全部问答∨

PADS 经典教程

最近不得不开始学PADS 找了几本资料觉得应该会不错,所以在这跟大家一起分享下,可能论坛中也已经有了。…

查看全部问答∨
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved