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
什么是RTK?GPS与RTK有什么区别
Hirth Engines 32系列空冷二冲程发动机
余承东:手机品牌的洗牌期加速 今年华为要做到全球第二
采用ARM9处理器和GPRS模块设计通用远程监测终端系统
FF曲线进入中国:借道睿驰汽车落地广州?
STM32单片机的usb上电和断电函数的定义
铜铝复合板冷轧复合法
苹果Vision Pro混合现实头显2月2日美发售,定价3499美元
基于ControlLogix PLC的水利工程自动化系统的实现
ATMEGA328芯片解密成功爱特梅尔单片机解密描述
用汽车USB端口给手机充电的好处和坏点
自动驾驶智能座舱的设计逻辑和发展模式
重磅!基于瑞芯微RK3588旗舰芯片打造的MinipcRK3588面世
汽车核心技术及零部件研发生产企业华培动力发布2022第一季度报告
如何进一步优化可实现显示屏的 LED 驱动器
如何搭建BIFACES+HighTec开发环境
气体检测仪的使用方法及注意事项
中电金信获软件测试成熟度模型集成(TMMi)三级水平认证
分布式节点的技术特点
使用键盘和LCD显示屏与MAXQ2000